zoukankan      html  css  js  c++  java
  • 机器视觉——医学检测

    利用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()函数中的参数无果后,我选择了一个很傻的方法:循环输出图像输出区域的面积,同时显示当时的图片,知道了需要的连通图面积后给定面积的值输出仅需要的连通图。

    实验总结

        这一次的实验与之前的其次实验相比难了很多,代码的难度、逻辑思维的难度以及编写程序的过程中出现的问题的难度,都大大提高了。很开心的是我顺利完成了这次实验,不足的是实验中的问题解决的并不完美,比解决消除图像中的“杂质”这一步出现的部分“杂质”消除不掉的问题,我使用的是最傻的办法。希望以后可以改进这一部分的缺陷。

  • 相关阅读:
    20169210《Linux内核原理与分析》第十周作业
    Collabtive 系统 SQL 注入实验(补充)
    20169211《Linux内核原理与分析》课程总结
    20169211《Linux内核原理及分析》第十二周作业
    20169211 《Linux内核原理与分析》第十一周作业
    20169211《Linux内核原理与分析》 第十周作业
    20169211《Linux内核原理与分析》 第九周作业
    20169210《Linux内核原理与分析》第八周作业
    20169211《linux内核原理与分析》第七周作业
    20169211《Linux内核原理与分析》第六周作业
  • 原文地址:https://www.cnblogs.com/zhangmingfeng/p/12895621.html
Copyright © 2011-2022 走看看