Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding a tight contour around a blurry object with Python OpenCV

I have trouble finding contours around a blurry object. Here are some examples of what I want to achieve:

enter image description here

enter image description here

As you can see the objects are quite blurry. I've tried calculating the mean background value and use a simple threshold. The problem is, that the smaller particles are much brighter than the bigger ones. So when I am using a simple threshold it either cuts off too much of the small particle or it doesnt fit tight enough around the bigger ones. I also tried to set the threshold depending on the darkest pixel values of the object. While this works for some particles, as soon as a particle has dark areas aswell as light areas it breaks down.

I also tried the skimage entropy filter with no success. Canny Edge detection is also not possible due to the blurry nature of the images.

But since my eyes are able to draw around the outline of the objects I think there has to be a simple way of finding the contour with python and open cv.

Thanks in advance! Luca

like image 985
Luca Rüffert Avatar asked Nov 26 '25 11:11

Luca Rüffert


1 Answers

A simple approach is to use Otsu's threshold or adaptive threshold to automatically determine the threshold value. The idea is to Gaussian blur, threshold to obtain a binary image, then find contours and highlight the contour with cv2.drawContours. You may need to adjust the parameters to get your desired output. Results:

Input (screenshotted) -> Output

enter image description here enter image description here

enter image description here enter image description here

import cv2
import numpy as np

# Load image, grayscale, Gaussian blur, Adaptive threshold
image = cv2.imread('2.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (9,9), 0)
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,23,3)

# Find contours and filter using contour area
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area > 10:
        cv2.drawContours(image, [c], -1, (36,255,12), 1)

cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()     
like image 174
nathancy Avatar answered Nov 29 '25 00:11

nathancy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!