In python I have a list of contours (each holding x, y, w, and h integers), I need to somehow iterate over the list and check, if the current x + w is greater than the last x + w by less than 3 (which mean by 1 or 2) remove the current one, otherwise keep going.
I have this for now:
contours_v2 = [[551, 0, 2, 1], [491, 0, 1, 1], [484, 0, 6, 1], [482, 0, 1, 1], [480, 0, 1, 1], [400, 0, 6, 1], [321, 0, 6, 1], [319, 0, 1, 1], [238, 0, 1, 1], [234, 0, 3, 1], [229, 0, 4, 1], [227, 0, 1, 1], [225, 0, 1, 1], [223, 0, 1, 1], [142, 0, 1, 1], [132, 0, 6, 1], [130, 0, 1, 1], [0, 0, 7, 1]]
last_x_w = contours_v2[0][0] + contours_v2[0][2] # Initialize with the first contour's x + w value
i = 1 # Start with the second contour
while i < len(contours_v2):
current_x_w = contours_v2[i][0] + contours_v2[i][2]
if abs(last_x_w - current_x_w) < 4:
contours_v2.pop(i)
else:
last_x_w = current_x_w
i += 1
I Need a few things:
If I move the i += 1
into the else
statement, the resulting list will be (input list was the example I provided):
# As you can see, the item didn't pop and should have popped is
# the one with x = 229, its next one is x = 227
# contours_v2
[[551, 0, 2, 1], [491, 0, 1, 1], [482, 0, 1, 1], [400, 0, 6, 1], [321, 0, 6, 1], [319, 0, 1, 1], [238, 0, 1, 1], [229, 0, 4, 1], [227, 0, 1, 1], [223, 0, 1, 1], [142, 0, 1, 1], [132, 0, 6, 1], [130, 0, 1, 1], [0, 0, 7, 1]]
One way to write shorter (but not necessarily faster) code is
from functools import reduce
contours_v2 = [[551, 0, 2, 1], [491, 0, 1, 1], [484, 0, 6, 1], [482, 0, 1, 1], [480, 0, 1, 1], [400, 0, 6, 1], [321, 0, 6, 1], [319, 0, 1, 1], [238, 0, 1, 1], [234, 0, 3, 1], [229, 0, 4, 1], [227, 0, 1, 1], [225, 0, 1, 1], [223, 0, 1, 1], [142, 0, 1, 1], [132, 0, 6, 1], [130, 0, 1, 1], [0, 0, 7, 1]]
def x_w(c):
return c[0] + c[2]
r = reduce(lambda x, y: x if abs(x_w(x[-1]) - x_w(y)) < 4 else x + [y],
contours_v2[1:], [contours_v2[0]])
print(r)
The initializer of reduce
is a list with the first item of contours_v2
, then for each item of the rest its distance to the last item of the list is checked and by the if-expression either the unmodified list is returned by the lambda or a new list with the new item appended is returned.
The code does some things which may be slower than a conventional loop because it may have to repeatedly calculate c[0] + c[2]
for the same c
and it uses something equivalent to x = x + [y]
which is slower than x.append(y)
.