@@ -48,7 +48,27 @@ def findVerticalSeam(self):
48
48
49
49
def findHorizontalSeam (self ):
50
50
"return horizontal seam in image"
51
- pass
51
+ # tranpose dimensions
52
+ self ._exchDims ()
53
+
54
+ # horizontal seam = sequence of rows; seam[0] is row of col 0
55
+ # col-indexed seam
56
+ seam = [- 1 for _ in range (self ._height )]
57
+ self ._buildGraph (transposed = True )
58
+ row = self ._height - 1
59
+ v = self ._edgeTo [self ._sink ]
60
+ while (v != self ._source ):
61
+ seam [row ] = v % self ._width # seam[row] = col
62
+ v = self ._edgeTo [v ]
63
+ row -= 1
64
+ self ._exchDims ()
65
+ return seam
66
+
67
+ def _exchDims (self ):
68
+ "exchange self._width and self._height"
69
+ swap = self ._width
70
+ self ._width = self ._height
71
+ self ._height = swap
52
72
53
73
def _toLinear (self , col , row ):
54
74
"converts pixel from (col, row) to single index"
@@ -64,7 +84,7 @@ def _toGrid(self, num):
64
84
65
85
def _isValid (self , col , row = None ):
66
86
if row is None :
67
- if (col < 0 ) or (col > self ._width * self ._height ):
87
+ if (col < 0 ) or (col > self ._width * self ._height - 1 ):
68
88
return False
69
89
else :
70
90
return True
@@ -74,7 +94,7 @@ def _isValid(self, col, row=None):
74
94
else :
75
95
return True
76
96
77
- def _buildGraph (self ):
97
+ def _buildGraph (self , transposed = False ):
78
98
"pixels are nodes; edges define precedence constraints in a seam"
79
99
80
100
# for row 0 pixels: distTo[] is 0; edgeTo[] is _source vertex
@@ -89,45 +109,58 @@ def _buildGraph(self):
89
109
for v in range (self ._width , self ._num_pixels ):
90
110
if (v % self ._width == 0 ):
91
111
# pixel is on left edge
92
- self ._edgeTodistTo (v , edgeL = True )
112
+ self ._edgeTodistTo (v , transposed = transposed , edgeL = True )
93
113
elif (v % self ._width == self ._width - 1 ):
94
114
# pixel is on right edge
95
- self ._edgeTodistTo (v , edgeR = True )
115
+ self ._edgeTodistTo (v , transposed = transposed , edgeR = True )
96
116
else :
97
- self ._edgeTodistTo (v )
117
+ self ._edgeTodistTo (v , transposed = transposed )
98
118
# for sink vertex
99
119
index , min_energy = min (enumerate (self ._distTo [self ._num_pixels - self ._width :self ._num_pixels ]), key = lambda (x , y ): y )
100
120
self ._distTo [self ._sink ] = min_energy
101
- self ._edgeTo [self ._sink ] = (self ._height - 1 ) * self ._width + index
121
+ self ._edgeTo [self ._sink ] = (self ._height - 1 ) * self ._width + index
102
122
103
123
104
- def _edgeTodistTo (self , v , edgeL = False , edgeR = False ):
124
+ def _edgeTodistTo (self , v , edgeL = False , edgeR = False , transposed = False ):
105
125
# returns pixel connected to v with min energy
126
+
106
127
if edgeL :
107
128
# left edge
108
129
vC = v - self ._width
109
- vR = v - self ._width + 1
110
- vL = vC
130
+ vRD = v - self ._width + 1
131
+ vLU = vC
111
132
elif edgeR :
112
133
# right edge
113
- vL = v - self ._width - 1
134
+ vLU = v - self ._width - 1
114
135
vC = v - self ._width
115
- vR = vC
136
+ vRD = vC
116
137
else :
117
138
# pixels connect to v
118
- vL = v - self ._width - 1
139
+ vLU = v - self ._width - 1
119
140
vC = v - self ._width
120
- vR = v - self ._width + 1
141
+ vRD = v - self ._width + 1
121
142
# energy of pixels connected to v
122
- eL = self ._energy [vL ]
123
- eC = self ._energy [vC ]
124
- eR = self ._energy [vR ]
125
- if eL <= min (eC , eR ):
126
- self ._edgeTo [v ] = vL
127
- self ._distTo [v ] = self ._distTo [vL ] + eL
128
- elif eR <= min (eL , eC ):
129
- self ._edgeTo [v ] = vR
130
- self ._distTo [v ] = self ._distTo [vR ] + eR
143
+ if transposed :
144
+ (colU , rowU ) = self ._toGrid (vLU )
145
+ (colC , rowC ) = self ._toGrid (vC )
146
+ (colD , rowD ) = self ._toGrid (vRD )
147
+ # read energy
148
+ eLU = self ._energy [self ._height * colU + rowU ]
149
+ eC = self ._energy [self ._height * colC + rowC ]
150
+ eRD = self ._energy [self ._height * colD + rowD ]
151
+
152
+ else :
153
+ # read energy directly from energy array
154
+ eLU = self ._energy [vLU ]
155
+ eC = self ._energy [vC ]
156
+ eRD = self ._energy [vRD ]
157
+
158
+ if eLU <= min (eC , eRD ):
159
+ self ._edgeTo [v ] = vLU
160
+ self ._distTo [v ] = self ._distTo [vLU ] + eLU
161
+ elif eRD <= min (eLU , eC ):
162
+ self ._edgeTo [v ] = vRD
163
+ self ._distTo [v ] = self ._distTo [vRD ] + eRD
131
164
else :
132
165
self ._edgeTo [v ] = vC
133
166
self ._distTo [v ] = self ._distTo [vC ] + eC
0 commit comments