RJ Uy
RJ Uy

Reputation: 397

Change ALL gray scale image pixel with white if gray value is in the list without a list

I have a gray scale image and a list of gray scale value as defined below:

grayImg= cv2.imread(file,0)
grayList = [102, 103, 104, 105, 106, 107, 108, 109, 
            110, 111, 112, 113, 114, 115]

Now I want to change ALL pixels of the grayImg to "white or 255" if the gray scale value belongs to my grayList without a loop. How can I do this in a NumPyish way?

Upvotes: 1

Views: 446

Answers (4)

Mark Setchell
Mark Setchell

Reputation: 207465

Here is another way, using a Lookup Table, or LUT. It is just an 8-bit, 256-element array of values in which you look-up the current pixel values to find the new value.

My LUT looks like this - hopefully you can see your values in the range 102..115 map to 255:

array([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,
        13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
        26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
        39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,
        52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
        65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,
        78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
        91,  92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 255, 255,
       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 116,
       117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
       130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
       143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
       156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
       169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
       182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
       195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
       208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
       221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
       234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
       247, 248, 249, 250, 251, 252, 253, 254, 255], dtype=uint8)

I did some timing to compare it against np.isin() and it comes out 3-8x faster depending on the size of the input array, specifically 3 times faster for input array 64x64 and 8 times faster for 640x640:

#!/usr/bin/env python3

import cv2
import numpy as np


def useLUT(im, grayList):
    """Make LUT and apply to image"""
    LUT = np.arange(256, dtype=np.uint8)    # Straight no-op LUT 0..255
    LUT[grayList] = 255                     # Values in list get changed to 255
    res = cv2.LUT(im, LUT)                  # Apply LUT
    return res

def useIsin(im, grayList):
    """Make pixels in grayList into white"""
    im[np.isin(im, grayList)] = 255
    return im

# Load image as greyscale
im = cv2.imread('image640.png',0)

# Your graylist
grayList = [102,103,104,105,106,107,108,109,110,111,112,113,114,115]

# Time and compare results
%timeit resA = useIsin(im, grayList)
%timeit resB = useLUT(im, grayList)

Result

13.4 ms ± 122 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.5 ms ± 95.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

I applied it to this input image:

enter image description here

Here is the result:

enter image description here

Upvotes: 1

Nicolas Gervais
Nicolas Gervais

Reputation: 36624

This will change all the pixels of grayImg that are in grayList to 255. Can't think of a shorter way to do it.

grayImg[np.isin(grayImg, grayList)] = 255
array([[255,  87,  52, ..., 245,   2, 236],
       [ 20, 255, 255, ...,  33, 205,  15],
       [255,  81, 255, ...,  17, 255, 255],
       ...,
       [236, 255, 255, ..., 217,  15, 255],
       [255, 221,  39, ...,  88, 240,  46],
       [ 17, 219, 224, ..., 255, 255, 204]])

Upvotes: 2

Code Pope
Code Pope

Reputation: 5449

Use in1d:

grayImg= np.array([0,3,5,102,106,4,56,107])
grayList = np.array([102,103,104,105,106,107,108,109,110,111,112,113,114,115])

grayImg[np.in1d(grayImg, grayList)] = 255

Ouptut grayImg:

array([  0,   3,   5, 255, 255,   4,  56, 255])

Upvotes: 1

Meto
Meto

Reputation: 658

grayImg[np.where((gray<min(grayList)) & (gray>max(grayList)))] = 255

should work if you mean a continious interval.

Upvotes: 0

Related Questions