Python - Finding contours of different colors on an image

10,135

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.

Share:
10,135
Jonathan
Author by

Jonathan

Cal, eecs, Go bears!

Updated on July 05, 2022

Comments

  • Jonathan
    Jonathan almost 2 years

    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?