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.