2015-05-19 20 views
13

Ich versuche, rote Farbe aus einem Bild zu extrahieren. Ich habe Code, den Schwellenwert nur Werte von bestimmtem Bereich zu verlassen gilt:Suche nach roter Farbe mit Python & OpenCV

img=cv2.imread('img.bmp') 
img_hsv=cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 
lower_red = np.array([0,50,50]) #example value 
upper_red = np.array([10,255,255]) #example value 
mask = cv2.inRange(img_hsv, lower_red, upper_red) 
img_result = cv2.bitwise_and(img, img, mask=mask) 

Aber, wie ich überprüfte, rot im Bereich Hue Wert haben, lassen Sie sich von 0 bis 10 sagt, sowie in Bereich von 170 bis 180. Daher möchte ich Werte aus einem dieser beiden Bereiche belassen. Ich habe versucht, den Schwellenwert von 10 auf 170 zu setzen und cv2.bitwise_not zu verwenden, aber dann bekomme ich auch die weiße Farbe. Ich denke, die beste Option wäre, für jeden Bereich eine Maske zu erstellen und sie beide zu verwenden, also muss ich sie irgendwie zusammenfügen, bevor ich fortfahre.

Gibt es eine Möglichkeit, zwei Masken mit OpenCV zu verbinden? Oder gibt es eine andere Möglichkeit, mein Ziel zu erreichen?

Bearbeiten. Ich kam mit nicht viel elegant, aber funktionierende Lösung:

image_result = np.zeros((image_height,image_width,3),np.uint8) 

for i in range(image_height): #those are set elsewhere 
    for j in range(image_width): #those are set elsewhere 
     if img_hsv[i][j][1]>=50 \ 
      and img_hsv[i][j][2]>=50 \ 
      and (img_hsv[i][j][0] <= 10 or img_hsv[i][j][0]>=170): 
      image_result[i][j]=img_hsv[i][j] 

Es ziemlich befriedigt meine Bedürfnisse und Funktionen des OpenCV wahrscheinlich tun so ziemlich die gleiche, aber wenn es eine bessere Art und Weise ist, dass (mit einiger speziellen Funktion zu tun und schreibe weniger code) bitte teile es mit mir. :)

Antwort

15

Ich würde nur die Masken zusammen, und verwenden Sie np.where, um das Originalbild zu maskieren.

img=cv2.imread("img.bmp") 
img_hsv=cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 

# lower mask (0-10) 
lower_red = np.array([0,50,50]) 
upper_red = np.array([10,255,255]) 
mask0 = cv2.inRange(img_hsv, lower_red, upper_red) 

# upper mask (170-180) 
lower_red = np.array([170,50,50]) 
upper_red = np.array([180,255,255]) 
mask1 = cv2.inRange(img_hsv, lower_red, upper_red) 

# join my masks 
mask = mask0+mask1 

# set my output img to zero everywhere except my mask 
output_img = img.copy() 
output_img[np.where(mask==0)] = 0 

# or your HSV image, which I *believe* is what you want 
output_hsv = img_hsv.copy() 
output_hsv[np.where(mask==0)] = 0 

Dies sollte durch jedes Pixel des Bildes viel schneller und viel besser lesbar als Looping.

+3

Falls jemand interessiert. Ich arbeite mit eingebetteten Geräten wie Raspberry Pi. Nächste Operation ID sehr schwer für solche Geräte: output_img [np.where (mask == 0)] = 0. Es kann mit viel schneller eins ersetzt werden: output_img = cv2.bitwise_and (output_img, output_img, mask = mask) –