Encontrando color rojo usando Python y OpenCV

Estoy tratando de extraer el color rojo de una imagen. Tengo un código que aplica un umbral para dejar solo valores de un rango específico:

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) 

Pero, como comprobé, el rojo puede tener un valor de Tono en el rango, digamos de 0 a 10, así como en un rango de 170 a 180. Por lo tanto, me gustaría dejar valores de cualquiera de esos dos rangos. Intenté establecer el umbral de 10 a 170 y usar la función cv2.bitwise_not, pero también obtengo todo el color blanco. Creo que la mejor opción sería crear una máscara para cada rango y usarlas, así que de alguna manera tengo que unirlas antes de continuar.

¿Hay alguna manera de unirme a dos máscaras usando OpenCV? ¿O hay alguna otra forma en que podría lograr mi objective?

Editar. Vine con no mucho elegante, pero solución de trabajo:

 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] =170): image_result[i][j]=img_hsv[i][j] 

Satisface bastante mis necesidades, y las funciones de OpenCV probablemente hacen casi lo mismo, pero si hay una mejor manera de hacerlo (utilizando alguna función dedicada y escribiendo menos código), compártala conmigo. 🙂

Simplemente agregaría las máscaras y usaría np.where para enmascarar la imagen original.

 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 

Esto debería ser mucho más rápido y más legible que recorrer cada píxel de su imagen.

Juega con esto.

 #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()