J'ai une image en échelle de gris et une liste de valeurs d'échelle de gris comme défini ci-dessous:

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

Maintenant, je veux changer TOUS les pixels de grayImg en "blanc ou 255" si la valeur de l'échelle de gris appartient à ma grayList sans boucle. Comment puis-je faire cela de manière NumPyish?

1
RJ Uy 20 mai 2020 à 14:26

5 réponses

Meilleure réponse

Cela changera tous les pixels de grayImg qui sont dans grayList en 255. Je ne peux pas penser à un moyen plus court de le faire.

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]])
2
Mark Setchell 20 mai 2020 à 11:57

Utilisez 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

Sortie grayImg:

array([  0,   3,   5, 255, 255,   4,  56, 255])
1
Code Pope 20 mai 2020 à 11:47

Voici une autre façon, en utilisant une table de recherche, ou LUT. Il s'agit simplement d'un tableau de valeurs de 8 bits et 256 éléments dans lequel vous recherchez les valeurs de pixels actuelles pour trouver la nouvelle valeur.

Ma LUT ressemble à ceci - j'espère que vous pouvez voir vos valeurs dans la plage 102..115 mapper à 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)

J'ai fait un timing pour le comparer à np.isin() et il sort 3 à 8 fois plus vite en fonction de la taille du tableau d'entrée, en particulier 3 fois plus rapide pour le tableau d'entrée 64x64 et 8 fois plus rapide pour 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)

Résultat

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)

Je l'ai appliqué à cette image d'entrée:

enter image description here

Voici le résultat:

enter image description here

1
Mark Setchell 20 mai 2020 à 13:31
grayImg[np.where((gray<min(grayList)) & (gray>max(grayList)))] = 255

Devrait fonctionner si vous entendez un intervalle continu.

0
Meto 20 mai 2020 à 11:43

Une manière simple de faire est de parcourir et de remplacer:

for pix in grayList:
    grayImg[grayImg == pix] = 255
0
hbFree 20 mai 2020 à 11:44