Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - Finding contours of different colors on an image

I have the following image: enter image description here

I used the following code to outline all the round blobs in this image using this code:

import numpy as np
import cv2

im = cv2.imread('im.jpg')

imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,200,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(im,contours,-1,(0,0,255),1)

#(B,G,R)

cv2.imshow('image',im)
cv2.waitKey(0)
cv2.destroyAllWindows()

And it produces this image: enter image description here

Which is great for the first step. But I'm having a really hard time drawing a different colored outline for the blue colored blobs. I tried using multiple contours:

import numpy as np
import cv2

im = cv2.imread('im.jpg')

imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,200,255,0)
ret, thresh2 = cv2.threshold(imgray,130,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
contours2, hierarchy2 = cv2.findContours(thresh2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

cv2.drawContours(im,contours,-1,(0,0,255),1)
cv2.drawContours(im,contours2,-1,(0,255,0),1)

#(B,G,R)

cv2.imshow('image',im)
cv2.waitKey(0)
cv2.destroyAllWindows()

and the image comes out like this: enter image description here

The first problem with this approach is the fact that it doesn't accurately only outline the blue blobs. Moreover, the sensitivity rating in the threshold function would have to be modified for each image depending on lighting, etc. Is there a smoother way to do this?

like image 665
Jonathan Avatar asked Jul 14 '17 06:07

Jonathan


1 Answers

Based on this:

import cv2
import numpy as np

img = cv2.imread("bluepink.jpg")
imghsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
mask_blue = cv2.inRange(imghsv, lower_blue, upper_blue)
_, contours, _ = cv2.findContours(mask_blue, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
im = np.copy(img)
cv2.drawContours(im, contours, -1, (0, 255, 0), 1)
cv2.imwrite("contours_blue.png", im)

enter image description here

Not ideal, but there seem to be no false positives. And you can probably improve it by adding another near-black color range (as really dark color is only present inside those bluish blobs). Maybe with some additional dilate-eroding, it never hurts to dilate-erode.

like image 101
Headcrab Avatar answered Oct 14 '22 06:10

Headcrab