Home > Enterprise >  How to effectively loop through each pixel for saving time with numpy?
How to effectively loop through each pixel for saving time with numpy?

Time:12-03

As you know looping through each pixels and accessing their values with opencv takes too long. As a beginner I'm trying to learn opencv myself when I tried this approach it took me around 7-10 seconds of time to loop through image and perform operations.

code is as below

original_image = cv2.imread(img_f)

image = np.array(original_image)
for y in range(image.shape[0]):
    for x in range(image.shape[1]):
        # remove grey background
        if 150 <= image[y, x, 0] <= 180 and \
                150 <= image[y, x, 1] <= 180 and \
                150 <= image[y, x, 2] <= 180:
            image[y, x, 0] = 0
            image[y, x, 1] = 0
            image[y, x, 2] = 0

        # remove green dashes
        if image[y, x, 0] == 0 and \
                image[y, x, 1] == 169 and \
                image[y, x, 2] == 0:
            image[y, x, 0] = 0
            image[y, x, 1] = 0
            image[y, x, 2] = 0

in above code i'm just trying to remove grey and green pixel colors.

I found similar question asked here but im not able to understand how to use numpy in my usecase as i'm beginner in python and numpy.

Any help or suggestion for solving this will be appreciated thanks

CodePudding user response:

You can take advantage of NumPy's vectorized operation to eliminate all loops which should be much faster.

# Remove grey background
is_grey = ((150 <= image) & (image <= 180)).all(axis=2, keepdims=True)
image = np.where(is_grey, 0, image)

# Remove green dashes
is_green_dash = (image[..., 0] == 0) & (image[..., 1] == 169) & (image[..., 2] == 0)
is_green_dash = is_green_dash[..., np.newaxis]  # append a new dim at the end
image = np.where(is_green_dash, 0, image)

Both invocations of np.where rely on NumPy's broadcasting.

CodePudding user response:

You can apply numpy filtering to image. In your scenario it would be:

mask_gray = (
    (150 <= image[:, :, 0]) & (image[:, :, 0] <= 180) & 
    (150 <= image[:, :, 1]) & (image[:, :, 1] <= 180) & 
    (150 <= image[:, :, 2]) & (image[:, :, 2] <= 180)
)

image[mask_gray] = 0

mask_green = (
    (image[:, :, 0] == 0) &
    (image[:, :, 1] == 169) &
    (image[:, :, 2] == 0)
)

image[mask_green] = 0

mask_gray and mask_green here are boolean masks

CodePudding user response:

One way to improve the performance of your code would be to use the cv2.inRange() function to find pixels with the desired colors, and then use the cv2.bitwise_and() function to remove those pixels from the image. This can be done more efficiently than looping through each pixel individually, which can be slow and computationally intensive. Here is an example of how this could be implemented:

import cv2
import numpy as np

# Read the image
original_image = cv2.imread('image.jpg')

# Define the colors to be removed as ranges of BGR values
grey_min = np.array([150, 150, 150], np.uint8)
grey_max = np.array([180, 180, 180], np.uint8)
green_min = np.array([0, 0, 0], np.uint8)
green_max = np.array([0, 169, 0], np.uint8)

# Use inRange() to find pixels with the desired colors
grey_mask = cv2.inRange(original_image, grey_min, grey_max)
green_mask = cv2.inRange(original_image, green_min, green_max)

# Use bitwise_and() to remove the pixels with
  • Related