我用粒子分析图像,例如
粒子 - 原始图像:
如图所示,一些粒子被破坏,程序并不总是能正确识别它们,如具有轮廓和颜色标记的图像中所示:
具有轮廓的图像:
带有颜色标记的图像
我的分析代码如下:
import cv2
import numpy as np
from IPython.display import Image, display
from matplotlib import pyplot as plt
from skimage import io, img_as_float, color, measure, img_as_ubyte
from skimage.segmentation import clear_border
from skimage.restoration import denoise_nl_means, estimate_sigma
path = 'xxx'
# import image and sigma factor for denoising
img_sigma = img_as_float(io.imread(path))
img = img_sigma[0:1024, :]
sigma_est = np.mean(estimate_sigma(img_sigma))
img_ori = cv2.imread(path)
img_ori = img_ori[:1024, :]
sigma_est
# denoise the image
sigma_fak = 2
denoise_img = denoise_nl_means(img, h = sigma_fak*sigma_est, fast_mode = True, patch_size = 5, patch_distance = 5)
denoise_img_ubyte = img_as_ubyte(denoise_img)
denoise_img = cv2.medianBlur(denoise_img_ubyte, 5)
#denoise_img = denoise_nl_means(denoise_img, fast_mode = True, patch_size = 3, patch_distance = 3)
#denoise_img_ubyte = img_as_ubyte(denoise_img)
# turn into gray scale
gray = denoise_img_ubyte
# tresholding
ret, bin_img = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# smoothing the image
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
#kernel = np.ones((5,5), np.uint8)
#bin_img = cv2.morphologyEx(bin_img, cv2.MORPH_CLOSE, kernel, iterations=3)
bin_img = cv2.morphologyEx(bin_img, cv2.MORPH_OPEN, kernel, iterations=2)
# removal of the objects that touch the edge of the image
bin_img = clear_border(bin_img)
# sure background area
sure_bg = cv2.dilate(bin_img, kernel, iterations=15)
# Distance transform
dist = cv2.distanceTransform(bin_img, cv2.DIST_L2, 5)
# Make the distance transform normal.
dist = cv2.normalize(dist, None, 0, 1.0, cv2.NORM_MINMAX)
# foreground area
ret, sure_fg = cv2.threshold(dist, 0.15 * dist.max(), 255, cv2.THRESH_BINARY)
sure_fg = sure_fg.astype(np.uint8)
# unknown area
unknown = cv2.subtract(sure_bg, sure_fg)
# Marker labelling sure foreground
ret, markers = cv2.connectedComponents(sure_fg)
markers += 255
markers[unknown == 255] = 0
# watershed Algorithm
gray = cv2.cvtColor(gray, cv2.COLOR_GRAY2RGB)
markers = cv2.watershed(gray, markers)
# drawing contours from color marks
labels = np.unique(markers)
coins = []
for label in labels[3:]:
target = np.where(markers == label, 255, 0).astype(np.uint8)
contours, hierarchy = cv2.findContours(target, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
coins.append(contours[0])
#img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.drawContours(img_ori, coins, -1, color=(0, 255, 0), thickness=2)
img2 = color.label2rgb(markers, bg_label=255)
img2[img2 == 0] = 0`
对于每张图像,我都会考虑一些因素来调整结果,例如:
添加额外的模糊方法(中值)和/或更改 denoise_nl_means 函数的 patch_size 和 patch_distance
denoise_img = denoise_nl_means(img, h = sigma_fak*sigma_est, fast_mode = True, patch_size = 5, patch_distance = 5)
denoise_img = cv2.medianBlur(denoise_img_ubyte, 5)
确定背景区域的迭代次数
sure_bg = cv2.dilate(bin_img, kernel, iterations=15)
确定前景的距离变换分数:
ret, sure_fg = cv2.threshold(dist, 0.15 * dist.max(), 255, cv2.THRESH_BINARY) sure_fg = sure_fg.astype(np.uint8)
打开的迭代次数:
bin_img = cv2.morphologyEx(bin_img, cv2.MORPH_OPEN, kernel, iterations=2)
我该怎么做才能确保粒子的裂缝被模糊/忽略,但粒子之间的边界不被模糊/忽略?有没有什么方法可以自动化它,即程序根据图像选择参数?
您可以尝试预先处理步骤来填充裂缝 - 因为裂缝的强度似乎始终低于实际背景,这样的操作应该有效:
# Create a binary mask of all values below this threshold
CRACK_INTENSITY_TH = 30
ret, thresh = cv.threshold(img, 0, CRACK_INTENSITY_TH, cv.THRESH_BINARY_INV)
img_post = img.copy()
# Fill in cracks with white, grey should also work
img_post[thresh != 0] = 255
这也可能会在您的背景中产生一些白噪声,具体取决于您选择的高度
CRACK_INTENSITY_TH
,但是这应该在 WST 的处理步骤中删除。如果没有,您也可以添加一个小开口操作作为预处理的一部分,这也可以解决这个问题。