3

I am running blob detection on a camera image of circular objects, using OpenCV 2.4.9. I run a number of standard filters on the image (blur, adaptive threshold, skeletonization using skimage routines, and dilation of the skeleton), and would like to identify blobs (contiguous black areas) on the result. There is SimpleBlobDetector just for that, but however I set its parameters, it is not doing what I would like to.

This is the original image: caputred image

and this is the processed version, with keypoints from the detector drawn in yellow: skeletonization

The keypoints don't seem to respect area constraints, and also don't appear where I would expect them.

The script looks like the following, is there something obviously wrong? Or any other suggestions?

import numpy as np
import cv2
import skimage, skimage.morphology

img0=cv2.imread('capture_b_07.cropped.png')
img1=cv2.cvtColor(img0,cv2.COLOR_BGR2GRAY)
img2=cv2.medianBlur(img1,5)
img3=cv2.bilateralFilter(img2,9,75,75)
img4=cv2.adaptiveThreshold(img3,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,21,0)
img5=skimage.img_as_ubyte(skimage.morphology.skeletonize(skimage.img_as_bool(img4)))
img6=cv2.dilate(img5,cv2.getStructuringElement(cv2.MORPH_RECT,(3,3)),iterations=1)
# blob detection
pp=cv2.SimpleBlobDetector_Params()
pp.filterByColor=True
pp.blobColor=0
pp.filterByArea=True
pp.minArea=500
pp.maxArea=5000
pp.filterByCircularity=True
pp.minCircularity=.4
pp.maxCircularity=1.

det=cv2.SimpleBlobDetector(pp)
keypts=det.detect(img6)
img7=cv2.drawKeypoints(img6,keypts,np.array([]),(0,255,255),cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imwrite('capture_b_07.blobs.png',img7)

Similar pipeline from ImageJ (Analyze Particles, circularity 0.5-1.0, area 500-5000 px^2), which I am trying to reproduce using OpenCV, gives something like this:

imagej blobs

eudoxos
  • 18,545
  • 10
  • 61
  • 110

2 Answers2

1

You can get a similar result to that of ImageJ using watershed. I inverted your img6, labeled it and then used it as the marker for opencv watershed. Then I enlarged the watershed segmented boundary lines using a morphological filter and found connected components using opencv findContours. Below are the results. Not sure if this is what you want. I'm not posting the code as I quickly tried this out with a combination of python and c++, so it's a bit messy.

watershed segmentation

ws

connected components cc

dhanushka
  • 10,492
  • 2
  • 37
  • 47
  • Thanks for suggestion, I will consider watershed, but it does not let me filter blobs by area or circularity (which is what makes ImageJ ignore 2 adjacent pellets which are not separated in the skeletonized image, something very desirable). SO I am still wondering why the SimpleBlobDetector does not do what I think it should. – eudoxos Apr 21 '16 at 12:58
0

I was able to use SBD and produce a somewhat acceptable result. My first step was to try and even brightness over your image as the lower left was brighter than the upper right. Errors of omission > than commissions so there is still refinements possible.

enter image description here

Julia Meshcheryakova
  • 3,162
  • 3
  • 22
  • 42
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 05 '23 at 20:33