标签:nes 一点 binary 像素 图片 完美 删除 缺陷 连通图
利用openCV或其他工具编写程序实现细化血管并输出血管轮廓图像的功能。
1、编写程序
目标图片如下
根据展示的程序功能编写对应的程序:
第一步,读取显示图像的功能openCV已经提供了函数imread()和imshow(),代码如下
img1=cv2.imread(‘123.jpg‘)
cv2.imshow(‘origin‘,img1)
cv2.waitKey(0)
第二步,使用open CV自带的局部阈值的方法adaptiveThreshold()处理原图片,得到一张带“杂质”的血管二值图,需要注意的是这个方法只能处理灰度图,所以我们需要先将原图进行灰度处理:
gray = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 31,2.7)
cv2.namedWindow("binary1", cv2.WINDOW_NORMAL)
cv2.imshow("binary1", binary)
cv2.waitKey(0)
第三步,对图像binary进行反色处理:
def pointInvert(img):
point = img.copy()
for i in range(0, img.shape[0]):
for j in range(0, img.shape[1]):
point[i,j] = 255 - img[i,j]
return point
img2 = pointInvert(binary)
cv2.imshow("img2", img2)
cv2.waitKey(0)
第四步,扩展图片,将图片四周向外扩展十个像素单位:
img3 = cv2.copyMakeBorder(img2,10,10,10,10, cv2.BORDER_CONSTANT,value=[0,0,0])
cv2.imshow("img3 ", img3 )
cv2.waitKey(0)
第五步,对图像img3进行轮廓查找操作,寻找处理后的图片的轮廓:
contours,hierarchy = cv2.findContours(img3, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
area = cv2.contourArea(contours[i])
if area < 700:
cv2.drawContours(img3,[contours[i]],0,0,-1)
cv2.imshow("img3 ",img3 )
cv2.waitKey(0)
第六步,输出给定范围内查找到的连通图:
img4=img3.copy()
contours1,hierarchy = cv2.findContours(img4, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
for j in range(len(contours1)):
area1 = cv2.contourArea(contours1[j])
print(area1)
if area1 ==155.0:
cv2.drawContours(img4,[contours1[j]],0,0,-1)
elif area1==266.5:
cv2.drawContours(img4,[contours1[j]],0,0,-1)
elif area1==437.0:
cv2.drawContours(img4,[contours1[j]],0,0,-1)
cv2.imshow(‘img4‘,img4)
cv2.waitKey(0)
第七步,查找最大连通图的轮廓并输出:
temp=temp=np.temp = np.ones(a.shape,np.uint8)
contours1, hierarchy = cv2.findContours(img4, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
for idx in range(len(contours)):
if verify(contours[idx],150,10000):
cv2.drawContours(temp,contours,idx,(255,255,255),1)
cv2.imshow("contours",temp)
cv2.waitKey(0)
第八步,对temp图像进行细化操作,这里我使用的是索引表的方式,在每行水平扫描时,先判断每一点的左右像素,如果都是黑点,则该点不做处理。如果某个黑点被删除了,则跳过它的右边的像素点,处理下一个点。再将水平扫描改为垂直扫描重复上一个操作。
多次重复以上的步骤,直到图像不再变化就得到了我们所需要的骨架图。
def VThin(image, array):
h,w= image.shape[:2]
NEXT = 1
for i in range(h):
for j in range(w):
if NEXT == 0:
NEXT = 1
else:
M = image[i, j-1] + image[i,j] + image[i, j+1] if 0<j<w-1 else 1
if image[i, j] == 0 and M != 0:
a = [0] * 9
for k in range(3):
for l in range(3):
if-1<(i-1+k)<h and -1<(j-1+l)<w and image[i-1+k, j-1+l] == 255:
a[k*3 + l] = 1
sum = a[0]*1 + a[1]*2 + a[2]*4 + a[3]*8 + a[5]*16 + a[6]*32 + a[7]*64 + a[8]*128
image[i,j] = array[sum]*255
if array[sum] == 1:
NEXT = 0
return image
def HThin(image, array):
h, w = image.shape[:2]
NEXT = 1
for j in range(w):
for i in range(h):
if NEXT == 0:
NEXT = 1
else:
M = image[i-1, j] + image[i, j] + image[i+1, j] if 0<i<h-1 else 1
if image[i, j] == 0 and M != 0:
a = [0] * 9
for k in range(3):
for l in range(3):
if -1<(i-1+k)<h and -1<(j-1+l)<w and image[i-1+k, j-1+l] == 255:
a[k*3 + l] = 1
sum = a[0]*1 + a[1]*2 + a[2]*4 + a[3]*8 + a[5]*16 + a[6]*32 + a[7]*64 + a[8]*128
image[i, j] = array[sum] * 255
if array[sum] == 1:
NEXT = 0
return image
def Xihua(binary, array, num=10):
iXihua = binary.copy()
for i in range(num):
VThin(iXihua, array)
HThin(iXihua, array)
return iXihua
iThin = Xihua(img6, array)
cv2.imshow(‘contours‘, iThin)
cv2.waitKey(0)
第九步,获取iThin图像的轮廓:
img7 = cv2.Canny(iThin,80,255)
cv2.imshow(‘img7‘, img7)
cv2.waitKey(0)
第十步,对图像img7进行反色处理:
point = pointInvert(img7)
cv2.imshow(‘pointInvert‘,point)
cv2.waitKey(0)
1、二值化
刚开始处理原图片时,使用openCV自带的二值化处理方法得到的结果总是不尽如人意,图片的下半区始终是一整块的黑块,没有办法进行下一步的处理,后来又使用增强对比度的方法来完成这一步的操作,发现下半区的问题还是没有解决。后来抱着试一试的心态搜索open CV中的Niblack处理,发现有类似这个操作的局部阈值的方法,最后使用这个方法成功完成图像二值化的步骤。
2、部分“杂质”消除不掉
这个问题在我更改了findContours()函数中的参数无果后,我选择了一个很傻的方法:循环输出图像输出区域的面积,同时显示当时的图片,知道了需要的连通图面积后给定面积的值输出仅需要的连通图。
这一次的实验与之前的其次实验相比难了很多,代码的难度、逻辑思维的难度以及编写程序的过程中出现的问题的难度,都大大提高了。很开心的是我顺利完成了这次实验,不足的是实验中的问题解决的并不完美,比解决消除图像中的“杂质”这一步出现的部分“杂质”消除不掉的问题,我使用的是最傻的办法。希望以后可以改进这一部分的缺陷。
标签:nes 一点 binary 像素 图片 完美 删除 缺陷 连通图
原文地址:https://www.cnblogs.com/zhangmingfeng/p/12895621.html