Reputation: 153
I'm trying to write a program that will convert a 480x480 image into 240x240 quality, by taking the average color of 4 pixels and replacing all 4 with that average color. Then I repeat this for all 2x2 squares in the image. My program so far keeps replacing the entire image with the average color from the top left corner 4 squares, which is bgr [150, 138, 126]. Can someone help me see what I'm doing wrong?
def get_square(x1, x2, y1, y2):
square = image[x1:x2, y1:y2]
return square
def bgr_vals(img):
b_vals, g_vals, r_vals = [], [], []
x, y = 0, 0
for i in range(4):
b, g, r = image[x][y]
b_vals.append(b)
g_vals.append(g)
r_vals.append(r)
if y != 1:
y += 1
elif x == 0 and y == 1:
x += 1
elif x == 1 and y == 1:
y -= 1
return b_vals, g_vals, r_vals
def avg_color(bgr_vals):
b_avg = np.average(bgr_vals[0])
g_avg = np.average(bgr_vals[1])
r_avg = np.average(bgr_vals[2])
return [b_avg, g_avg, r_avg]
image = cv2.imread('src.jpg')
y1, y2 = 0, 2
for i in range(240):
x1, x2 = 0, 2
for i in range(240):
patch = get_square(x1, x2, y1, y2)
bgr_colors = bgr_vals(patch)
color = avg_color(bgr_colors)
image[x1:x2, y1:y2] = color
x1 += 2
x2 += 2
y1 += 2
y2 += 2
Thanks!
Upvotes: 0
Views: 251
Reputation: 52407
In your function bgr_vals
you take argument img
(which is the current patch), but within the method you inadvertently access image
(the whole image) in this line:
b, g, r = image[x][y]
Your script works fine when you fix this typo.
Here are some tips for the future:
Images in OpenCV (and most libraries) are stored in row-first order, this means that you should write image[y][x]
or img[y][x]
. In your case it doesn't matter but in future work it might.
In general try to test your programs with non-square images, it is a common pitfall to only test with square-sized images
When you have cascaded loops, don't use the same variable name in the loop (you used i both times). Again, in your case it doesn't matter but as soon as you would use the value of i
the confusion would start
Instead of increasing x, y within the loop you can use the loop variable directly, by getting a range with a step:
for y in range(0, 480, 2):
for x in range(0, 480, 2):
…
Use array shape instead of hard-coding dimensions:
for y in range(0, image.shape[0], 2):
for x in range(0, image.shape[1], 2):
…
Upvotes: 1