How to Change a Pixel Color in Python using OpenCV and NumPy
When editing images in Python using OpenCV, you are working directly with NumPy arrays. A frequent issue developers encounter is attempting to modify a pixel by assigning it to a local variable first, only to find the image remains completely unchanged.
The Cause of the Problem: Variable Rebinding
In Python, extracting a pixel value from a NumPy array and assigning it to a variable creates a reference or a separate copy of that pixel's value:
aCertainPixel = imgRGB[242, 71]
aCertainPixel = (255, 0, 0) # This reassigns the variable, NOT the image array!Executing aCertainPixel = (255, 0, 0) simply rebinds the local variable aCertainPixel to a new RGB tuple. It does not perform an in-place mutation on the underlying imgRGB array.
The Solution: Direct Index Assignment
To modify the image data, you must perform the assignment directly on the NumPy array index using coordinate notation img[y, x] = [R, G, B] or img[row, col] = [R, G, B]:
# Directly set pixel at row 242, column 71 to Red
imgRGB[242, 71] = [255, 0, 0]Complete Working Example
Here is the corrected and clean solution using OpenCV and Matplotlib:
import cv2 as cv
import matplotlib.pyplot as plt
def readAndWriteImage():
imPath = 'C:\\Body Type Examination App\\Images\\IMG_9991.jpeg'
img = cv.imread(imPath)
# OpenCV loads images in BGR format by default. Convert to RGB for Matplotlib.
imgRGB = cv.cvtColor(img, cv.COLOR_BGR2RGB)
# Change the target pixel directly in the array
imgRGB[242, 71] = [255, 0, 0]
plt.figure()
plt.imshow(imgRGB)
plt.show()
if __name__ == '__main__':
readAndWriteImage()Key Tips for OpenCV Pixel Manipulation
- Color Order Matters: OpenCV loads images in BGR order by default. If you modify a pixel before converting to RGB, red is
[0, 0, 255]. After converting to RGB, red is[255, 0, 0]. - Modifying Regions (Slicing): If you want to color a region instead of a single tiny pixel (which can be hard to see on high-resolution photos), use array slicing:
# Draws a 10x10 red box starting at pixel (242, 71) imgRGB[242:252, 71:81] = [255, 0, 0] - Performance: Always use NumPy indexing or vectorized operations rather than looping over pixels using pure Python loops for optimal speed.