我正在尝试从图像中提取血管,为此,我首先对图像进行均衡,应用CLAHE直方图获得以下结果:
clahe = cv2.createCLAHE(clipLimit=100.0, tileGridSize=(100,100))
self.cl1 = clahe.apply(self.result_array)
self.cl1 = 255 - self.cl1
然后我使用OTSU阈值提取血管,但是做得不好:
self.ret, self.thresh = cv2.threshold(self.cl1, 0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)
kernel = np.ones((1,1),np.float32)/1
self.thresh = cv2.erode(self.thresh, kernel, iterations=3)
self.thresh = cv2.dilate(self.thresh, kernel, iterations=3)
结果如下:
显然有很多噪音。我尝试使用中值模糊,但是在某些地方,它只是将噪声聚类并使其变成斑点。我该如何消除噪音以获取血管?
这是我要提取血管的原始图像:
最佳答案
获得真正好的结果是一个困难的问题(您可能必须以某种方式对血管和噪音的结构进行建模),但是您可能仍然比过滤做得更好。
受Canny边缘检测器启发,解决此类问题的一种技术是使用两个阈值-[hi,low]
,如果p
||,将具有响应r
的像素V
分类为属于血管r > hi
(r > lo
和&p
的邻居之一在V
中)。
同样,在滤波方面,双边滤波和均值漂移滤波均适用于嘈杂的图像。
kernel3 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
kernel5 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
kernel7 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(7,7))
t_lo = 136
t_hi = 224
blured = cv2.pyrMeanShiftFiltering(img, 3, 9)
#blured = cv2.bilateralFilter(img, 9, 32, 72)
clahe = cv2.createCLAHE(clipLimit=128.0, tileGridSize=(64, 64))
cl1 = clahe.apply(blured)
cl1 = 255 - cl1
ret, thresh_hi = cv2.threshold(cl1, t_hi, 255, cv2.THRESH_TOZERO)
ret, thresh_lo = cv2.threshold(cl1, t_lo, 255, cv2.THRESH_TOZERO)
低阈值图像
嗨阈值图像
准备和清理:
current = np.copy(thresh_hi)
prev = np.copy(current)
prev[:] = 0
current = cv2.morphologyEx(current, cv2.MORPH_OPEN, kernel5)
iter_num = 0
max_iter = 1000
并非最有效的方法...但是易于实现:
while np.sum(current - prev) > 0 and iter_num < max_iter:
iter_num = iter_num+1
prev = np.copy(current)
current = cv2.dilate(current, kernel3)
current[np.where(thresh_lo == 0)] = 0
初始面膜
去除小斑点:
contours, hierarchy = cv2.findContours(current, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
area = cv2.contourArea(contour)
if area < 256:
cv2.drawContours( current, [contour], 0, [0,0,0], -1 )
去除小斑点后
形态清理:
opening = cv2.morphologyEx(current, cv2.MORPH_OPEN, kernel7)
cl1[np.where(opening == 0)] = 0
结果
这绝不是最佳选择,但我认为它应该为您提供足够的启动工具。