20070454

10
CS101 Documentation for Homework 2 20070454 Seung Ho Yang As the second homework did not have a specific framework within which it was supposed to work my objective was to make my programs as general-purpose as possible. I set up very unusual circumstances with various problems that may break the program and found ways (or at least attempte d) to go around those obstacles. The first task I tackled was of course the concatenation problem. This was pretty straightforward as all I had to do was determine the size of the resultant image and draw it pixel by pixel utilizing two sets of doubly nested for loops, one for each image to be concatenated. As it stands the program works in the aforementioned obvious way. if direction=="h": width = w1 + w2 if h1 > h2: height = h1 else: height = h2 else: height = h1 + h2 if w1 > w2: width = w1 else: width = w2 concat_img = create_picture( width, height, white ) if direction=="h": for x in range(w1): for y in range(h1): concat_img.set(x,y,img1.get(x,y)) for x in range(w2): for y in range(h2): concat_img.set(x+w1,y,img2.get(x,y)) else: for y in range(h1): for x in range(w1): concat_img.set(x,y,img1.get(x,y)) for y in range(h2): for x in range(w2): concat_img.set(x,y+h1,img2.get(x,y))  The results of the program are as obvious as the coding itself. It is clear that the algorithm is working as intended.

Upload: seungho-yang

Post on 08-Apr-2018

218 views

Category:

Documents


0 download

TRANSCRIPT

8/7/2019 20070454

http://slidepdf.com/reader/full/20070454 1/10

CS101

Documentation for Homework 2

20070454 Seung Ho Yang

As the second homework did not have a specific framework within which it was

supposed to work my objective was to make my programs as general-purpose as

possible. I set up very unusual circumstances with various problems that may break the

program and found ways (or at least attempted) to go around those obstacles.

The first task I tackled was of course the concatenation problem. This was

pretty straightforward as all I had to do was determine the size of the resultant image

and draw it pixel by pixel utilizing two sets of doubly nested for loops, one for each

image to be concatenated. As it stands the program works in the aforementioned

obvious way.

if direction=="h":

width = w1 + w2

if h1 > h2:

height = h1

else:

height = h2

else:

height = h1 + h2

if w1 > w2:

width = w1

else:

width = w2

concat_img = create_picture( width, height, white )

if direction=="h":

for x in range(w1):

for y in range(h1):

concat_img.set(x,y,img1.get(x,y))

for x in range(w2):

for y in range(h2):

concat_img.set(x+w1,y,img2.get(x,y))

else:

for y in range(h1):

for x in range(w1):

concat_img.set(x,y,img1.get(x,y))

for y in range(h2):for x in range(w2):

concat_img.set(x,y+h1,img2.get(x,y)) 

The results of the program are as obvious as the coding itself. It is clear that

the algorithm is working as intended.

8/7/2019 20070454

http://slidepdf.com/reader/full/20070454 2/10

-------------------------  

| CS101 Image Processor |

-------------------------  

| 1. Concatenate |

| 2. Detect |

| 3. Segment |

| 4. Quit |

-------------------------  

Select : 1

Enter the 1st image name to concatenate : iu.jpg 

Enter the 2nd image name to concatenate : kara.jpg 

Enter the direction of concatenation (h or v) : v  

8/7/2019 20070454

http://slidepdf.com/reader/full/20070454 3/10

 

-------------------------  

| CS101 Image Processor |-------------------------  

| 1. Concatenate |

| 2. Detect |

| 3. Segment |

| 4. Quit |

-------------------------  

Select : 1

Enter the 1st image name to concatenate : Circus_Live_london.jpg 

Enter the 2nd image name to concatenate : Circus_Boston.jpg 

8/7/2019 20070454

http://slidepdf.com/reader/full/20070454 4/10

Enter the direction of concatenation (h or v) : h

A superb specimen of the female human form, courtesy of Mrs. Britney Spears

(divorced).

And yes, I agree her singing is NOT superb, but her body is, right?

Next stop is the detect task. The first thought that came to my mind when

looking at this problem was to simply for-loop the search space and whenever I hit apixel identical to obj_img.get(0,0) run a function checking I did indeed hit the mother lode;

however I realized that doing this would be hellishly inefficient if there were many cases

of identical pixels (if this was so the multiple instances of checks happening would slow

the program down to a crawl) so I wrote two functions- a light one that would run

first and check the four corners of the c hit aread , and a heavier one that follows the

first and checks the entire region for identity.

def detect_chkinit( inimg, objimg, x, y ):

8/7/2019 20070454

http://slidepdf.com/reader/full/20070454 5/10

inimg_w, inimg_h = inimg.size()

objimg_w, objimg_h = objimg.size()

if (inimg_w -x)<objimg_w:

return False

elif (inimg_h-y)<objimg_h:

return False

else:

if not inimg.get(x+objimg_w -1,y)==objimg.get(objimg_w -1,0):

return False

elif not inimg.get(x,y+objimg_h-1)==objimg.get(0,objimg_h-1):

return False

elif not inimg.get(x+objimg_w -1,y+objimg_h-1)==objimg.get(objimg_w -1,objimg_h-1):

return False

else:

return True

def detect_chk( inimg, objimg, x, y ):

inimg_w, inimg_h = inimg.size()

objimg_w, objimg_h = objimg.size()result=True

for bx in range(objimg_w):

for by in range(objimg_h):

if not inimg.get(x+bx,y+by)==objimg.get(bx,by):

result=False

break 

return result

Now that a region containing the detect object has been pinpointed, we need to

frame it in green. I decided on using two for-loops, one for each axis, and coloring the

inner two pixels of the region in green.

def detect_gotcha( inimg, objimg, x, y):

inimg_w, inimg_h = inimg.size()

objimg_w, objimg_h = objimg.size()

for cx in range(objimg_w):

inimg.set(x+cx,y,green)

inimg.set(x+cx,y+1,green)

inimg.set(x+cx,y+objimg_h-1,green)

inimg.set(x+cx,y+objimg_h-2,green)

for cy in range(objimg_h):

inimg.set(x,y+cy,green)

inimg.set(x+1,y+cy,green)

inimg.set(x+objimg_w -1,y+cy,green)

inimg.set(x+objimg_w -2,y+cy,green)

return inimg 

All this comes together in the detect() method.

for tx in range(img_w):

for ty in range(img_h):

if det_img.get(tx,ty)==obj_img.get(0,0):

if detect_chkinit(det_img,obj_img,tx,ty):

if detect_chk(det_img,obj_img,tx,ty):

8/7/2019 20070454

http://slidepdf.com/reader/full/20070454 6/10

det_img = detect_gotcha(det_img,obj_img,tx,ty)

-------------------------  

| CS101 Image Processor |

-------------------------  

| 1. Concatenate || 2. Detect |

| 3. Segment |

| 4. Quit |

-------------------------  

Select : 2

Enter a search space image name : ta_faces.bmp

Enter an object image name : ta_face4.bmp

And there you are! Gotcha! (a ahem)

The third and last task, segmentation, was quite troublesome for me. I hit stone

walls several times while trying to figure this out, but luckily with the help of the online

python library and a few moments of inspiration I came up with something which is, I

hope, versatile enough to get through most of the stranger inputs someone might throw

at it. It did withstand things I threw at it, even rotten tomatoes loaded with extra

8/7/2019 20070454

http://slidepdf.com/reader/full/20070454 7/10

doses of ass.

My segment() method does not look so straightforward as the above two methods.

Why oh my, the methodd s contents are simply a collection of function calls nested inside

a single while loop! I did this to make sure my program could handle queerer inputs, and

so Id ll explain one-by-one why a certain part looks like this and why that code had tobe written down instead of whatd s-it-you-call-it.

def segment( img ) :

seg_img = copy( img )

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

# (4) Do something on here to segment the faces inside the green rectangles !

seg_img = segenlarge( seg_img )

seg_comparison = copy( seg_img )

fillqueue=[(0,0)]

while len(fillqueue)>0:

fx,fy = fillqueue[0]

seg_img,fillqueue = floodfill( seg_img, fx, fy, green, fillqueue )fillqueue = fillqueue[1:]

seg_img = segblackout( seg_img, seg_comparison, green )

seg_img = segshrink( seg_img )

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

return seg_img 

The first function called is the segenlarge(). This goes hand-in-hand with the last

function, segshrink(), so Id ll describe those two together. Here is the code for the two.

def segenlarge( img ):

w,h = img.size()

w=w+2

h=h+2

largeimg = create_picture( w, h, white )

for x in range(w -2):

for y in range(h-2):

largeimg.set(x+1,y+1,img.get(x,y))

return largeimg 

def segshrink( img ):

w,h = img.size()

w=w -2

h=h-2

smallimg = create_picture( w, h, white )

for x in range(w):

for y in range(h):

smallimg.set(x,y,img.get(x+1,y+1))

return smallimg 

These two methods segenlarge() and segshrink() are there to handle the following

question: What if the pixel (0,0) contained green? That is, if one of the green

8/7/2019 20070454

http://slidepdf.com/reader/full/20070454 8/10

rectangles began in the (0,0) coordinate my method wond t be able to find where to

start coloring things black, not without making mistakes some of the time. I could have

simply made the program keep going to neighboring coordinates until a non-green square

is found, but in the strange case where the ENTIRE TOP ROW is green this approach

fails: the first non-green pixel it would encounter would be INSIDE a green rectangle. So

I solved this by giving the image extra pixels, empty rows and columns on all four sides,where I could start coloring things in comfort. This way, as long as the ENTIRE edge is

not green, my floodfill() function (explained later) will find ways to get into the image, and

if the ENTIRE edge is indeed green then I need not worry because then I dond t have to

color a single pixel(the entire image is encased in a green rectangle).

The next function in line isa is that a while loop we see? Yes, it is. What is this

doing here? The answer to that question can be given by looking at the floodfill() function

sitting inside the loop.

def floodfill( img, x, y, color, queue ):

imgw, imgh = img.size()

if not img.get(x,y)==color:

img.set(x,y,color)

# this line was written for debugging 

#print str(x)+","+str(y)

if x>0:

if not img.get(x -1,y)==color:

queue.append((x -1,y))

img.set(x -1,y,color)

if y>0:

if not img.get(x,y -1)==color:

queue.append((x,y -1))

img.set(x,y -1,color)

if x<(imgw -1):

if not img.get(x+1,y)==color:

queue.append((x+1,y))

img.set(x+1,y,color)

if y<(imgh-1):

if not img.get(x,y+1)==color:

queue.append((x,y+1))

img.set(x,y+1,color)

return img, queue

This is the crme de la crme of the entire program, the central achievement,

the crowning glory that everything else pales in comparison toa and a complete

headache to implement. The logic itself was pretty simple, but I had to spend a full hour

debugging and scratching my head because this just wouldnd t work as I told it to.

However all that toil finally paid off and this is now working as designed. Sigh 

The floodfill() function is a recursive method; it is supposed to call itself when

certain conditions are met. It works like this: First, it checks the color of the pixel it is

standing on and colors it if it doesnd t match the one it received as input. Second, it

checks its neighboring pixels and sees if their colors are any different; if one of them

also isnd t the object color it colors it green and calls itself on that coordinate. The

8/7/2019 20070454

http://slidepdf.com/reader/full/20070454 9/10

result is that when a single pixel that isn

t green is chosen an

  floodfill(green) is calle

on

it, the function will color the entire contiguously non-green region in green.

e Okay,f you might ask, e I see that floodfill() is recursive, but why the queue?

Why not simply call floodfill() from within the floodfill()?f Oh, I think you know perfectly

why, sir. I actually

i

write it as such at the beginning, only to receive an error

message from Wing IDE saying c maximum recursion level reache

. I coul

n

t call thatmany recursive functions with python! So I ma

e a queue an

then whenever floodfill() 

eci

es it nee

s to clone itself (ala Agent Smith in the Matrix series) it can a

the

target coor

inate in the queue.

On a si

e note, the above was not the only bug I encountere

while programming

floodfill(). For one, the program woul

just simply freeze whenever I trie

to run the

segment() metho

. This was because the queue was filling up with en

less instances of the

same coor

inates, which was in turn because two pixels neighboring the same non-green

pixel woul

BOTH call that coor

inate an

put it in the queue, an

when THAT

coor

inate was reache

it woul

 

o the same with its neighboring coor

inates (an

 

o

that multiple times because itself happens multiple times), a

infinatum. This was solve

 

by intro

ucing the img.set(x,y,color) line to each queue-a

ing sequence so that multiple

appen

s of the same pixel woul

not happen.

Alright, now we have a green-fille

image rea

y for

isplaying. Wait,

i

I say

green? Yes, I sai

green. The problem aske

for a black image, so then why have I gone

into all that trouble just to paint the whole thing green? This is, again, to counter

another c strange an

 

evilish input

I thought up: what if, for whatever reasons, there

is a big wall of black surroun

ing a green rectangle? If I

i

  floodfill(black) it woul

stop

when it encounters black, so if such a wall existe

then it woul

n

t touch the area

enclose

insi

e, which I AM suppose

to fill up as it is still outsi

e any GREEN rectangles.

I knew that checking for outsi

e-green-ness was too haphazar

so I opte

for a

estructively creative solution:

o floodfill(green) an

worry about color afterwar

s. This

way I can safely assume that any area not colore

is insi

e a green rectangle. 

Thus naturally follows the next function: segblackout().

def segblackout( img, compare, color ):if not img.size() == compare.size():

return img 

imgw,imgh = img.size()

for x in range(imgw):

for y in range(imgh):

if img.get(x,y)==color:

if not compare.get(x,y)==color:

img.set(x,y,black)

return img 

This function compares the green-fille

result of floodfill(green) with the original

input image an

 

eci

es which green pixel is a green rectangle an

which isn

t. After

that is

one it colors all green pixels that aren

t part of a rectangle in black. It looks

extremely simple(an

blunt) but I ha

to go through 20 a

itional minutes of

ebugging

since this, too, woul

n

t work. When I finally foun

out that compare_img = seg_img  

oesn

t

work an

has to be rewritten as compare_img = copy(seg_img) I crawle

on the groun

crying.

Metaphorically Speaking, that is.

Finally, we see the results.

-------------------------  

| CS101 Image Processor |

8/7/2019 20070454

http://slidepdf.com/reader/full/20070454 10/10

-------------------------  

| 1. Concatenate |

| 2. Detect |

| 3. Segment |

| 4. Quit |

-------------------------  

Select : 3

Enter an image name to segment : ta_faces_found.bmp

Now that¡

one I feel like a¡

rink. Martini, please. Shaken, not stirre¡

.

One last thing I¡ ¡

like to note before conclu¡

ing the¡

ocumentation: perhaps

because of its recursive nature segmentation metho¡

takes a long time to compute. I¡ ¡

 

like to point out (with pri¡

e) that the recursive nature allows it to a¡

apt to¡

ifferentcases of the problem: it is even able to cope with non-rectangular green enclosures. I

strongly protest that the long time taken by recursion shoul¡

t be a cause for a

lower gra¡

e. By taking a few longer it¡

oes much more! Yes, taking long is criminal in

the context of to¡

ay¡

s programming, but isn¡

t versatility a great thing to have? You

think so, right? So please¡

o look upon me an¡

my program kin¡

ly an¡

give it goo¡

 

gra¡

es,¡

ear goo¡

sir(or ma¡

am). Por favor.

Yours truly, 20070454 !