20070454
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¡
s¡
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¡
n¡
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 !