我有一个嘈杂的灰度图像,我想对其分割/遮盖其余图像上的大弧。我打算遮罩弧线以及弧线上方的所有像素。
为此,我将图像阈值化以创建二进制图像,并使用cv2.findContours()
来跟踪弧的轮廓。
原始图片:
大津阈值后的图像:
阈值+关闭:
闭合图像的轮廓:
如您所见,闭合的图像不会产生实心弧。闭合进一步会使弧失去形状。绿线是闭合图像的轮廓。蓝线是用approxpolyDP()
创建的,但我无法使用它。有没有更好的方法可以掩盖图像中的弧形?
这是我的代码:
import cv2, matplotlib
import numpy as np
import matplotlib.pyplot as plt
# read an image
img = cv2.imread('oct.png')
# get gray image and apply Gaussian blur
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# get binary image
ret, thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# close image to "solidify" it
kernel = np.ones((3,3),np.uint8)
closing = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,kernel, iterations = 3)
# find contours
(_, contours, _) = cv2.findContours(closing, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
max_area = cv2.contourArea(cnt)
for cont in contours:
if cv2.contourArea(cont) > max_area:
cnt = cont
max_area = cv2.contourArea(cont)
# define main arc contour approx. and hull
perimeter = cv2.arcLength(cnt, True)
epsilon = 0.1 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
# hull = cv2.convexHull(cnt)
# cv2.isContourConvex(cnt)
imgcopy = np.copy(img)
cv2.drawContours(imgcopy, [cnt], -1, (0, 255, 0), 3)
cv2.drawContours(imgcopy, [approx], -1, (0, 0, 255), 3)
# plot figures
plt.figure(1)
plt.imshow(imgcopy, cmap="gray")
plt.figure(2)
plt.imshow(thresh, cmap="gray")
plt.figure(3)
plt.imshow(closing, cmap="gray")
答案 0 :(得分:2)
您在正确的道路上。如果先稍微平滑一下图像,关闭效果可能会更好。我喜欢在形态学运算之后最后应用阈值。在这种情况下,关闭和阈值排序的顺序实际上并不重要,但在优化预处理时,将阈值保留在最后有助于以后。一旦阈值丢失了很多信息,就需要确保保留了所有需要的信息,因此在阈值确定之前,正确过滤图像非常重要。
这是一个快速尝试,我敢肯定它可以改进:
import matplotlib.pyplot as pp
import PyDIP as dip
img = pp.imread('/Users/cris/Downloads/MipBB.jpg')
img = img[:,:,0]
smooth = dip.Gauss(img, [3]) # Gaussian smoothing with sigma=3
smooth = dip.Closing(smooth, 25) # Note! This uses a disk SE with diameter 25 pixels
out = dip.Threshold(smooth, 'triangle')[0]
pp.imsave('/Users/cris/Downloads/MipBB_out.png', out)
我使用了三角形阈值方法(也称为和弦方法或倾斜的双峰阈值,请参见PL Rosin,“单峰阈值”,模式识别34(11):2083-2096,2001),因为它可以更好地工作在这种情况下。
代码使用PyDIP,但我确定您可以使用OpenCV重新创建相同的过程。
答案 1 :(得分:2)