How to change the value of one RGB channel in Python with cv2?

Question:

So I am trying to change the values of one RGB channel in cv2 by splitting it by pixel and then adding or substracting a value. This would make a pixel "greener" or "reder" in theory. But instead it is not working. Do you know what is the problem?
Original image:

Desired Output

Current Output

This is my code:

import numpy
import dlib
import cv2

image = cv2.imread("image.jpeg")
num = 1

x_max, y_max, rgba = image.shape

for x in range(x_max):
    num += 1
    for y in range(y_max):
        b, g, r = image[x, y]
        image[x:x_max, y:y_max] = b, g+100, r


while True:
    cv2.imshow("Output", image)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()
Asked By: Emilio Garcia

||

Answers:

When you index with image[y,x] you’re getting a 3-element list [b,g,r]. If you want to add 100 to the red channel then you can index the color directly and add the number image[y,x,2].

However, when you add scalar values directly to the colors like this, there’s nothing protecting you from overflowing the UInt8 value. If it goes over 255 it’ll wrap back around to zero. You can either manually do the overflow check yourself or use OpenCV’s cv2.add() function.

import cv2
import numpy as np

# load image
img = cv2.imread("test.jpg");
orig = np.copy(img);

# create blank image
red = np.zeros_like(img);

# fill with red
red[:,:] = [0,0,100]; # (b,g,r)

# add to image (has overflow protection, values are clamped between [0,255])
img = cv2.add(img, red);

# show
cv2.imshow("Original", orig);
cv2.imshow("OpenCV Add", img);
cv2.waitKey(0);

# do it with loops
img = np.copy(orig);
unprotected = np.copy(orig);
height, width = img.shape[:2];

# loop through and add 100 red to each pixel
# WARNING, this method has no automatic overflow protection
# if the red value goes over 255 then it'll wrap back around to 0 (i.e. 200 + 100 will give 45)
for y in range(height):
    for x in range(width):
        # overflow check
        if 100 + img[y,x,2] > 255:
            # saturate value
            img[y,x,2] = 255;
        else:
            # add normally
            img[y,x,2] += 100;

        # always add to unprotected image
        unprotected[y,x,2] += 100;

# show
cv2.imshow("Looping Add", img);
cv2.imshow("Unprotected", unprotected);
cv2.waitKey(0);

Overflow Protected

enter image description here

No Overflow Protection

enter image description here

Answered By: Ian Chu