简体   繁体   中英

Find pixel with specific values in its all 3-channel in an image

I have an image of 3 channels. I have pixel values of 3 channels that if a pixel has these 3 values in its 3 channels then it belongs to class 'A'. For example

classes_channel = np.zeros((image.shape[0], image.shape[1], num_classes))
pixel_class_dict={'0': [128, 64, 128], '1': [230, 50, 140]} #num_classes=2
for channel in range(num_classes):
    pixel_value= pixel_class_dict[str(channel)]
    for i in range(image.shape[0]):
        for j in range(image.shape[1]):
            if list(image[i][j])==pixel_value:
                classes_channel[i,j,channel]=1

Basically I want to generate an array of channels equal to number of classes with each class separate in a particular channel. Is there any efficient way to do this?

You could use numpy's broadcasting to check more efficiently whether any value in the channels matches another value:

>>> a=np.arange(2*3).reshape(2,3)
>>> a
array([[0, 1, 2],
       [3, 4, 5]])
>>> a == 4
array([[False, False, False],
       [False,  True, False]])

This way you can create binary masks. And those you can combine with boolean operators, like np.logical_and and np.logical_or :

>>> b = a == 4
>>> c = a == 0
>>> np.logical_and(b, c)
array([[False, False, False],
       [False, False, False]])
>>> np.logical_or(b, c)
array([[ True, False, False],
       [False,  True, False]])

In your case, you could loop over the classes of pixel values, and compare the different channels:

>>> pixel_class_dict = {1: [18, 19, 20], 2: [9,10,11]}
>>> a = np.arange(2*4*3).reshape(2,4,3)
>>> b = np.zeros((a.shape[:2]), dtype=np.int)
>>> for pixel_class, pixel_values in pixel_class_dict.items():
...     mask = np.logical_and(*(a[..., channel] == pixel_values[channel] 
...       for channel in range(a.shape[-1])))
...     b += pixel_class*mask
...
>>> b
array([[0, 0, 0, 2],
       [0, 0, 1, 0]])

This last part works because you can multiply a number with a boolean value ( 4*True == 4 and 3*False == 0 and because I'm assuming each of the pixel values in your dictionary is unique. If the latter doesn't hold, you'll sum up the class identifiers.

A slightly shorter approach would be to reshape the starting array:

>>> b = np.zeros((a.shape[:2]), dtype=np.int)
>>> a2 = a.reshape(-1, 3)
>>> for pixel_class, pixel_values in pixel_class_dict.items():
...     mask = (np.all(a2 == pixel_values, axis=1)
...             .reshape(b.shape))
...     b += mask * pixel_class
...
>>> b
array([[0, 0, 0, 4],
       [0, 0, 2, 0]])

Found another solution: Here image is the image (with 3 channels) to which we want to

import numpy as np
import cv2
for class_id in pixel_class_dict:
    class_color = np.array(pixel_class_dict[class_id])
    classes_channel[:, :, int(class_id)] = cv2.inRange(image,class_color,class_color).astype('bool').astype('float32')                                  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM