eudoxos
eudoxos

Reputation: 19085

setting blob detection parameters in python

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

Upvotes: 3

Views: 4290

Answers (2)

seabirdman
seabirdman

Reputation: 1

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

Upvotes: 0

dhanushka
dhanushka

Reputation: 10702

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

Upvotes: 1

Related Questions