Ask Your Question

Revision history [back]

Blob Detector Not working when it should on obvious blobs, makes no sense

So I have an HSV filtered image that I am trying to do blob detection on but for some reason it is not working. The image is this one:https://i.stack.imgur.com/OhIaY.png

Using the Simple Blob Detector, I get this: https://i.stack.imgur.com/07wl0.png

However, on other samples such as https://i.stack.imgur.com/mYgbc.png, the code works perfectly fine and does the job I want. What parameter do I change? I'm really not sure what's going wrong, this should be working. My code is attached below:

import cv2
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = [20, 10]

img = cv2.imread('graphenetest.png')
#img = cv2.resize(img,(800,600))

SLG_MIN = np.array([114, 50, 50],np.uint8)
SLG_MAX = np.array([116, 255, 255],np.uint8)

hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

frame_threshed = cv2.inRange(hsv_img, SLG_MIN, SLG_MAX)

imagem = cv2.bitwise_not(frame_threshed)

kernel = np.ones((10, 10), np.uint8)
#blur = cv2.morphologyEx(imagem, cv2.MORPH_CLOSE, kernel)
median = cv2.medianBlur(imagem,9)



im = median
plt.imshow(im)
plt.title('Single Layer Graphene Detected')
plt.show()

# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()

# Change thresholds
params.minThreshold = 50
params.maxThreshold = 100


# Filter by Area.
params.filterByArea = True
params.minArea = 10000
params.maxArea = 100000000

params.filterByCircularity = False

params.filterByInertia = False

params.filterByConvexity = False


# Create a detector with the parameters
ver = (cv2.__version__).split('.')
if int(ver[0]) < 3 :
    detector = cv2.SimpleBlobDetector(params)
else : 
    detector = cv2.SimpleBlobDetector_create(params)


# Detect blobs.
keypoints = detector.detect(im)

# Draw detected blobs as red circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures
# the size of the circle corresponds to the size of blob

#im_with_keypoints = cv2.drawKeypoints(im, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

img2 = im.copy()
for x in range(1,len(keypoints)):
  img2=cv2.circle(img, (np.int(keypoints[x].pt[0]),np.int(keypoints[x].pt[1])), radius=np.int(keypoints[x].size), color=(255, 0, 0), thickness=10)

# Show blobs
plt.imshow(img)
plt.title('Single Layer Graphene Detected')
plt.show()

cv2.imwrite("SLG.png", img)

I tried messing with the parameters, making minArea = 150 works for the one it otherwise doesn't work for, but doing that screws the other shapes. I even tried adding a constraint to the circle drawing function:

if np.int(keypoints[x].size) >= 500:

but that did not help either. Besides all this parameter messing seems so arbitrary, I want something more systematic.

Here is the original image I am trying to do a detection on: https://imgur.com/a/UKh7Xfu

Blob Detector Not working when it should on obvious blobs, makes no sense

So I have an HSV filtered image that I am trying to do blob detection on but for some reason it is not working. The image is this one:https://i.stack.imgur.com/OhIaY.pngone: https://i.stack.imgur.com/OhIaY.png

Using the Simple Blob Detector, I get this: https://i.stack.imgur.com/07wl0.png

However, on other samples such as https://i.stack.imgur.com/mYgbc.png, the code works perfectly fine and does the job I want. What parameter do I change? I'm really not sure what's going wrong, this should be working. My code is attached below:

import cv2
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = [20, 10]

img = cv2.imread('graphenetest.png')
#img = cv2.resize(img,(800,600))

SLG_MIN = np.array([114, 50, 50],np.uint8)
SLG_MAX = np.array([116, 255, 255],np.uint8)

hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

frame_threshed = cv2.inRange(hsv_img, SLG_MIN, SLG_MAX)

imagem = cv2.bitwise_not(frame_threshed)

kernel = np.ones((10, 10), np.uint8)
#blur = cv2.morphologyEx(imagem, cv2.MORPH_CLOSE, kernel)
median = cv2.medianBlur(imagem,9)



im = median
plt.imshow(im)
plt.title('Single Layer Graphene Detected')
plt.show()

# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()

# Change thresholds
params.minThreshold = 50
params.maxThreshold = 100


# Filter by Area.
params.filterByArea = True
params.minArea = 10000
params.maxArea = 100000000

params.filterByCircularity = False

params.filterByInertia = False

params.filterByConvexity = False


# Create a detector with the parameters
ver = (cv2.__version__).split('.')
if int(ver[0]) < 3 :
    detector = cv2.SimpleBlobDetector(params)
else : 
    detector = cv2.SimpleBlobDetector_create(params)


# Detect blobs.
keypoints = detector.detect(im)

# Draw detected blobs as red circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures
# the size of the circle corresponds to the size of blob

#im_with_keypoints = cv2.drawKeypoints(im, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

img2 = im.copy()
for x in range(1,len(keypoints)):
  img2=cv2.circle(img, (np.int(keypoints[x].pt[0]),np.int(keypoints[x].pt[1])), radius=np.int(keypoints[x].size), color=(255, 0, 0), thickness=10)

# Show blobs
plt.imshow(img)
plt.title('Single Layer Graphene Detected')
plt.show()

cv2.imwrite("SLG.png", img)

I tried messing with the parameters, making minArea = 150 works for the one it otherwise doesn't work for, but doing that screws the other shapes. I even tried adding a constraint to the circle drawing function:

if np.int(keypoints[x].size) >= 500:

but that did not help either. Besides all this parameter messing seems so arbitrary, I want something more systematic.

Here is the original image I am trying to do a detection on: https://imgur.com/a/UKh7Xfu

EDITED TO FIX LINK - Tetragramm