web-dev-qa-db-fra.com

Trouver la couleur rouge en utilisant Python & OpenCV

J'essaie d'extraire la couleur rouge d'une image. J'ai un code qui applique un seuil pour ne laisser que les valeurs de la plage spécifiée:

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)

Mais, comme je l'ai vérifié, le rouge peut avoir une valeur de teinte dans la plage, disons de 0 à 10, ainsi que dans la plage de 170 à 180. Par conséquent, je voudrais laisser des valeurs de l'une de ces deux plages. J'ai essayé de définir un seuil de 10 à 170 et d'utiliser la fonction cv2.bitwise_not, mais j'ai également obtenu toute la couleur blanche. Je pense que la meilleure option serait de créer un masque pour chaque gamme et de les utiliser tous les deux, donc je dois en quelque sorte les réunir avant de continuer.

Existe-t-il un moyen de joindre deux masques à l'aide d'OpenCV? Ou existe-t-il un autre moyen d'atteindre mon objectif?

Éditer. Je suis venu avec une solution peu élégante mais fonctionnelle:

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]

Cela répond à peu près à mes besoins, et les fonctions d'OpenCV font probablement à peu près la même chose, mais s'il y a une meilleure façon de le faire (en utilisant une fonction dédiée et en écrivant moins de code), partagez-la avec moi. :)

16
yolo77

Je voudrais simplement ajouter les masques ensemble et utiliser np.where pour masquer l'image d'origine.

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

Cela devrait être beaucoup plus rapide et beaucoup plus lisible que de parcourir chaque pixel de votre image.

20
derricw

Jouez avec ça.

#blurring and smoothin
img1=cv2.imread('marathon.png',1)

hsv = cv2.cvtColor(img1,cv2.COLOR_BGR2HSV)

#lower red
lower_red = np.array([0,50,50])
upper_red = np.array([10,255,255])


#upper red
lower_red2 = np.array([170,50,50])
upper_red2 = np.array([180,255,255])

mask = cv2.inRange(hsv, lower_red, upper_red)
res = cv2.bitwise_and(img1,img1, mask= mask)


mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
res2 = cv2.bitwise_and(img1,img1, mask= mask2)

img3 = res+res2
img4 = cv2.add(res,res2)
img5 = cv2.addWeighted(res,0.5,res2,0.5,0)


kernel = np.ones((15,15),np.float32)/225
smoothed = cv2.filter2D(res,-1,kernel)
smoothed2 = cv2.filter2D(img3,-1,kernel)





cv2.imshow('Original',img1)
cv2.imshow('Averaging',smoothed)
cv2.imshow('mask',mask)
cv2.imshow('res',res)
cv2.imshow('mask2',mask2)
cv2.imshow('res2',res2)
cv2.imshow('res3',img3)
cv2.imshow('res4',img4)
cv2.imshow('res5',img5)
cv2.imshow('smooth2',smoothed2)




cv2.waitKey(0)
cv2.destroyAllWindows()
0
dxVxb