简体   繁体   中英

Python: Image preprocessing - Thresholding and binarizing low contrast images for Blob Detection

I am having difficulty thresholding and binarizing low contrast grayscale images that contain white blobs on a black background. Ultimately, I want to count and measure the area of all white blobs in the image. However, Otsu's Thresholding method does not seem to be a good fit because my graylevel histogram lacks two clear peaks. Are there alternate thresholding methods that might be better suited to this type of image?

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import skimage
import skimage.filters
from skimage.io import imread, imshow
from skimage.color import rgb2gray, rgb2hsv
from skimage.measure import label, regionprops, regionprops_table
from skimage.filters import threshold_otsu 
from scipy.ndimage import median_filter
from matplotlib.patches import Rectangle
from tqdm import tqdm

Here is my code:

pic = imread('image.jpg')
imshow(pic)

raw grayscale image:

原始灰度图像

# blur the image to de-noise

blurred_image = skimage.filters.gaussian(pic, sigma=1.0)

# show the histogram of the blurred image

histogram, bin_edges = np.histogram(blurred_image, bins=256, range=(0.0, 1.0))
fig, ax = plt.subplots()
plt.plot(bin_edges[0:-1], histogram)
plt.title("Graylevel histogram")
plt.xlabel("gray value")
plt.ylabel("pixel count")
plt.xlim(0, 1.0)
plt.show()

graylevel histogram:

灰度直方图

# perform automatic thresholding

t = skimage.filters.threshold_otsu(blurred_image)
print("Found automatic threshold t = {}.".format(t))

Found automatic threshold t = 0.035040431336474526.

# create a binary mask with the threshold found by Otsu's method

binary_mask = blurred_image > t

fig, ax = plt.subplots()
plt.imshow(binary_mask, cmap="gray")
plt.show()

binary mask:

二进制掩码

The white halo in the center of the image is quite problematic. Is there a way to de-noise, threshold, and binarize such that I can isolate the white blobs in the image?

Given your image, the blobs are the outliers.

From the given grayscale image gray , here are some measures:

np.max(gray)

89

np.mean(gray)

7.49876

np.median(gray)

6.0

Although the mean and median are in the range of 6 to 8, the maximum value is at 89, meaning there are some bright pixels in there. To get these outliers, I placed the threshold at mean + ( x * standard_deviation) The value x is a value of your choice given the outliers present. For this image, I chose x = 3

Code using OpenCV :

# read image in color BGR
img =cv2.imread('Pattern.jpg')
# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# binarize using threshold
thresh = cv2.threshold(gray, int(np.mean(gray) + (np.std(gray) * 3)), 255, cv2.THRESH_BINARY)

The threshold value: thresh[0] -> 31.0

Pixels above this value are white:

cv2.imshow('output', thresh[1])

在此处输入图像描述

You can try changing the x value for a better output or run a median filter on the above result

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM