Python – Finding contours of different colors on an image

Question:

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?

Asked By: Jonathan

||

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.

Answered By: Headcrab
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.