2 votes

Filtrer les pixels en fonction de plusieurs conditions

J'ai un morceau de code comme ci-dessous :

import cv2
import numpy as np
import operator
from functools import reduce

image = cv2.imread("<some image path>")
bgr   = np.int16(image)

h, w, _ = image.shape
mask    = np.zeros((h, w), np.uint8)

# Get all channels
blue  = bgr[:,:,0]
green = bgr[:,:,1]
red   = bgr[:,:,2]

rules = np.where(reduce(operator.and_, [(red > 100), (red > green), (red > blue)]

# Create mask using above rules
mask[rules] = 255

### Then use cv2.findContours ...

Ce morceau de code ne s'exécute pas aussi vite que je l'espérais. Je pense que je peux le rendre plus rapide en appliquant toutes les conditions une par une, c'est à dire :

rule_1 = np.where(red > 100)
rule_2 = np.where(red[rule_1] > green)
rule_3 = np.where(red[rule_2] > blue)

mask[rule_3] = 255

La méthode ci-dessus peut-elle accélérer mon code ? Et comment le faire ? Merci beaucoup !

3voto

Johannes Kasimir Points 147

Un bon moyen est (adapté du commentaire de Cris Luengo)

mask = 255 * ((red > 100) & (red > green) & (red > blue)) 

mais si vous avez besoin de plus de rapidité, vous pouvez utiliser Numba

from numba import jit, prange

@jit(nopython=True, parallel=True) 
def red_dominates(rgb, mask):
    M, N, _ = rgb.shape
    for i in prange(M):
        for j in prange(N):
            r = rgb[i,j,0]
            g = rgb[i,j,1]
            b = rgb[i,j,2]
            mask[i,j] = 255 * ((r > 100) & (r > g) & (r > b))
    return mask

Remarquez que prange est utilisé à la place de range . Cela indique à Numba que les boucles sont parallélisables.

Sur mon ordinateur, la version Numba est environ 3x plus rapide.

>>> bgr = np.int16(255 * np.random.random((100, 100, 3)))
>>> w = np.ones(bgr.shape[:2], np.uint8)
>>> %timeit red_dominates(bgr, w)
13.7 µs ± 26.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
>>> %timeit 255 * ((bgr[:,:,0] > 100) & (bgr[:,:,0] > bgr[:,:,1]) & (bgr[:,:,0] > bgr[:,:,2]))
46.3 µs ± 208 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Bonne chance !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X