岩石Edge (Contour) Detection效果优化求助(基于Watershed Segmentation实现)
岩石Edge (Contour) Detection效果优化求助(基于Watershed Segmentation实现)
大家好,我现在在做一个用图像处理技术检测岩石/石块尺寸的项目——完成轮廓检测后,计算尺寸的Python代码已经能用了,但目前卡在边缘/轮廓检测(图像分割)这一步,急需优化建议。
查了不少文献后,我认为分水岭分割算法是最适合我场景的方案,但如果有其他更合适的方法,我也愿意尝试。
我想要达到的理想分割效果是能清晰勾勒出每块岩石的边缘,类似这样:
- 理想效果示例1:

- 理想效果示例2:

- 理想效果示例3:

但我自己用Python尝试后,得到的结果和理想效果差距很大,要么漏检轮廓,要么存在大量冗余噪声:
- 我的尝试结果1:

- 我的尝试结果2:

- 我的尝试结果3:

- 我的尝试结果4:

- 我的尝试结果5:

我已经反复调整过不少参数了(下面代码里我用加粗标出来的就是我试过的可调参数,比如亮度、伽马值、滤波权重、迭代次数等),但不管怎么调,都没法接近理想效果。我是图像处理和Python的新手,有没有大佬能帮我看看代码里的问题,或者给点优化方向的建议?
下面是我使用的Python代码:
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_tv_chambolle,denoise_bilateral,denoise_wavelet,estimate_sigma) from PIL import Image from PIL import ImageEnhance path = 'OrijinalKaya5.jpg' #BRIGHTNESS SETTING image=Image.open(path) enhancer=ImageEnhance.Brightness(image) brightness_factor=**1.3** brightened_image=enhancer.enhance(brightness_factor) brightened_image.save('Brightened.jpg') brightened_img=cv2.imread('Brightened.jpg') #GAMMA SETTING gamma=**1.45** invGamma = 1.0 / gamma table = np.array([((i / 255.0) ** invGamma) * 255 for i in np.arange(0, 256)]).astype("uint8") gamma_img=cv2.LUT(brightened_img, table) cv2.imwrite('Gamma.jpg',gamma_img) path='Gamma.jpg' img_ori = img_as_float(io.imread(path)) # Bilateral Filter #denoise = denoise_bilateral(img_ori, sigma_color=**0.03**, sigma_spatial=**0.9**, channel_axis=-1) # Total Variation Filter denoise = denoise_tv_chambolle(img_ori, weight=**0.01**, channel_axis=-1) # Wavelet Denoising #denoise = denoise_wavelet(img_ori, channel_axis=-1, rescale_sigma=True) # Wavelet Denoising in YCbCr Colorspace #denoise = denoise_wavelet(img_ori, channel_axis=-1, convert2ycbcr=True, rescale_sigma=True) denoise_img_ubyte = img_as_ubyte(denoise) # turn into gray scale gray = denoise_img_ubyte.astype("uint8") gray=cv2.cvtColor(gray, cv2.COLOR_BGR2GRAY) # tresholding ret, bin_img = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # smoothing the image kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3)) #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=**30**) # Distance transform dist = cv2.distanceTransform(bin_img, **cv2.DIST_L2**, 3) # 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 # display results fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(8, 8), sharex=True, sharey=True) ax = axes.ravel() ax[0].imshow(gamma_img, cmap=plt.cm.gray) ax[0].set_title("Original") ax[1].imshow(img, cmap=plt.cm.nipy_spectral) ax[1].set_title("Contours") ax[2].imshow(img2, cmap=plt.cm.nipy_spectral) ax[2].set_title("Labels") for a in ax: a.axis('off') fig.tight_layout() plt.show()
备注:内容来源于stack exchange,提问作者Nazım Çimen




