破碎颗粒的分水岭调整

问题描述 投票:0回答:1

我用粒子分析图像,例如

粒子 - 原始图像:

Particles - raw image

如图所示,一些粒子被破坏,程序并不总是能正确识别它们,如具有轮廓和颜色标记的图像中所示:

具有轮廓的图像:

Image with contours

带有颜色标记的图像

Image with color marks

我的分析代码如下:

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)

我该怎么做才能确保粒子的裂缝被模糊/忽略,但粒子之间的边界不被模糊/忽略?有没有什么方法可以自动化它,即程序根据图像选择参数?

python opencv image-processing particles watershed
1个回答
0
投票

您可以尝试预先处理步骤来填充裂缝 - 因为裂缝的强度似乎始终低于实际背景,这样的操作应该有效:

# 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 的处理步骤中删除。如果没有,您也可以添加一个小开口操作作为预处理的一部分,这也可以解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.