What does a Burmese Python wear to the beach?

Posted by Dillon Reedy on 2017-03-31

A Pythong

Let’s talk about Python. She’s a real bitch and a half, that I’ve only viewed the truly gifted be good at it. In my time with working on her, I’ve come around though. Also if you just want to skip my article and look at straight code, I made a repository on Github.

Prerequisites

1.) Unfortunately I’m an idiot and do all my development in Python 2.7, if you adapt my work to 3.X show it off to me!
2.) A text editor, I just go with Sublime for that’s what I’m used to, but any real text editor will do. I’m not aware of any Python Studio editors, but if you find a good one email me a link to it!
3.) The PEP-8 Sublime formatter keeps you from running into indentation errors when compiling your Python program.
4.) Pip install Tkinter and PIL using the command “pip install Tkinter” and “pip install pillow” respectively.

Some Nifty Python Features

Getting used to indentions is a hard reality to face with Python. I’m adjusted to my little world of brackets, but we all make adjustments. You’ll definitely need PEP-8 formatting to prevent all the indention errors you will receive when trying to compile your Python program.

As we all know from previous posts, I don’t like having to declare a variables’ type, it saves the programmer time. Python does this, to which it deserves a mention. On top of this, Python makes it so that you don’t have to declare variables, like at all, you can just make them exist. I really do like that feature within the language (I’ll give it kudos for that).

A Description of Seam Carving

Seam Carving is an interesting thing to do, I’d advise any person looking to make an application on this topic to look over the wikipedia page and this youtube video on it first. The basic idea of seam carving is that we want to cut out the unimportant parts of an image.

I created this .gif to kind of demonstrate what it does:

As we can see, at the end of the .gif, the path in the image gets bizarrely shifted. I suppose the math formula defining out what to remove can be a little refined, but overall it somewhat works.

Getting Energy From Image

So as described above, we cut out what is unimportant to an image. Well how do we determine what is important and what is not important? What I end up using is a very basic math formula “Given a pixel, we calculate the pythogrean formula between the RGB values of the pixel between the top and bottom, and then the pixels to the left and right, and then sum those two pythogrean values.” Here’s some code I made in Python that calculates that:

1
2
3
4
5
6
7
8
9
10
11
12
13
def deltaSquared(self, pixel1, pixel2):
if (len(pixel1) == 4):
(r1, g1, b1, opac1) = pixel1
elif (len(pixel1) == 3):
(r1, g1, b1) = pixel1
if (len(pixel2) == 4):
(r2, g2, b2, opac2) = pixel2
elif (len(pixel2) == 3):
(r2, g2, b2) = pixel2
r_delta = r1 - r2
g_delta = g1 - g2
b_delta = b1 - b2
return ((r_delta ** 2) + (g_delta ** 2) + (b_delta ** 2))

Now “why?” you may ask, am I setting my tuples differently? Well, for some images in my program, we get the pixel with opacity other times we don’t get opacity. Why this

A Dynamic Programming Solution

My dynamic programming solution runs in (H-1)*(W) time, where H is the number of pixels along the height of the image, and W is the number of pixels along the width of the image. I start out by copying the top row of the importance values into our dynamic matrix. Then starting on the 2nd row, I get the minimum value from the dynamic value to the top-left, top, and top-right of the current pixel and sum that up with the energy value of the current pixel

1
2
3
4
5
6
7
8
def getPointsAbove(self, givenPt, w, h):
ptsLis = []
ptsLis.append(Point(givenPt.x - 1, givenPt.y))
if (givenPt.y + 1 < w):
ptsLis.append(Point(givenPt.x - 1, givenPt.y + 1))
if (givenPt.y - 1 > -1):
ptsLis.append(Point(givenPt.x - 1, givenPt.y - 1))
return ptsLis

I use a lot of list of lists representations for matrixes, I’d advise you to do the same, although accessing the values for list of lists is weird and not very straightforward:

1
Matrix = [[0 for x in range(w)] for y in range(h)]

Tkinter

Our ultimate goal is going to make our application look like this:

So what kind of controls do we have here on the screen? Well we’ve got an image display, two labels, two entries, and two buttons.

Our image display code doesn’t require much work:

1
2
3
4
5
6
7
8
9
self.original = Image.open(imageName)
image = ImageTk.PhotoImage(self.original)
self.w = Canvas(master, width=self.original.width,
height=self.original.height)
self.w.grid(row=1, column=0)
self.w.create_image(0, 0, image=image, anchor=NW, tags="IMG")
self.w.img = image
self.w.pack()

Labels are pretty straight forward:

1
2
3
self.l1 = Label(master, text="Height:")
self.l1.grid(row=2, column=0)
self.l1.pack(side=LEFT)

Along with Entry objects:

1
2
3
4
self.e1 = Entry(master)
self.e1.insert(0, str(self.original.height))
self.e1.grid(row=2, column=1)
self.e1.pack(side=LEFT)

And finally buttons, an important thing to note about buttons is what code they should execute when they are pressed, in my example code the stretch button calls the resize method:

1
2
3
self.b1 = Button(master, text="Stretch", fg="blue", command=self.resize)
self.b1.grid(row=2, column=4)
self.b1.pack(side=LEFT)

Conclusion

Python is a different breed of programming that is ruthless and unwavering, although I respect its’ philosophy. Python needs more structure in my opinion, it allows for too much creativity, when programming as a whole is about control and structure. As always e-mail me if you have anything you’d like to talk about at dillon.reedy123@gmail.com