python - 如何使用python从图像中去除边界边缘噪声?
问题描述
我正在尝试通过用 3 个随机数的平均像素值替换黑色区域来去除图像中的黑色边框和无关的非眼睛特征(例如,请参阅下面的文本和“剪辑”)来预处理眼血管的照片正方形。
crop1 = randomCrop(image2, 50, 50) #Function that finds random 50x50 area
crop2 = randomCrop(image2, 50, 50)
crop3 = randomCrop(image2, 50, 50)
mean1 = RGB_Mean(crop1)
mean2 = RGB_Mean(crop2)
mean3 = RGB_Mean(crop3)
#RGB Mean
result = [statistics.mean(k) for k in zip(mean1, mean2, mean3)]
for i in range(len(image2[:,0, 0])):
for j in range(len(image2[0,:,0])):
thru_pixel = image2[i, j]
if (thru_pixel[0] < 50 and thru_pixel[1] < 50 and thru_pixel[2] < 50):
image2[i,j, :] = result
if (thru_pixel[0] > 190 and thru_pixel[1] > 190 and thru_pixel[2] > 190):
image2[i,j, :] = result
但是,图像边框周围还有剩余的噪点,以及左下角的剩余文本和剪辑。
这是一个示例图像。
原来的 :
和后处理
您可以看到仍然存在黑灰色边框噪点以及右下角的文本和左下角的“剪辑”。在保持眼血管完整性的同时,我有什么办法可以尝试去除这些伪影吗?
感谢您的时间和帮助!
解决方案
假设您要隔离眼睛血管,这里有一种方法,可以分为两个阶段,一个是去除伪影,另一个是隔离血管
- 将图像转换为灰度
- 大津阈值获取二值图像
- 执行形态学操作以去除伪影
- 隔离血管的自适应阈值
- 使用最大阈值区域查找轮廓和过滤
- 按位与得到最终结果
从您的原始图像开始,我们转换为灰度和 Otsu 的阈值以获得二值图像
现在我们执行 morph open 以移除伪影(左)。我们反转这个掩码以获得白色边框,然后进行一系列按位运算来获得去除的伪影图像(右)
从这里我们自适应阈值来获得静脉
请注意,存在不需要的边界,因此我们使用最大阈值区域找到轮廓并进行过滤。如果轮廓通过过滤器,我们将其绘制到空白蒙版上
最后,我们对原始图像执行按位与运算以获得我们的结果
请注意,我们可以在自适应阈值之后执行额外的变形打开以去除小颗粒噪声,但代价是它将去除静脉细节。我将把这个可选步骤留给你
import cv2
import numpy as np
# Grayscale, Otsu's threshold, opening
image = cv2.imread('1.png')
blank_mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,15))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)
inverse = 255 - opening
inverse = cv2.merge([inverse,inverse,inverse])
removed_artifacts = cv2.bitwise_and(image,image,mask=opening)
removed_artifacts = cv2.bitwise_or(removed_artifacts, inverse)
# Isolate blood vessels
veins_gray = cv2.cvtColor(removed_artifacts, cv2.COLOR_BGR2GRAY)
adaptive = cv2.adaptiveThreshold(veins_gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,3)
cnts = cv2.findContours(adaptive, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area < 5000:
cv2.drawContours(blank_mask, [c], -1, (255,255,255), 1)
blank_mask = cv2.cvtColor(blank_mask, cv2.COLOR_BGR2GRAY)
final = cv2.bitwise_and(image, image, mask=blank_mask)
# final[blank_mask==0] = (255,255,255) # White version
cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('removed_artifacts', removed_artifacts)
cv2.imshow('adaptive', adaptive)
cv2.imshow('blank_mask', blank_mask)
cv2.imshow('final', final)
cv2.waitKey()
推荐阅读
- html - 将元素显示为内联块的问题
- python - 泡菜数据被截断
- java - 在 Activity 中实现“选项卡布局”的好方法是什么?
- c - 如何在没有 sprintf 或 strcpy 的情况下将字符串分配给 char 数组
- git - Github 中显示重复提交,但在执行 rebase 时没有
- php - 如何在 Laravel 和 MailTrap 中发送电子邮件通知
- php - 为什么通过 php 运行 Ratchet websocket 服务器会挂起浏览器请求?
- linux - 'arecord' 有效,但 FFMPEG '无法打开音频设备'
- python - 如何使用 Python 检查一年是否是闰年?
- apache-spark - PySpark MLLib 随机森林分类器可重复性问题