From d2bac1900fa1c7d18361e5762145ad779c6931aa Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Tue, 8 Oct 2013 17:44:58 -0400 Subject: [PATCH 01/16] rename var for clarity --- SeamCarverUtilities.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index a6c85f7..e80c579 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -4,9 +4,10 @@ def printVerticalSeam(sc): totalSeamEnergy = 0 for row in range(sc.height()): for col in range(sc.width()): + seam_col = seam[row_index] lmarker = ' ' rmarker = ' ' - if col == seam[row]: + if col == seam_col: lmarker = '[' rmarker = ']' totalSeamEnergy += sc.energy(col, row) From c39488e657fb0fc7756bc8fd21f01dd7ff060b7c Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Tue, 8 Oct 2013 17:52:51 -0400 Subject: [PATCH 02/16] use ternary operators and sum comprehension --- SeamCarverUtilities.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index e80c579..1acf9b4 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -4,15 +4,13 @@ def printVerticalSeam(sc): totalSeamEnergy = 0 for row in range(sc.height()): for col in range(sc.width()): - seam_col = seam[row_index] - lmarker = ' ' - rmarker = ' ' - if col == seam_col: - lmarker = '[' - rmarker = ']' - totalSeamEnergy += sc.energy(col, row) + seam_col = seam[row] + lmarker = '[' if col == seam_col else ' ' + rmarker = ']' if col == seam_col else ' ' print '{:s}{:>6d}{:s}'.format(lmarker, sc.energy(col, row), rmarker), print + + totalSeamEnergy = sum(sc.energy(col, row) for col, row in zip(seam, range(sc.height()))) print "\nTotal seam energy: {:d}".format(totalSeamEnergy) From 41d3f1a8a3b13308333c87a721568800f2dfa9a0 Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Tue, 8 Oct 2013 17:53:46 -0400 Subject: [PATCH 03/16] DRY out code with tuple unpacking --- SeamCarverUtilities.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index 1acf9b4..bb3f5b1 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -5,8 +5,7 @@ def printVerticalSeam(sc): for row in range(sc.height()): for col in range(sc.width()): seam_col = seam[row] - lmarker = '[' if col == seam_col else ' ' - rmarker = ']' if col == seam_col else ' ' + lmarker, rmarker = ('[', ']') if col == seam_col else (' ',' ') print '{:s}{:>6d}{:s}'.format(lmarker, sc.energy(col, row), rmarker), print From 1203fcda495c84d1b3a0c2ba30d5b8f3282f0192 Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Tue, 8 Oct 2013 18:07:11 -0400 Subject: [PATCH 04/16] Refactor print seam functions to combine them ... to better highlight the small differences between the two functions --- ResizeDemo.py | 8 ++++---- SeamCarverUtilities.py | 37 ++++++++++++++----------------------- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/ResizeDemo.py b/ResizeDemo.py index fa4032c..93422f9 100644 --- a/ResizeDemo.py +++ b/ResizeDemo.py @@ -20,7 +20,7 @@ print "print vertical seam 1" print sc.width(), sc.height() #SeamCarverUtilities.printVerticalSeamEnergy(sc) -SeamCarverUtilities.printVerticalSeam(sc) +SeamCarverUtilities.printSeam(sc, direction="vertical") #SeamCarverUtilities.distToArray(sc) print "remove vertical seam" @@ -28,10 +28,10 @@ sc.removeVerticalSeam(s) print sc.width(), sc.height() print "find vertical seam" -SeamCarverUtilities.printVerticalSeam(sc) +SeamCarverUtilities.printSeam(sc, direction="vertical") print "print horizontal seam" -SeamCarverUtilities.printHorizontalSeam(sc) +SeamCarverUtilities.printSeam(sc, direction="horizontal") #SeamCarverUtilities.distToArray(sc) #SeamCarverUtilities.printHorizontalSeamEnergy(sc) @@ -41,7 +41,7 @@ print sc.width(), sc.height() #SeamCarverUtilities.printHorizontalSeamEnergy(sc) print "find horizontal seam" -SeamCarverUtilities.printHorizontalSeam(sc) +SeamCarverUtilities.printSeam(sc, direction="horizontal") #SeamCarverUtilities.distToArray(sc) diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index bb3f5b1..9fdf128 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -1,34 +1,25 @@ -def printVerticalSeam(sc): +def printSeam(sc, direction): "vertical seam is a list of cols" - seam = sc.findVerticalSeam() - totalSeamEnergy = 0 + if direction == "vertical": + seam = sc.findVerticalSeam() + seam_indices = zip(seam, range(sc.height())) + else: + seam = sc.findHorizontalSeam() + seam_indices = zip(range(sc.width()), seam) + for row in range(sc.height()): for col in range(sc.width()): - seam_col = seam[row] - lmarker, rmarker = ('[', ']') if col == seam_col else (' ',' ') + if direction == "vertical": + is_on_seam = col == seam[row] + else: + is_on_seam = row == seam[col] + lmarker, rmarker = ('[', ']') if is_on_seam else (' ',' ') print '{:s}{:>6d}{:s}'.format(lmarker, sc.energy(col, row), rmarker), print - totalSeamEnergy = sum(sc.energy(col, row) for col, row in zip(seam, range(sc.height()))) + totalSeamEnergy = sum(sc.energy(col, row) for col, row in seam_indices) print "\nTotal seam energy: {:d}".format(totalSeamEnergy) - -def printHorizontalSeam(sc): - "horizontal seam is a list of rows" - seam = sc.findHorizontalSeam() - totalSeamEnergy = 0 - for row in range(sc.height()): - for col in range(sc.width()): - lmarker = ' ' - rmarker = ' ' - if row == seam[col]: - lmarker = '[' - rmarker = ']' - totalSeamEnergy += sc.energy(col, row) - print '{:s}{:>6d}{:s}'.format(lmarker, sc.energy(col, row), rmarker), - print - print "\nTotal seam energy: {:d}".format(totalSeamEnergy) - def printVerticalSeamEnergy(sc): "vertical seam is a list of cols" seam = sc.findVerticalSeam() From 61b1f56b10f4b90b6b4c653d6655495bdd137f85 Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Tue, 8 Oct 2013 18:11:55 -0400 Subject: [PATCH 05/16] Use docstrings (""") instead of strings You have well-documented functions here: make the docs accessible by formatting them with triply-quoted strings. (See, eg. my_function.func_doc). --- SeamCarverLib.py | 34 +++++++++++++++++----------------- SeamCarverUtilities.py | 4 ++-- readPNG_2.py | 6 +++--- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/SeamCarverLib.py b/SeamCarverLib.py index 2b265c4..a78db5f 100644 --- a/SeamCarverLib.py +++ b/SeamCarverLib.py @@ -6,7 +6,7 @@ import pdb class SeamCarver(object): - "removes seams from an image" + """removes seams from an image""" def __init__(self, picture): self._img = picture.imageArray self._height = picture.num_rows @@ -33,12 +33,12 @@ def height(self): return self._height def energy(self, col, row): - "return energy of pixel in (col, row)" + """return energy of pixel in (col, row)""" if self._isValid(col, row): return self._energy[self._toLinear(col, row)] def findVerticalSeam(self, transposed=False): - "return vertical seam in image" + """return vertical seam in image""" # vertical seam = sequence of cols; seam[0] is col of row 0 # row-indexed seam seam = [-1 for _ in range(self._height)] @@ -54,7 +54,7 @@ def findVerticalSeam(self, transposed=False): return seam def findHorizontalSeam(self, transposed=True): - "return horizontal seam in image" + """return horizontal seam in image""" # tranpose dimensions self._exchDims() @@ -67,7 +67,7 @@ def findHorizontalSeam(self, transposed=True): return seam def _shiftImgUp(self, (col, row)): - "remove horizontal seam in img and energy array by shifting up each col" + """remove horizontal seam in img and energy array by shifting up each col""" for r in range(row, self._height - 1): i = self._width * r + col rchan_index = i*3 @@ -77,7 +77,7 @@ def _shiftImgUp(self, (col, row)): self._energy[i] = self._energy[i + self._width] def _removeSeam(self, seam): - "remove seam of pixels from image" + """remove seam of pixels from image""" # remove horizontal seam if(len(seam)) != self._width or self._width < 2: raise ValueError @@ -91,7 +91,7 @@ def _removeSeam(self, seam): def removeVerticalSeam(self, seam): - "remove vertical seam of pixels from image" + """remove vertical seam of pixels from image""" if (len(seam) != self._height or self._height == 0 or self._width == 2): raise ValueError indexes_to_remove = map(lambda (r, col): self._width * r + col, enumerate(seam)) @@ -128,7 +128,7 @@ def removeVerticalSeam(self, seam): self._sink = self._source + 1 def removeHorizontalSeam(self, seam): - "remove horizontal seam of pixels" + """remove horizontal seam of pixels""" self._removeSeam(seam) # update energy @@ -147,13 +147,13 @@ def removeHorizontalSeam(self, seam): def _onEdge(self, col, row): - "True if pixel is on left, top, or right edge" + """True if pixel is on left, top, or right edge""" return col == 0 or col == self._width - 1 or row == 0 def _updateEnergy(self, R_chan, resized_width): - '''re-calculate energy values for pixels on either side of seam + """re-calculate energy values for pixels on either side of seam - R_chan is a list of R channels''' + R_chan is a list of R channels""" for R in R_chan: # index = index of seam pixel wrt original image index = R / self._num_channels @@ -199,9 +199,9 @@ def _updateEnergy(self, R_chan, resized_width): self._energyGrad(resized_index - 1, resized_width) def _energyGrad(self, index, width): - '''Calculate energy of pixel in resized image. Update self._energy + """Calculate energy of pixel in resized image. Update self._energy - uses resized_index and resized_width''' + uses resized_index and resized_width""" left = (index - 1) * self._num_channels right = (index + 1) * self._num_channels @@ -231,18 +231,18 @@ def _diff_squared(self, x, y): return (x - y)**2 def _exchDims(self): - "exchange self._width and self._height" + """exchange self._width and self._height""" swap = self._width self._width = self._height self._height = swap def _toLinear(self, col, row): - "converts pixel from (col, row) to single index" + """converts pixel from (col, row) to single index""" if self._isValid(col, row): return row * self._width + col def _toGrid(self, num): - "converts pixel from single index to (col, row)" + """converts pixel from single index to (col, row)""" if self._isValid(num): row = num / self._width col = num % self._width @@ -261,7 +261,7 @@ def _isValid(self, col, row=None): return True def _buildGraph(self, transposed): - "pixels are nodes; edges define precedence constraints in a seam" + """pixels are nodes; edges define precedence constraints in a seam""" # graph data structures self._edgeTo = [_SENTINEL for _ in range(self._num_pixels + 2)] # add 2 for source, sink pixels self._distTo = [_INF for _ in range(self._num_pixels + 2)] diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index 9fdf128..810848a 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -1,5 +1,5 @@ def printSeam(sc, direction): - "vertical seam is a list of cols" + """vertical seam is a list of cols""" if direction == "vertical": seam = sc.findVerticalSeam() seam_indices = zip(seam, range(sc.height())) @@ -21,7 +21,7 @@ def printSeam(sc, direction): print "\nTotal seam energy: {:d}".format(totalSeamEnergy) def printVerticalSeamEnergy(sc): - "vertical seam is a list of cols" + """vertical seam is a list of cols""" seam = sc.findVerticalSeam() totalSeamEnergy = 0 for row in range(sc.height()): diff --git a/readPNG_2.py b/readPNG_2.py index d2dd381..26daabe 100644 --- a/readPNG_2.py +++ b/readPNG_2.py @@ -2,13 +2,13 @@ class Picture(object): - "reads a png image from a filename" + """reads a png image from a filename""" #BORDER_ENERGY = 195075 BORDER_ENERGY = 195705 def __init__(self, pngfilename): - "reads in a .png image" + """reads in a .png image""" _CH = 3 # number of channels (R,G,B = 3; R,G,B,A = 4) _r = png.Reader(filename=pngfilename) res = _r.read() @@ -44,7 +44,7 @@ def __init__(self, pngfilename): # for images with more than 2 rows for _row_next in res[2]: - "build image array and energy array" + #build image array and energy array # add _row_next to image array self.imageArray.extend(_row_next) From 91be59694fce7cc232c9888cf7df13b0d2ddfcaa Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Tue, 8 Oct 2013 18:15:50 -0400 Subject: [PATCH 06/16] Refactor seam energy function --- SeamCarverUtilities.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index 810848a..9eb9cef 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -20,12 +20,13 @@ def printSeam(sc, direction): totalSeamEnergy = sum(sc.energy(col, row) for col, row in seam_indices) print "\nTotal seam energy: {:d}".format(totalSeamEnergy) -def printVerticalSeamEnergy(sc): - """vertical seam is a list of cols""" - seam = sc.findVerticalSeam() - totalSeamEnergy = 0 - for row in range(sc.height()): - for col in range(sc.width()): - if col == seam[row]: - totalSeamEnergy += sc.energy(col, row) - print "\nTotal seam energy: {:d}".format(totalSeamEnergy) \ No newline at end of file +def calculateSeamEnergy(sc, direction): + if direction == "vertical": + seam = sc.findVerticalSeam() + else: + seam = sc.findHorizontalSeam() + relevant_size = sc._height if direction == "vertical" else sc._width + seam_indices = zip(seam, relevant_size) + totalSeamEnergy = sum(sc.energy(col, row) for col, row in seam_indices) + print "\nTotal seam energy: {:d}".format(totalSeamEnergy) + return totalSeamEnergy From c5bd76ed7ea0881edf7f43640eb7eeb24095e658 Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Tue, 8 Oct 2013 18:16:50 -0400 Subject: [PATCH 07/16] use shiny new function --- SeamCarverUtilities.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index 9eb9cef..182acea 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -2,10 +2,8 @@ def printSeam(sc, direction): """vertical seam is a list of cols""" if direction == "vertical": seam = sc.findVerticalSeam() - seam_indices = zip(seam, range(sc.height())) else: seam = sc.findHorizontalSeam() - seam_indices = zip(range(sc.width()), seam) for row in range(sc.height()): for col in range(sc.width()): @@ -17,7 +15,7 @@ def printSeam(sc, direction): print '{:s}{:>6d}{:s}'.format(lmarker, sc.energy(col, row), rmarker), print - totalSeamEnergy = sum(sc.energy(col, row) for col, row in seam_indices) + totalSeamEnergy = calculateSeamEnergy(sc, direction) print "\nTotal seam energy: {:d}".format(totalSeamEnergy) def calculateSeamEnergy(sc, direction): From b5bb15809bc29b266731d9601c2ab8704d954de1 Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Tue, 8 Oct 2013 18:22:34 -0400 Subject: [PATCH 08/16] Remove getter It's not generally pythonic to have a "getter" like this - you usually want to just access the object's attributes directly. It looks like you're signalling to the end user that the width and height aren't part of the object's public API. I think it's more clean to skip this (and in fact, I'd change the names from _width and _height to width and height). Others may disagree :) --- ResizeDemo.py | 30 +++++++++++++++--------------- SeamCarverLib.py | 7 ------- SeamCarverUtilities.py | 4 ++-- 3 files changed, 17 insertions(+), 24 deletions(-) diff --git a/ResizeDemo.py b/ResizeDemo.py index 93422f9..628056c 100644 --- a/ResizeDemo.py +++ b/ResizeDemo.py @@ -18,7 +18,7 @@ sc = SeamCarverLib.SeamCarver(pic) print "print vertical seam 1" -print sc.width(), sc.height() +print sc._width, sc._height #SeamCarverUtilities.printVerticalSeamEnergy(sc) SeamCarverUtilities.printSeam(sc, direction="vertical") #SeamCarverUtilities.distToArray(sc) @@ -26,7 +26,7 @@ print "remove vertical seam" s = sc.findVerticalSeam() sc.removeVerticalSeam(s) -print sc.width(), sc.height() +print sc._width, sc._height print "find vertical seam" SeamCarverUtilities.printSeam(sc, direction="vertical") @@ -38,7 +38,7 @@ print "remove horizontal seam" s = sc.findHorizontalSeam() sc.removeHorizontalSeam(s) -print sc.width(), sc.height() +print sc._width, sc._height #SeamCarverUtilities.printHorizontalSeamEnergy(sc) print "find horizontal seam" SeamCarverUtilities.printSeam(sc, direction="horizontal") @@ -49,11 +49,11 @@ # sc.removeVerticalSeam(s) # # print "print vertical seam 2" -# print sc.width(), sc.height() +# print sc._width, sc._height # SeamCarverUtilities.printVerticalSeam(sc) # #SeamCarverUtilities.printVerticalSeamEnergy(sc) # # s = sc.findVerticalSeam() -# # for i in range(sc.height()): +# # for i in range(sc._height): # # print s[i] # # # print sc._edgeTo # # # print sc._distTo @@ -62,27 +62,27 @@ # s = sc.findVerticalSeam() # sc.removeVerticalSeam(s) -# print sc.width(), sc.height() +# print sc._width, sc._height # # print "print vertical seam 3" -# # print sc.width(), sc.height() +# # print sc._width, sc._height # SeamCarverUtilities.printVerticalSeam(sc) # SeamCarverUtilities.distToArray(sc) # #SeamCarverUtilities.printVerticalSeamEnergy(sc) # # s = sc.findVerticalSeam() -# # for i in range(sc.height()): +# # for i in range(sc._height): # # print s[i] # s = sc.findVerticalSeam() # sc.removeVerticalSeam(s) -# print sc.width(), sc.height() +# print sc._width, sc._height # # print "print vertical seam 4" -# # print sc.width(), sc.height() +# # print sc._width, sc._height # SeamCarverUtilities.printVerticalSeam(sc) #SeamCarverUtilities.printVerticalSeamEnergy(sc) # s = sc.findVerticalSeam() -# for i in range(sc.height()): +# for i in range(sc._height): # print s[i] # print "print vertical seam 2" @@ -90,14 +90,14 @@ # # print sc._distTo # s = sc.findVerticalSeam() # sc.removeVerticalSeam(s) -# print sc.height(), sc.width() +# print sc._height, sc._width #SeamCarverUtilities.printVerticalSeam(sc) # print # print "print vertical seam 3" # s = sc.findVerticalSeam() # sc.removeVerticalSeam(s) -# print sc.height(), sc.width() +# print sc._height, sc._width # # print sc._edgeTo # # print sc._distTo # #pdb.set_trace() @@ -107,7 +107,7 @@ # print "remove vertical seam 4" # s = sc.findVerticalSeam() # sc.removeVerticalSeam(s) -# print sc.height(), sc.width() +# print sc._height, sc._width # # print sc._edgeTo # # print sc._distTo # SeamCarverUtilities.printVerticalSeam(sc) @@ -115,7 +115,7 @@ # print "remove vertical seam 5" # s = sc.findVerticalSeam() # sc.removeVerticalSeam(s) -# print sc.height(), sc.width() +# print sc._height, sc._width # SeamCarverUtilities.printVerticalSeam(sc) diff --git a/SeamCarverLib.py b/SeamCarverLib.py index a78db5f..4b47f0a 100644 --- a/SeamCarverLib.py +++ b/SeamCarverLib.py @@ -25,13 +25,6 @@ def __init__(self, picture): self._edgeTo = [] self._distTo = [] - - def width(self): - return self._width - - def height(self): - return self._height - def energy(self, col, row): """return energy of pixel in (col, row)""" if self._isValid(col, row): diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index 182acea..878b599 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -5,8 +5,8 @@ def printSeam(sc, direction): else: seam = sc.findHorizontalSeam() - for row in range(sc.height()): - for col in range(sc.width()): + for row in range(sc._height): + for col in range(sc._width): if direction == "vertical": is_on_seam = col == seam[row] else: From 9820c3f8dde57b450a112ba6a8cad73538cfdede Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Thu, 10 Oct 2013 11:20:34 -0400 Subject: [PATCH 09/16] Refactor removeXSeam to be one method and update callers --- ResizeDemo.py | 4 ++-- SeamCarverLib.py | 23 ++++++++--------------- SeamCarverUtilities.py | 8 ++++---- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/ResizeDemo.py b/ResizeDemo.py index 628056c..5c9fe8d 100644 --- a/ResizeDemo.py +++ b/ResizeDemo.py @@ -24,7 +24,7 @@ #SeamCarverUtilities.distToArray(sc) print "remove vertical seam" -s = sc.findVerticalSeam() +s = sc.findSeam(transposed=False) sc.removeVerticalSeam(s) print sc._width, sc._height print "find vertical seam" @@ -36,7 +36,7 @@ #SeamCarverUtilities.printHorizontalSeamEnergy(sc) print "remove horizontal seam" -s = sc.findHorizontalSeam() +s = sc.findSeam(transposed=True) sc.removeHorizontalSeam(s) print sc._width, sc._height #SeamCarverUtilities.printHorizontalSeamEnergy(sc) diff --git a/SeamCarverLib.py b/SeamCarverLib.py index 4b47f0a..df34b03 100644 --- a/SeamCarverLib.py +++ b/SeamCarverLib.py @@ -30,10 +30,14 @@ def energy(self, col, row): if self._isValid(col, row): return self._energy[self._toLinear(col, row)] - def findVerticalSeam(self, transposed=False): + def findSeam(self, transposed=False): """return vertical seam in image""" # vertical seam = sequence of cols; seam[0] is col of row 0 - # row-indexed seam + # - row-indexed seam + # horizontal seam = sequence of rows; seam[0] is row of col 0 + # - col-indexed seam + if transposed: + self._exchDims() seam = [-1 for _ in range(self._height)] self._buildGraph(transposed) row = self._height - 1 @@ -44,19 +48,8 @@ def findVerticalSeam(self, transposed=False): row -= 1 #self._edgeTo = [] #self._distTo = [] - return seam - - def findHorizontalSeam(self, transposed=True): - """return horizontal seam in image""" - # tranpose dimensions - self._exchDims() - - # horizontal seam = sequence of rows; seam[0] is row of col 0 - # col-indexed seam - seam = self.findVerticalSeam(transposed) - self._exchDims() - #self._edgeTo = [] - #self._distTo = [] + if transposed: + self._exchDims() return seam def _shiftImgUp(self, (col, row)): diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index 878b599..e3dc6a8 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -1,9 +1,9 @@ def printSeam(sc, direction): """vertical seam is a list of cols""" if direction == "vertical": - seam = sc.findVerticalSeam() + seam = sc.findSeam(transposed=False) else: - seam = sc.findHorizontalSeam() + seam = sc.findSeam(transposed=True) for row in range(sc._height): for col in range(sc._width): @@ -20,9 +20,9 @@ def printSeam(sc, direction): def calculateSeamEnergy(sc, direction): if direction == "vertical": - seam = sc.findVerticalSeam() + seam = sc.findSeam(transposed=False) else: - seam = sc.findHorizontalSeam() + seam = sc.findSeam(transposed=True) relevant_size = sc._height if direction == "vertical" else sc._width seam_indices = zip(seam, relevant_size) totalSeamEnergy = sum(sc.energy(col, row) for col, row in seam_indices) From 1dcaccd6ccea08596bef47754e6eee9e2cadf597 Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Thu, 10 Oct 2013 11:28:25 -0400 Subject: [PATCH 10/16] Change name of variable to be more clear We found ourselves asking which way transposed was - this naming makes that explicit. --- ResizeDemo.py | 4 ++-- SeamCarverLib.py | 6 +++--- SeamCarverUtilities.py | 11 +++-------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/ResizeDemo.py b/ResizeDemo.py index 5c9fe8d..6ccab64 100644 --- a/ResizeDemo.py +++ b/ResizeDemo.py @@ -24,7 +24,7 @@ #SeamCarverUtilities.distToArray(sc) print "remove vertical seam" -s = sc.findSeam(transposed=False) +s = sc.findSeam(direction="vertical") sc.removeVerticalSeam(s) print sc._width, sc._height print "find vertical seam" @@ -36,7 +36,7 @@ #SeamCarverUtilities.printHorizontalSeamEnergy(sc) print "remove horizontal seam" -s = sc.findSeam(transposed=True) +s = sc.findSeam(direction="horizontal") sc.removeHorizontalSeam(s) print sc._width, sc._height #SeamCarverUtilities.printHorizontalSeamEnergy(sc) diff --git a/SeamCarverLib.py b/SeamCarverLib.py index df34b03..ed9fc1b 100644 --- a/SeamCarverLib.py +++ b/SeamCarverLib.py @@ -30,13 +30,13 @@ def energy(self, col, row): if self._isValid(col, row): return self._energy[self._toLinear(col, row)] - def findSeam(self, transposed=False): + def findSeam(self, direction): """return vertical seam in image""" # vertical seam = sequence of cols; seam[0] is col of row 0 # - row-indexed seam # horizontal seam = sequence of rows; seam[0] is row of col 0 # - col-indexed seam - if transposed: + if direction == "horizontal": self._exchDims() seam = [-1 for _ in range(self._height)] self._buildGraph(transposed) @@ -48,7 +48,7 @@ def findSeam(self, transposed=False): row -= 1 #self._edgeTo = [] #self._distTo = [] - if transposed: + if direction == "horizontal": self._exchDims() return seam diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index e3dc6a8..6245dda 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -1,9 +1,6 @@ def printSeam(sc, direction): """vertical seam is a list of cols""" - if direction == "vertical": - seam = sc.findSeam(transposed=False) - else: - seam = sc.findSeam(transposed=True) + seam = sc.findSeam(direction) for row in range(sc._height): for col in range(sc._width): @@ -19,10 +16,8 @@ def printSeam(sc, direction): print "\nTotal seam energy: {:d}".format(totalSeamEnergy) def calculateSeamEnergy(sc, direction): - if direction == "vertical": - seam = sc.findSeam(transposed=False) - else: - seam = sc.findSeam(transposed=True) + seam = sc.findSeam(direction) + relevant_size = sc._height if direction == "vertical" else sc._width seam_indices = zip(seam, relevant_size) totalSeamEnergy = sum(sc.energy(col, row) for col, row in seam_indices) From 6f9a5609a44e598168324bf1f883680f7ece4aef Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Thu, 10 Oct 2013 11:32:15 -0400 Subject: [PATCH 11/16] list multiplication is simpler to read here --- SeamCarverLib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SeamCarverLib.py b/SeamCarverLib.py index ed9fc1b..740b5fb 100644 --- a/SeamCarverLib.py +++ b/SeamCarverLib.py @@ -38,7 +38,7 @@ def findSeam(self, direction): # - col-indexed seam if direction == "horizontal": self._exchDims() - seam = [-1 for _ in range(self._height)] + seam = [-1] * self._height self._buildGraph(transposed) row = self._height - 1 v = self._edgeTo[self._sink] From 9341fbf6358f49557307e39286cdcc4290938409 Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Thu, 10 Oct 2013 11:50:40 -0400 Subject: [PATCH 12/16] Rename variables Feel free to be verbose in your variable names in pursuit of readability :) --- SeamCarverLib.py | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/SeamCarverLib.py b/SeamCarverLib.py index 740b5fb..63bc74f 100644 --- a/SeamCarverLib.py +++ b/SeamCarverLib.py @@ -277,44 +277,44 @@ def _buildGraph(self, transposed): - def _edgeTodistTo(self, v, transposed, edgeL=False, edgeR=False): + def _edgeTodistTo(self, pixel, transposed, edgeL=False, edgeR=False): # returns pixel connected to v with min energy if edgeL: # left edge - vC = v - self._width - vRD = v - self._width + 1 - vLU = vC + up_pixel = pixel - self._width + right_up_diagonal_pixel = pixel - self._width + 1 + left_up_diagonal_pixel = up_pixel elif edgeR: # right edge - vLU = v - self._width - 1 - vC = v - self._width - vRD = vC + left_up_diagonal_pixel = pixel - self._width - 1 + up_pixel = pixel - self._width + right_up_diagonal_pixel = up_pixel else: - # pixels connect to v - vLU = v - self._width - 1 - vC = v - self._width - vRD = v - self._width + 1 + # pixels connect to pixel + left_up_diagonal_pixel = pixel - self._width - 1 + up_pixel = pixel - self._width + right_up_diagonal_pixel = pixel - self._width + 1 - # energy of pixels connected to v + # energy of pixels connected to pixel if transposed: - (colU, rowU) = self._toGrid(vLU) - (colC, rowC) = self._toGrid(vC) - (colD, rowD) = self._toGrid(vRD) + (colU, rowU) = self._toGrid(left_up_diagonal_pixel) + (colC, rowC) = self._toGrid(up_pixel) + (colD, rowD) = self._toGrid(right_up_diagonal_pixel) # read energy eLU = self._energy[self._height * colU + rowU] eC = self._energy[self._height * colC + rowC] eRD = self._energy[self._height * colD + rowD] else: # read energy directly from energy array - eLU = self._energy[vLU] - eC = self._energy[vC] - eRD = self._energy[vRD] - #print (eLU, vLU), (eC, vC), (eRD, vRD) + eLU = self._energy[left_up_diagonal_pixel] + eC = self._energy[up_pixel] + eRD = self._energy[right_up_diagonal_pixel] + #print (eLU, left_up_diagonal_pixel), (eC, up_pixel), (eRD, right_up_diagonal_pixel) # find min distance and its associated vertex - dist, from_vertex = min((self._distTo[vLU] + eLU, vLU), (self._distTo[vC] + eC, vC), (self._distTo[vRD] + eRD, vRD)) - #e, vertex = min([(eC, vC), (eLU, vLU), (eRD, vRD)]) - self._edgeTo[v] = from_vertex - self._distTo[v] = dist + dist, from_vertex = min((self._distTo[left_up_diagonal_pixel] + eLU, left_up_diagonal_pixel), (self._distTo[up_pixel] + eC, up_pixel), (self._distTo[right_up_diagonal_pixel] + eRD, right_up_diagonal_pixel)) + #e, vertex = min([(eC, up_pixel), (eLU, left_up_diagonal_pixel), (eRD, right_up_diagonal_pixel)]) + self._edgeTo[pixel] = from_vertex + self._distTo[pixel] = dist From 98419d14a129d05829ce84bc0b122a5b488ecf93 Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Thu, 10 Oct 2013 11:54:48 -0400 Subject: [PATCH 13/16] Remove repeated code to showcase differences between cases. --- SeamCarverLib.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/SeamCarverLib.py b/SeamCarverLib.py index 63bc74f..88d5b83 100644 --- a/SeamCarverLib.py +++ b/SeamCarverLib.py @@ -279,21 +279,16 @@ def _buildGraph(self, transposed): def _edgeTodistTo(self, pixel, transposed, edgeL=False, edgeR=False): # returns pixel connected to v with min energy + up_pixel = pixel - self._width + right_up_diagonal_pixel = pixel - self._width + 1 + left_up_diagonal_pixel = pixel - self._width - 1 + if edgeL: # left edge - up_pixel = pixel - self._width - right_up_diagonal_pixel = pixel - self._width + 1 left_up_diagonal_pixel = up_pixel elif edgeR: # right edge - left_up_diagonal_pixel = pixel - self._width - 1 - up_pixel = pixel - self._width right_up_diagonal_pixel = up_pixel - else: - # pixels connect to pixel - left_up_diagonal_pixel = pixel - self._width - 1 - up_pixel = pixel - self._width - right_up_diagonal_pixel = pixel - self._width + 1 # energy of pixels connected to pixel if transposed: From 4df7f95123584c1136098b4cccba2ebbf05e58ac Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Fri, 11 Oct 2013 15:48:45 -0400 Subject: [PATCH 14/16] Don't transpose Refactors edge and distance calculation to avoid confusing (to me) transposition. This commit isn't quite complete/working, but it gives an idea of the direction I'd suggest going. By the way, it's possible to swap two variables in python in one line: b, a = a, b --- SeamCarverLib.py | 94 +++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 49 deletions(-) diff --git a/SeamCarverLib.py b/SeamCarverLib.py index 88d5b83..119e1bf 100644 --- a/SeamCarverLib.py +++ b/SeamCarverLib.py @@ -36,10 +36,8 @@ def findSeam(self, direction): # - row-indexed seam # horizontal seam = sequence of rows; seam[0] is row of col 0 # - col-indexed seam - if direction == "horizontal": - self._exchDims() seam = [-1] * self._height - self._buildGraph(transposed) + self._buildGraph(direction) row = self._height - 1 v = self._edgeTo[self._sink] while (v != self._source): @@ -48,8 +46,6 @@ def findSeam(self, direction): row -= 1 #self._edgeTo = [] #self._distTo = [] - if direction == "horizontal": - self._exchDims() return seam def _shiftImgUp(self, (col, row)): @@ -216,12 +212,6 @@ def _energyGrad(self, index, width): def _diff_squared(self, x, y): return (x - y)**2 - def _exchDims(self): - """exchange self._width and self._height""" - swap = self._width - self._width = self._height - self._height = swap - def _toLinear(self, col, row): """converts pixel from (col, row) to single index""" if self._isValid(col, row): @@ -246,7 +236,7 @@ def _isValid(self, col, row=None): else: return True - def _buildGraph(self, transposed): + def _buildGraph(self, direction): """pixels are nodes; edges define precedence constraints in a seam""" # graph data structures self._edgeTo = [_SENTINEL for _ in range(self._num_pixels + 2)] # add 2 for source, sink pixels @@ -262,14 +252,23 @@ def _buildGraph(self, transposed): # for each vertex (pixel), calculate edgeTo[], distTo[] # start at row 1 for v in range(self._width, self._num_pixels): - if (v % self._width == 0): - # pixel is on left edge - self._edgeTodistTo(v, transposed, edgeL=True) - elif (v % self._width == self._width - 1): - # pixel is on right edge - self._edgeTodistTo(v, transposed, edgeR=True) - else: - self._edgeTodistTo(v, transposed) + edges = [] + if v % self._width == 0: + edges.append('left') + if v % self._width == self._width - 1: + edges.append("right") + if v / self._width == 0: + edges.append("top") + if v / self._width == self._height - 1: + edges.append("bottom") + + if direction == "vertical" and "top" in edges: + continue + if direction == "horizontal" and "left" in edges: + continue + + self._edgeTodistTo(v, direction, edges) + # edgeTo[sink] is vertex in last row with min energy index, min_energy = min(enumerate(self._distTo[self._num_pixels - self._width:self._num_pixels]), key=lambda (x, y): y) self._distTo[self._sink] = min_energy @@ -277,37 +276,34 @@ def _buildGraph(self, transposed): - def _edgeTodistTo(self, pixel, transposed, edgeL=False, edgeR=False): + def _edgeTodistTo(self, pixel, direction, edges): # returns pixel connected to v with min energy - up_pixel = pixel - self._width - right_up_diagonal_pixel = pixel - self._width + 1 - left_up_diagonal_pixel = pixel - self._width - 1 - - if edgeL: - # left edge - left_up_diagonal_pixel = up_pixel - elif edgeR: - # right edge - right_up_diagonal_pixel = up_pixel - - # energy of pixels connected to pixel - if transposed: - (colU, rowU) = self._toGrid(left_up_diagonal_pixel) - (colC, rowC) = self._toGrid(up_pixel) - (colD, rowD) = self._toGrid(right_up_diagonal_pixel) - # read energy - eLU = self._energy[self._height * colU + rowU] - eC = self._energy[self._height * colC + rowC] - eRD = self._energy[self._height * colD + rowD] - else: - # read energy directly from energy array - eLU = self._energy[left_up_diagonal_pixel] - eC = self._energy[up_pixel] - eRD = self._energy[right_up_diagonal_pixel] - #print (eLU, left_up_diagonal_pixel), (eC, up_pixel), (eRD, right_up_diagonal_pixel) + + if direction == "vertical": + ancestor_one = pixel - self._width - 1 + ancestor_two = pixel - self._width + ancestor_three = pixel - self._width + 1 + if 'left' in edges: + ancestor_one = ancestor_two + elif 'right' in edges: + ancestor_three = ancestor_two + + else: #horizontal + ancestor_one = pixel + self._width - 1 + ancestor_two = pixel - 1 + ancestor_three = pixel - self._width - 1 + if 'top' in edges: + ancestor_three = ancestor_two + elif 'bottom' in edges: + ancestor_one = ancestor_two + + eLU = self._energy[ancestor_one] + eC = self._energy[ancestor_two] + eRD = self._energy[ancestor_three] + #print (eLU, ancestor_one), (eC, ancestor_two), (eRD, ancestor_three) # find min distance and its associated vertex - dist, from_vertex = min((self._distTo[left_up_diagonal_pixel] + eLU, left_up_diagonal_pixel), (self._distTo[up_pixel] + eC, up_pixel), (self._distTo[right_up_diagonal_pixel] + eRD, right_up_diagonal_pixel)) - #e, vertex = min([(eC, up_pixel), (eLU, left_up_diagonal_pixel), (eRD, right_up_diagonal_pixel)]) + dist, from_vertex = min((self._distTo[ancestor_one] + eLU, ancestor_one), (self._distTo[ancestor_two] + eC, ancestor_two), (self._distTo[ancestor_three] + eRD, ancestor_three)) + #e, vertex = min([(eC, ancestor_two), (eLU, ancestor_one), (eRD, ancestor_three)]) self._edgeTo[pixel] = from_vertex self._distTo[pixel] = dist From 5570215dd7df16e42208b559e33f198b3bfccc8c Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Fri, 11 Oct 2013 15:55:16 -0400 Subject: [PATCH 15/16] Just a little log message --- SeamCarverLib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SeamCarverLib.py b/SeamCarverLib.py index 119e1bf..493f300 100644 --- a/SeamCarverLib.py +++ b/SeamCarverLib.py @@ -29,6 +29,8 @@ def energy(self, col, row): """return energy of pixel in (col, row)""" if self._isValid(col, row): return self._energy[self._toLinear(col, row)] + else: + print "invalid coordinates to energy: %s %s" % (col, row) def findSeam(self, direction): """return vertical seam in image""" From 50696e41de7aee9c08ce8f5c38b9e9119cf9c04e Mon Sep 17 00:00:00 2001 From: Allison Kaptur Date: Fri, 11 Oct 2013 15:55:32 -0400 Subject: [PATCH 16/16] fix to earlier commit --- SeamCarverUtilities.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/SeamCarverUtilities.py b/SeamCarverUtilities.py index 6245dda..9837274 100644 --- a/SeamCarverUtilities.py +++ b/SeamCarverUtilities.py @@ -18,8 +18,10 @@ def printSeam(sc, direction): def calculateSeamEnergy(sc, direction): seam = sc.findSeam(direction) - relevant_size = sc._height if direction == "vertical" else sc._width - seam_indices = zip(seam, relevant_size) + if direction == "vertical": + seam_indices = zip(seam, range(sc._height)) + else: + seam_indices = zip(range(sc._width), seam) totalSeamEnergy = sum(sc.energy(col, row) for col, row in seam_indices) print "\nTotal seam energy: {:d}".format(totalSeamEnergy) return totalSeamEnergy