Katherine
Katherine

Reputation: 153

How to change the color of 4 pixels in an image, multiple times using opencv?

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

Answers (1)

ypnos
ypnos

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:

  1. 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.

  2. In general try to test your programs with non-square images, it is a common pitfall to only test with square-sized images

  3. 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

  4. 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):
            …
    
  5. 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

Related Questions