graduate project report - · pdf filegraduate project report ... abstract— in this...

18
1 Graduate Project Report Student: Maryam Nezamabadi Ezell 01370072 Advising Professor: Dr. Mo Jamshidi Committee Member: Dr. Jeff Prevost Summer 2015 ECE Department UTSA

Upload: buitu

Post on 28-Mar-2018

223 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

1

Graduate Project Report

Student:

Maryam Nezamabadi Ezell

01370072

Advising Professor:

Dr. Mo Jamshidi

Committee Member:

Dr. Jeff Prevost

Summer 2015

ECE Department

UTSA

Page 2: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

2

Investigating the Use of an Evolutionary Algorithm and Geometric

Shapes in Approximating a Target Image for Compression in

Python

Maryam Nezamabadi Ezell

ECE Department

UTSA

[email protected]

Abstract— In this project, a method for lossless image compression has been developed. A number of random circles (or rectangles)

got created on a canvas and through a series of mutations of their parameters they approximated a gray-scale target image. An error

image got created by finding the difference between the target image and its approximation. The pixel values of this error image then

got compressed using Huffman Coding. The Huffman coded error image plus a file that contained the parameter values of the circles

that approximated the image, had a smaller size than the target image.

Keywords— Evolutionary Algorithms, Mutation, Hill Climbing, Huffman Coding, Image Compression, Parallel Processing, Python

I. INTRODUCTION

Image compression is minimizing the size in bytes of a graphics file without degrading the quality of the image to an unacceptable

level. The reduction in file size allows more images to be stored in a given amount of disk or memory space. It also reduces the

time required for images to be sent over the Internet or downloaded from Web pages. Image compression may be lossy or lossless.

lossless image compression means all the data from the original file is preserved. Lossy compression, on the other hand, removes

some data from the original file and saves the image with a reduced file size. This project is twofold. In the first part, it tries to

demonstrate the abilities of Evolutionary Algorithms in finding an optimum solution to a problem, by imitating a gray-scale image,

using a number of gray-scale circles (rectangles) and mutating their parameters, until the overall image gets close to the target

image. In the second part, the use of this circles (rectangles) image, in image compression and its effectiveness has been discussed.

Parts II through IV give brief introductions to the methods used in this project such as Evolutionary Algorithms, Parallel Processing

and Huffman Coding. In part V the project has been discussed in more detail with samples of the circle (rectangle) images, graphs

and the relevant data. In the last part the conclusion of this project and future work has been discussed. [1] [2]

II. EVOLUTAIONARY ALGORITHMS

In artificial intelligence, an evolutionary algorithm (EA) is a subset of evolutionary computation. A population of individuals exists

in an environment with limited resources. Competition for those resources causes selection of those fitter individuals that are better

adapted to the environment. These individuals act as seeds for the generation of new individuals through recombination and

mutation. The new individuals have their fitness evaluated and compete (possibly also with parents) for survival. Over time natural

selection causes a rise in the fitness of the population. EAs are stochastic, population-based algorithms. The operators

recombination and mutation, create the necessary diversity and thereby facilitate novelty, but selection reduces diversity and acts as

a force pushing quality. [3]

Page 3: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

3

A. Genetic Algorithm

Historically different flavors of EAs have been associated with different representations. For Binary strings, Genetic Algorithms

are used. The genetic algorithm is a method for solving both constrained and unconstrained optimization problems that is based on

natural selection. The genetic algorithm repeatedly modifies a population of individual solutions. At each step, the genetic

algorithm selects individuals at random from the current population to be parents and uses them to produce the children for the next

generation. Over successive generations, the population "evolves" toward an optimal solution. You can apply the genetic algorithm

to solve a variety of optimization problems that are not well suited for standard optimization algorithms, including problems in

which the objective function is discontinuous, non-differentiable, stochastic, or highly nonlinear. [3] [4]

B. Hill Climbing

In computer science, Hill Climbing is a mathematical optimization technique which belongs to the family of local search. It is an

iterative algorithm that starts with an arbitrary solution to a problem, then attempts to find a better solution by incrementally

changing a single element of the solution. If the change produces a better solution, an incremental change is made to the new

solution, repeating until no further improvements can be found. In Hill Climbing search, we select any local change that improves

the current value of the objective function. Hill Climbing is similar to Genetic Algorithm but only mutation is used to modify the

population. Traditionally, one would terminate Hill Climbing when no local move could further improve the objective function.

Upon termination, the search would have reached a local, but not necessarily global, optimum of the objective function. For many

optimization problems, such a local optimum is quite acceptable, since it often is a reasonable approximation of the global

optimum value. However, when a globally optimal solution is required, local optima present a serious problem for local search

methods. [5]

III. PARALLEL PROCESSING

Parallel Processing is the processing of program instructions by dividing them among multiple processors with the objective of

running a program in less time. To execute a program in parallel, you must have hardware with multiple processing elements so

concurrent tasks execute in parallel. The idle time of processor cycles across network can be used effectively by sophisticated

distributed computing software. The term parallel processing is used to represent a large class of techniques which are used to

provide simultaneous data processing tasks for the purpose of increasing the computational speed of a computer system. [6] [7] [8]

IV. HUFFMAN CODING

Huffman Coding is a lossless data compression algorithm. The idea is to assign variable-length codes to input characters. The

lengths of the assigned codes are based on the frequencies of corresponding characters. The most frequent character gets the

smallest code and the least frequent character gets the largest code. The variable-length codes assigned to input characters are

Prefix Codes, meaning the codes (bit sequences) are assigned in such a way that the code assigned to one character is not prefix of

the code assigned to any other character. This is how Huffman Coding makes sure that there is no ambiguity when decoding the

generated bit stream.. [9]

Page 4: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

4

V. PROJECT DESCRIPTION

In this project an experiment has been run to demonstrate the capabilities of Evolutionary Algorithms, and also the use of such

algorithms has been investigated in image compression.

A certain number of random gray scale circles (or rectangles) got created, and through a series of mutations to their parameters,

they approximated a gray-scale target image. The difference between the pixel values of this approximate image and the target

image was then found (error image). Huffman Coding was used to encode the pixel values of the error image. The Huffman coded

error image got bundled up with a text file that contained the parameter values of the circles that had approximated the image. This

bundle had a smaller size than the original bitmap image.

The idea is that on the user end, an algorithm reconstructs the target image by using the circle parameters to recreate the circles

image, decode the Huffman encoded error image, and add it to the circles image.

The number of the random circles is arbitrary, but by trial and error, 200 to 500 circles seem to do a relatively good approximation

of the target image. The quality of the approximation also depends on how detailed the target image is. Images with less detail are

better approximated and their evolution takes a shorter time.

The circle parameters that got mutated were the position of the circles on the canvas (x,y), radius, gray-scale color, the order the

circles appeared on the canvas, and their level of transparency (α).

At each iteration, one of these parameters (of one circle) got mutated, and then the mutated circles image got compared to the target

image (fitness evaluated). If the fitness of the newly mutated image was better than that of the previous image, it would replace the

previous image, but if not, the previous circles image would get passed on to the next iteration.

The code was run for 250K, 500K, 750K and one million iterations, and the results were compared. Although running the code for

more iterations produced better results (better fitness values), the visual improvement of the resulting images was not too

significant after 250K iterations, and running the code for more iterations was computationally expensive. By trial and error, it has

been concluded that an approximation after 250K iterations is good enough for our purposes.

In our quest for getting more detailed approximate images in less time, parallel processing was used. In parallel processing, the

target image got divided into 4 equally sized images, and each image section got sent to a separate process to get approximated by

evolving circles (rectangles), and once the evolution of all the 4 separate parts was done, the approximate image portions got

collected and reattached to create an approximation of the whole target image.

The results were much better this time as more circles had been used, and the evolution of the circles (rectangles) image happened

in a much shorter time. But in the end, the results of this parallel processed image approximation were not used. The reason for that

was that 500 circles were used for each image portion, so the total number of circles for the entire image was 2000 circles. The

parameters of 2000 circles saved in a text file, made the file large enough that it didn’t make using this method as an image

compression method feasible. But the resulting image is good to demonstrate the capabilities of evolutionary algorithms.

Compression

After all iterations were done and the approximate image had been created, the error image was generated by finding the difference

between the target image (Chaplin) and the circles (rectangles) image. Huffman Coding was used to encode the pixel values of the

error image for compression. The error image which was a 512X619 bitmap image had 316,928 pixel values. After using Huffman

Coding, the number of values had been reduced to 511 values in the binary format and each value had a weight (number of

occurrences). To store the data, we needed to store the Symbols and the weights as well as the Huffman codes. The number of the

bits of the Huffman code was equal to 2,174,086. We divided it first by 8 and then by 1024. So the Huffman coded values required

265.39 KB to be stored in a binary file.

Page 5: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

5

There were 511 weight values, and the values were between 1 and 13,199. Log 2 of 511 is close to 9. So we needed 511 X 9= 0.56

KB to store the weights. And there were 511 symbols between -255 and 255. Log 2 of 511 is close to 9. So we needed 511 X 9 =

0.56 KB to store the symbols. And we also needed to include the circles image to reconstruct the original image using the circles

image and the error image. Instead of including the circles image itself, we included the circles parameters in a text file. This way

the circles image could be reconstructed using the parameters before it was added to the error image. The circles parameters file,

had a size of 14KB. So the total was 265.39 + 0.56 + 0.56 + 14 = 280.51 KB which is less than 311KB, the size of the original

image.

So we have successfully compressed the image to a smaller size using this method, and it also has the advantage of being a lossless

method, as we didn’t need to eliminate any image data to compress it. The compressed image is about 10% reduced in size. With

image compression formats such as JPEG and PNG we can compress the image much more, but at the price of losing some of the

data as they are lossy methods.

Fig 1. Target image

Page 6: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

6

(a) (b)

Fig 2. (a) 500 randomly generated gray scale circles. (b) The approximation of the target image after one million iterations

(a) (b)

Fig 3. (a) 500 randomly generated gray scale rectangles. (b) The approximation of the target image after 250,000 iterations

Page 7: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

7

Fig 4. The fitness values for 50,000 iterations and 500 circles with the Chaplin image as target. The fitness values significantly

improved during the first 5000 or so generations, but slowed down after that. As can be seen, sometimes there is a spike in the

fitness graph as some later fitness values may be worse than the earlier ones, but the code quickly compensated for them and the

fitness values eventually got smaller (smaller fitness values are better).

Page 8: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

8

Fig 5. The fitness values for 50,000 iterations and 500 rectangles with the Chaplin image as target.

Fig 6. The Half image and the mutated circles image using parallelization. The four image segments were attached together after

all four processes were done. As can be seen, an image with less detail is approximated more effectively and in shorter time.

Page 9: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

9

Fig 7. The mutated circles Chaplin image using parallelization. The four image segments reattached after all four processes were

done. 500 circles were used in each segment and each segment evolved for 250,000 generations.

Fig 8. The histogram of the pixel values of the Chaplin image

Page 10: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

10

Fig 9. The histogram of the pixel values of the error image (the difference between the Chaplin image and the approximated

image) for 500 circles. These values were used in Huffman coding

Fig 10. (a) The circles error image. (b) The rectangles error image

Page 11: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

11

CONCLUSION

In this project the capabilities of evolutionary algorithms have been investigated. The results demonstrate that an Evolutionary

Algorithm such as Hill Climbing can be used to mimic a gray-scale image to a reasonable degree, using random geometric shapes

such as circles. Also, the use of such algorithm has been investigated in image compression. The results demonstrate that this

algorithm combined with Huffman Coding can be used to compress gray-scale bitmap images in a lossless format. Future work

will include improving this method to achieve better compression results, trying the cross over element of Genetic Algorithms in

combination with mutation to improve the circles (rectangles) population, and developing the code for compression of non-gray-

scale images.

REFERENCES

[1] http://whatis.techtarget.com/definition/image-compression

[2] http://www.noupe.com/design/everything-you-need-to-know-about-image-compression.html

[3] Lecture Notes, A.E. Eiben and J. E. Smith, Introduction to Evolutionary Computing, Chapter 2, What is an Evolutionary Algorithm?

[4] http://www.mathworks.com/help/gads/what-is-the-genetic-algorithm.html

[5] Bart Selman, Carla P Gomes, Hill-Climbing Search, P 334, Cornell University, Ithaca, NY

[6] http://searchdatacenter.techtarget.com/definition/parallel-processing

[7] https://software.intel.com/en-us/articles/how-to-sound-like-a-parallel-programming-expert-part-1-introducing-concurrency-and-parallelism/

[8] https://en.wikipedia.org/wiki/Parallel_processing

[9] http://www.geeksforgeeks.org/greedy-algorithms-set-3-huffman-coding/

[10] http://www.petercollingridge.co.uk/evolving-images

[11] http://paddy3118.blogspot.com/2009/03/huffman-encoding-in-python.html

APPENDIX

# Main code

# This code generates 500 random circles and evolve them for 250,000 generations so

they can mimic the target image

import pygame

import random

import numpy

import time

from PIL import Image

import os.path

from Fitness import fit

from MutateOrder import mutation

from GenerateCircles import generate

from MutatePosition import position

from MutateRadius import rad

from MutateColor import ccolor

from MutateAlpha import trans

import pygame.locals

import matplotlib.pyplot as plt

Page 12: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

12

start_time = time.time()

WIDTH = 512

HEIGHT = 619

THICKNESS = 0

d = (HEIGHT)*1/6

WHITE = (255,255,255)

genome = []

bestFit = []

bestMutation = []

bestIndex = []

bestDif = []

DISPLAY = (1, 1)

DEPTH = 32

FLAGS = 0

num = 500

iter = 250000

fitness = numpy.zeros((1,iter+1))

t= numpy.zeros((1,iter+1))

pygame.init()

def circle_drawing(surf):

for i in range(1,num+1):

r = random.randint(0,d)

x = random.randint(0,WIDTH)

y = random.randint(0,HEIGHT)

alfa = random.randint(0,255)

color1 = random.randint(0,255)

color = (color1,color1,color1)

# the genome vector

genome[((i-1)+(i-1)*5):((i+4)+(i-1)*5)] = [x,y,i,r,color1,alfa]

surf2 = pygame.Surface((r*2,r*2))

surf2.fill(WHITE)

surf2.set_colorkey(WHITE)

pygame.draw.circle(surf2, color, (r,r), r, THICKNESS)

surf2.set_alpha(alfa)

surf.blit(surf2, (x-r,y-r))

pygame.display.flip()

return surf

screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)

work_surface = pygame.Surface((WIDTH,HEIGHT))

work_surface.fill(WHITE)

ws = circle_drawing(work_surface.copy())

Page 13: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

13

pygame.image.save(ws, "circles_0.bmp")

# the original genome gets saved as a numpy array, then reshaped into a 2-D 50x6 array

genomeArr = numpy.asarray(genome)

genomeArr.shape = (num,6)

# saving the first array of randomly generated circles in originalGenomeArr

originalGenomeArr = genomeArr.copy()

# the image of the circles (the original genome)gets converted into a numpy array

# this is done so we can subtract its elements from the target image and calculate

fitness

circles = Image.open("circles_0.bmp").convert('L')

circlesArr = numpy.asarray(circles)

# The target image converted into a numpy array

im = Image.open("chaplin.bmp")

arr = numpy.asarray(im)

if os.path.isfile('FitVals1.txt'):

os.remove('FitVals1.txt')

if os.path.isfile('FitVals1.py'):

os.remove('FitVals1.py')

# subtracting the original genome array from the target image array

# then calculating the fitness

fitness[0,0] = fit(arr,circlesArr,WIDTH,HEIGHT)

fitValsTx_handle = file('FitVals1.txt','a')

fitValsPy_handle = file('FitVals1.py','a')

numpy.savetxt(fitValsTx_handle,numpy.array(fitness[0,0]).reshape(1,),fmt='%10.4f',deli

miter='\n')

numpy.savetxt(fitValsPy_handle,numpy.array(fitness[0,0]).reshape(1,),fmt='%10.4f',deli

miter='\n')

fitValsTx_handle.close()

fitValsPy_handle.close()

for j in range(0,iter,5):

fitValsTx_handle = file('FitVals1.txt','a')

fitValsPy_handle = file('FitVals1.py','a')

# mutating the order in which the circles are drawn

mutated = mutation(genomeArr.copy(),num).copy()

mutatedCircles = generate(mutated.copy(),work_surface.copy(),num).copy()

fitness[0,j+1] = fit(arr,mutatedCircles.copy(),WIDTH,HEIGHT)

numpy.savetxt(fitValsTx_handle,numpy.array(fitness[0,j+1]).reshape(1,),fmt='%10.4f',de

limiter='\n')

numpy.savetxt(fitValsPy_handle,numpy.array(fitness[0,j+1]).reshape(1,),fmt='%10.4f',de

limiter='\n')

dif1 = fitness[0,j] - fitness[0,j+1]

Page 14: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

14

if dif1 >= 20:

bestFit.append(fitness[0,j+1])

bestIndex.append(j+1)

bestDif.append(dif1)

bestMutation.append(mutated.copy())

if fitness[0,j+1] < fitness[0,j]:

genomeArr = mutated.copy()

# mutating the position

mposition = position(genomeArr.copy(),WIDTH,HEIGHT,num).copy()

mutatedCircles = generate(mposition.copy(),work_surface.copy(),num).copy()

fitness[0,j+2] = fit(arr,mutatedCircles.copy(),WIDTH,HEIGHT)

numpy.savetxt(fitValsTx_handle,numpy.array(fitness[0,j+2]).reshape(1,),fmt='%10.4f',de

limiter='\n')

numpy.savetxt(fitValsPy_handle,numpy.array(fitness[0,j+2]).reshape(1,),fmt='%10.4f',de

limiter='\n')

dif2 = fitness[0,j+1] - fitness[0,j+2]

if dif2 >= 20:

bestFit.append(fitness[0,j+2])

bestIndex.append(j+2)

bestDif.append(dif2)

bestMutation.append(mposition.copy())

if fitness[0,j+2] < fitness[0,j+1]:

genomeArr = mposition.copy()

# mutating the radius

mrad = rad(genomeArr.copy(),HEIGHT,num).copy()

mutatedCircles = generate(mrad.copy(),work_surface.copy(),num).copy()

fitness[0,j+3] = fit(arr,mutatedCircles.copy(),WIDTH,HEIGHT)

numpy.savetxt(fitValsTx_handle,numpy.array(fitness[0,j+3]).reshape(1,),fmt='%10.4f',de

limiter='\n')

numpy.savetxt(fitValsPy_handle,numpy.array(fitness[0,j+3]).reshape(1,),fmt='%10.4f',de

limiter='\n')

dif3 = fitness[0,j+2] - fitness[0,j+3]

if dif3 >= 20:

bestFit.append(fitness[0,j+3])

bestIndex.append(j+3)

bestDif.append(dif3)

bestMutation.append(mrad.copy())

if fitness[0,j+3] < fitness[0,j+2]:

genomeArr = mrad.copy()

# mutating the color

mcolor = ccolor(genomeArr.copy(),num).copy()

mutatedCircles = generate(mcolor.copy(),work_surface.copy(),num).copy()

fitness[0,j+4] = fit(arr,mutatedCircles.copy(),WIDTH,HEIGHT)

numpy.savetxt(fitValsTx_handle,numpy.array(fitness[0,j+4]).reshape(1,),fmt='%10.4f',de

limiter='\n')

numpy.savetxt(fitValsPy_handle,numpy.array(fitness[0,j+4]).reshape(1,),fmt='%10.4f',de

limiter='\n')

Page 15: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

15

dif4 = fitness[0,j+3] - fitness[0,j+4]

if dif4 >= 20:

bestFit.append(fitness[0,j+4])

bestIndex.append(j+4)

bestDif.append(dif4)

bestMutation.append(mcolor.copy())

if fitness[0,j+4] < fitness[0,j+3]:

genomeArr = mcolor.copy()

# mutating the transparency

mtrans = trans(genomeArr.copy(),num).copy()

mutatedCircles = generate(mtrans.copy(),work_surface.copy(),num).copy()

fitness[0,j+5] = fit(arr,mutatedCircles.copy(),WIDTH,HEIGHT)

numpy.savetxt(fitValsTx_handle,numpy.array(fitness[0,j+5]).reshape(1,),fmt='%10.4f',de

limiter='\n')

numpy.savetxt(fitValsPy_handle,numpy.array(fitness[0,j+5]).reshape(1,),fmt='%10.4f',de

limiter='\n')

dif5 = fitness[0,j+4] - fitness[0,j+5]

if dif5 >= 20:

bestFit.append(fitness[0,j+5])

bestIndex.append(j+5)

bestDif.append(dif5)

bestMutation.append(mtrans.copy())

if fitness[0,j+5] < fitness[0,j+4]:

genomeArr = mtrans.copy()

fitValsTx_handle.close()

fitValsPy_handle.close()

numpy.savetxt('genomeArr1.txt', genomeArr,fmt='%d', delimiter='\n')

print "This is the end of iteration ", j, ' for circles ', "\n"

if not len(bestDif)==0:

numpy.savetxt('BestDif1.txt',bestDif,fmt='%10.4f',delimiter='\n')

numpy.savetxt('BestDif1.py',bestDif,fmt='%10.4f',delimiter='\n')

if not len(bestFit)==0:

numpy.savetxt('BestFitness1.txt',bestFit,fmt='%10.4f',delimiter='\n')

numpy.savetxt('BestFitness1.py',bestFit,fmt='%10.4f',delimiter='\n')

if not len(bestIndex)==0:

numpy.savetxt('BestIndex1.txt',bestIndex,fmt='%d',delimiter='\n')

numpy.savetxt('BestIndex1.py',bestIndex,fmt='%d',delimiter='\n')

fitnessSorted = numpy.sort(fitness)

numpy.savetxt('FitValsSorted1.txt',fitnessSorted,fmt='%10.4f',delimiter='\n')

numpy.savetxt('FitValsSorted1.py',fitnessSorted,fmt='%10.4f',delimiter='\n')

for i in range(0,iter+1):

t[0,i] = i

Page 16: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

16

plt.plot(t, fitness, 'ro')

plt.axis([0, fitness.size, 0, fitnessSorted[0,iter]+200])

plt.xlabel('Generation for x = 1')

plt.ylabel('Fitness Value for x = 1')

NameFig = 'fitnessCircs.png'

plt.savefig(NameFig, bbox_inches='tight')

print("\n --- %s seconds ---" % round(time.time() - start_time,2))

pygame.quit()

######################################################################################

# Huffman Encode, Decode and graphing Histograms

from heapq import heappush, heappop, heapify

from PIL import Image

import numpy

import pylab as P

WIDTH = 512

HEIGHT = 619

imgconcat = []

huffCode = []

error = numpy.zeros((HEIGHT,WIDTH))

im1 = Image.open("chaplin.bmp")

IOF = numpy.asarray(im1)

IO = IOF.astype('float')

im1flat = IO.copy()

im1flat.shape = (HEIGHT*WIDTH)

im2 = Image.open("circles_2.bmp").convert('L')

ICF = numpy.asanyarray(im2)

IC = ICF.astype('float')

for i in range(0,HEIGHT):

for j in range(0,WIDTH):

error[i,j] = IO[i,j] - IC[i,j]

error2 = error.astype(numpy.int8)

im = Image.fromarray(error2,'L')

im.save("Error.bmp")

errflat = error.copy()

errflat.shape = (HEIGHT*WIDTH)

text_file2 = open("errflat.txt", "w")

text_file2.write(errflat)

Page 17: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

17

text_file2.close()

errflat2 = errflat.copy()

errflat2 = errflat2.astype(numpy.int8)

for k in range(0,errflat2.size):

imgconcat.append(str(errflat2[k]))

# placeholder

decode = lambda : None

def codecreate(symbol2weights, tutor= False):

''' Huffman encode the given dict mapping symbols to weights '''

global decode

heap = [ [float(wt), [[sym, []]], repr(sym)] for sym, wt in

symbol2weights.iteritems() ]

heapify(heap)

#if tutor: print "ENCODING:", sorted(symbol2weights.iteritems())

while len(heap) >1:

lo = heappop(heap)

hi = heappop(heap)

#if tutor: print " COMBINING:", lo, '\n AND:', hi

for i in lo[1]: i[1].insert(0, '0')

for i in hi[1]: i[1].insert(0, '1')

lohi = [ lo[0] + hi[0] ] + [lo[1] + hi[1]]

lohi.append('(%s if nextbit() else %s)' % (hi[2], lo[2]))

#if tutor: print " PRODUCING:", lohi, '\n'

heappush(heap, lohi)

wt, codes, decoder = heappop(heap)

decode = eval('lambda :' + decoder, globals())

decode.__doc__ = decoder

for i in codes: i[1] = ''.join(i[1])

#for i in codes: i[::] = i[:2]

return sorted(codes, key=lambda x: (len(x[-1]), x))

if 1:

tutor = True

astring = imgconcat

symbol2weights = dict((ch, astring.count(ch)) for ch in set(astring)) # for

astring

else:

tutor = False

huff = codecreate(symbol2weights, tutor= tutor)

print "\nSYMBOL\tWEIGHT\tHUFFMAN CODE"

sequencecount = 0

for h in huff:

sequencecount = sequencecount + symbol2weights[h[0]]

huffCode.append(str(h[1]))

print "%s\t%s\t%s" % (h[0], symbol2weights[h[0]], h[1])

Page 18: Graduate Project Report - · PDF fileGraduate Project Report ... Abstract— In this project, a method for lossless image compression has ... In parallel processing, the target image

18

# encode-decode check

symbol2code = dict(huff)

symbols, weights = zip(*symbol2weights.iteritems())

# normalize weights

weights = [float(wt) for wt in weights]

tot = sum(weights)

weights = [wt/tot for wt in weights]

symbolsequence = list(astring)

# encode

bitsequence = ''.join(symbol2code[sym] for sym in symbolsequence)

Binsequence = ''.join(format(x, 'b') for x in bytearray(bitsequence))

sslen, slen, blen = len(symbolsequence), len(symbols), len(bitsequence)

countlen = len(bin(slen-1)[2:])

text_file = open("BitSequence.txt", "w")

text_file.write(bitsequence)

text_file.close()

with open('BitSequence.txt','r') as f:

txt = f.read()

# decode

nextbit = (bit=='1' for bit in txt).next

decoded = []

try:

while 1:

decoded.append(decode())

except StopIteration:

pass

print "Comparing the decoded sequence with the original I get:", decoded ==

symbolsequence

# Splitting the characters of bitsequence

SplitBit = list(bitsequence)

SeqLen = len(SplitBit)

print 'The number of bits in the Huffman coded error image is: ', SeqLen

P.figure()

n, bins, patches = P.hist(errflat, 50, normed=1, histtype='bar')

P.xlabel('pixel values')

P.title('Error pixel value histogram')

P.figure()

n, bins, patches = P.hist(im1flat, 50, normed=1, histtype='bar')

P.xlabel('pixel values')

P.title('Original image pixel value histogram')

P.show()