精华内容
下载资源
问答
  • opencv-python图像孔洞填充

    万次阅读 2018-11-24 16:26:09
      在进行图像分割的过程中,由于算法的不稳定或者图像质量的问题,会造成图像孔洞出现,这个时候就需要对图像中的孔洞进行填充,具体函数如下 def fillHole(im_in): im_floodfill = im_in.copy() # Mask used ...

      在进行图像分割的过程中,由于算法的不稳定或者图像质量的问题,会造成图像孔洞出现,这个时候就需要对图像中的孔洞进行填充,具体函数如下

    def fillHole(im_in):
    	im_floodfill = im_in.copy()
    
    	# Mask used to flood filling.
    	# Notice the size needs to be 2 pixels than the image.
    	h, w = im_in.shape[:2]
    	mask = np.zeros((h+2, w+2), np.uint8)
    
    	# Floodfill from point (0, 0)
    	cv2.floodFill(im_floodfill, mask, (0,0), 255);
    
    	# Invert floodfilled image
    	im_floodfill_inv = cv2.bitwise_not(im_floodfill)
    
    	# Combine the two images to get the foreground.
    	im_out = im_in | im_floodfill_inv
    
    	return im_out
    

      这里调用了 opencv 库中的泛洪函数。我们将图像输入就可以获得整幅图像填充后的结果。

    展开全文
  • 今天我们就用python语言基于OpenCV实现孔洞填充。图1 有孔洞的分割图像我们要用到的函数是OpenCV里的floodFill函数。使用floodFill函数可以得到只标记孔洞的像素矩阵(孔洞值为0,非孔洞值为指定值)。有了...

    我们在进行图像分割后,分割结果有时会有一些小孔洞,如图1所示,其中黑白两色表示两种不同的类别。一般情况下,这些孔洞属于错分情况,为了优化结果,我们通常对这些孔洞进行填充。今天我们就用python语言基于OpenCV实现孔洞填充。图1 有孔洞的分割图像

    我们要用到的函数是OpenCV里的floodFill函数。使用floodFill函数可以得到只标记孔洞的像素矩阵(孔洞值为0,非孔洞值为指定值)。有了孔洞的位置填充孔洞就容易多了。python代码如下。

    import cv2

    import numpy as np

    '''图像说明:图像为二值化图像,255白色为目标物,0黑色为背景要填充白色目标物中的黑色空洞'''

    def FillHole(imgPath,SavePath):

    im_in = cv2.imread(imgPath, cv2.IMREAD_GRAYSCALE);

    cv2.imwrite("im_in.png",im_in)

    # 复制 im_in 图像

    im_floodfill = im_in.copy()

    # Mask 用于 floodFill,官方要求长宽+2

    h, w = im_in.shape[:2]

    mask = np.zeros((h+2, w+2), np.uint8)

    # floodFill函数中的seedPoint对应像素必须是背景

    isbreak = False

    for i in range(im_floodfill.shape[0]):

    for j in range(im_floodfill.shape[1]):

    if(im_floodfill[i][j]==0):

    seedPoint=(i,j)

    isbreak = True

    break

    if(isbreak):

    break

    # 得到im_floodfill 255填充非孔洞值

    cv2.floodFill(im_floodfill, mask,seedPoint, 255)

    # 得到im_floodfill的逆im_floodfill_inv

    im_floodfill_inv = cv2.bitwise_not(im_floodfill)

    # 把im_in、im_floodfill_inv这两幅图像结合起来得到前景

    im_out = im_in | im_floodfill_inv

    # 保存结果

    cv2.imwrite(SavePath, im_out)

    填充结果如图2所示,三个孔洞均被填充。图2 填充结果

    现在又有一个问题,就是说如果我们的多类分割呢,就像图3所示。我们可以利用for循环分颜色进行单类别填充孔洞,然后进行合并。python代码如下。图3 有孔洞的多类图像分割

    import cv2;

    import numpy as np;

    def FillHole_RGB(imgPath,SavePath):

    # 读取图像为uint32,之所以选择uint32是因为下面转为0xbbggrr不溢出

    im_in_rgb = cv2.imread(imgPath).astype(np.uint32)

    # 将im_in_rgb的RGB颜色转换为 0xbbggrr

    im_in_lbl = im_in_rgb[:,:,0] + (im_in_rgb[:,:,1] << 8) + (im_in_rgb[:,:,2] << 16)

    # 将0xbbggrr颜色转换为0,1,2,...

    colors, im_in_lbl_new = np.unique(im_in_lbl, return_inverse=True)

    # 将im_in_lbl_new数组reshape为2维

    im_in_lbl_new = np.reshape(im_in_lbl_new,im_in_lbl.shape)

    # 创建从32位im_in_lbl_new到8位colorize颜色的映射

    colorize = np.empty((len(colors), 3), np.uint8)

    colorize[:,0] = (colors & 0x0000FF)

    colorize[:,1] = (colors & 0x00FF00) >> 8

    colorize[:,2] = (colors & 0xFF0000) >> 16

    # 输出一下colorize中的color

    print("Colors_RGB: \n",colorize)

    # 有几种颜色就设置几层数组,每层数组均为各种颜色的二值化数组

    im_result = np.zeros((len(colors),)+im_in_lbl_new.shape,np.uint8)

    # 初始化二值数组

    im_th = np.zeros(im_in_lbl_new.shape,np.uint8)

    for i in range(len(colors)):

    for j in range(im_th.shape[0]):

    for k in range(im_th.shape[1]):

    if(im_in_lbl_new[j][k]==i):

    im_th[j][k] = 255

    else:

    im_th[j][k] = 0

    # 复制 im_in 图像

    im_floodfill = im_th.copy()

    # Mask 用于 floodFill,mask多出来的2可以保证扫描的边界上的像素都会被处理.

    h, w = im_th.shape[:2]

    mask = np.zeros((h+2, w+2), np.uint8)

    isbreak = False

    for m in range(im_floodfill.shape[0]):

    for n in range(im_floodfill.shape[1]):

    if(im_floodfill[m][n]==0):

    seedPoint=(m,n)

    isbreak = True

    break

    if(isbreak):

    break

    # 得到im_floodfill

    cv2.floodFill(im_floodfill, mask, seedPoint, 255,4)

    # help(cv2.floodFill.rect)

    # 得到im_floodfill的逆im_floodfill_inv

    im_floodfill_inv = cv2.bitwise_not(im_floodfill)

    # 把im_in、im_floodfill_inv这两幅图像结合起来得到前景

    im_out = im_th | im_floodfill_inv

    im_result[i] = im_out

    # rgb结果图像

    im_fillhole = np.zeros((im_in_lbl_new.shape[0],im_in_lbl_new.shape[1],3),np.uint8)

    # 之前的颜色映射起到了作用

    for i in range(im_result.shape[1]):

    for j in range(im_result.shape[2]):

    for k in range(im_result.shape[0]):

    if(im_result[k][i][j] == 255):

    im_fillhole[i][j] = colorize[k]

    break

    # 保存图像

    cv2.imwrite(SavePath, im_fillhole)

    填充结果如图4所示,所有孔洞均被填充。图4 填充结果

    现在问题又来了,如果我只想填充特定大小阈值以内的孔洞,不填充大空洞怎么办呢?OpenCV里有个函数findContours可以获取每一个孔洞的轮廓,然后用contourArea函数计算每个孔洞的面积,如果面积大于阈值就不填充。代码如下。

    import cv2;

    import numpy as np;

    def FillHole_RGB(imgPath,SavePath,SizeThreshold):

    # 读取图像为uint32,之所以选择uint32是因为下面转为0xbbggrr不溢出

    im_in_rgb = cv2.imread(imgPath).astype(np.uint32)

    # 将im_in_rgb的RGB颜色转换为 0xbbggrr

    im_in_lbl = im_in_rgb[:,:,0] + (im_in_rgb[:,:,1] << 8) + (im_in_rgb[:,:,2] << 16)

    # 将0xbbggrr颜色转换为0,1,2,...

    colors, im_in_lbl_new = np.unique(im_in_lbl, return_inverse=True)

    # 将im_in_lbl_new数组reshape为2维

    im_in_lbl_new = np.reshape(im_in_lbl_new,im_in_lbl.shape)

    # 创建从32位im_in_lbl_new到8位colorize颜色的映射

    colorize = np.empty((len(colors), 3), np.uint8)

    colorize[:,0] = (colors & 0x0000FF)

    colorize[:,1] = (colors & 0x00FF00) >> 8

    colorize[:,2] = (colors & 0xFF0000) >> 16

    # 输出一下colorize中的color

    print("Colors_RGB: \n",colorize)

    # 有几种颜色就设置几层数组,每层数组均为各种颜色的二值化数组

    im_result = np.zeros((len(colors),)+im_in_lbl_new.shape,np.uint8)

    # 初始化二值数组

    im_th = np.zeros(im_in_lbl_new.shape,np.uint8)

    for i in range(len(colors)):

    for j in range(im_th.shape[0]):

    for k in range(im_th.shape[1]):

    if(im_in_lbl_new[j][k]==i):

    im_th[j][k] = 255

    else:

    im_th[j][k] = 0

    # 复制 im_in 图像

    im_floodfill = im_th.copy()

    # Mask 用于 floodFill,mask多出来的2可以保证扫描的边界上的像素都会被处理.

    h, w = im_th.shape[:2]

    mask = np.zeros((h+2, w+2), np.uint8)

    isbreak = False

    for m in range(im_floodfill.shape[0]):

    for n in range(im_floodfill.shape[1]):

    if(im_floodfill[m][n]==0):

    seedPoint=(m,n)

    isbreak = True

    break

    if(isbreak):

    break

    # 得到im_floodfill

    cv2.floodFill(im_floodfill, mask, seedPoint, 255,4)

    # 得到im_floodfill的逆im_floodfill_inv,im_floodfill_inv包含所有孔洞

    im_floodfill_inv = cv2.bitwise_not(im_floodfill)

    # 之所以复制一份im_floodfill_inv是因为函数findContours会改变im_floodfill_inv_copy

    im_floodfill_inv_copy = im_floodfill_inv.copy()

    # 函数findContours获取轮廓

    contours, hierarchy = cv2.findContours(im_floodfill_inv_copy, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

    for num in range(len(contours)):

    if(cv2.contourArea(contours[num])>=SizeThreshold):

    cv2.fillConvexPoly(im_floodfill_inv, contours[num], 0)

    # 把im_in、im_floodfill_inv这两幅图像结合起来得到前景

    im_out = im_th | im_floodfill_inv

    im_result[i] = im_out

    # rgb结果图像

    im_fillhole = np.zeros((im_in_lbl_new.shape[0],im_in_lbl_new.shape[1],3),np.uint8)

    # 之前的颜色映射起到了作用

    for i in range(im_result.shape[1]):

    for j in range(im_result.shape[2]):

    for k in range(im_result.shape[0]):

    if(im_result[k][i][j] == 255):

    im_fillhole[i][j] = colorize[k]

    break

    # 保存图像

    cv2.imwrite(SavePath, im_fillhole)

    填充结果如图5所示,所有阈值大小以内孔洞均被填充。图5 有阈值的填充结果

    目前以上代码测试没有问题,如有问题请留言,我们共同交流。

    【后言】

    python实现全连接CRFs后处理文字:馨意:【图像后处理】python实现全连接CRFs后处理​zhuanlan.zhihu.com

    展开全文
  • Python-基于OpenCV的轮廓填充 泛洪算法 孔洞填充

    千次阅读 多人点赞 2021-04-03 21:19:40
    孔洞填充就是在二值化下,图像中出现了“白点”或者“黑点”,这会影响我们计算轮廓里面的面积计算! 孔洞填充在这里我们针对的是二值图,并不是灰度图! 在OpenCV中实现imfill的步骤 阅读以下步骤时请参考下图. ...

    在这里插入图片描述
    左为原图 右为填充后

    针对轮廓填充,我们先要提取图像中的轮廓,在对里面的进行颜色填充,这个我自己也有点分不清楚,他和阈值分割进行填充有什么区别,要是有大佬知道,分享一下,将感激不尽!轮廓填充的方法常用的是泛洪算法!

    孔洞填充就是在二值化下,图像中出现了“白点”或者“黑点”,这会影响我们计算轮廓里面的面积计算!
    孔洞填充在这里我们针对的是二值图,并不是灰度图!

    在OpenCV中实现imfill的步骤
    阅读以下步骤时请参考下图.

    • 读取图片。
    • 将输入图像二值化。
    • 从像素(0,0)填充颜色。请注意,步骤2和步骤3的输出之间的差异在于步骤3中的图像的背景现在是白色的。
    • 反转洪水填充的图像(即黑色变为白色,白色变为黑色)。
    • 使用按位OR运算将阈值图像与反向洪水填充图像组合以获得填充有孔的最终前景掩模。步骤4中的图像在边界内具有一些黑色区域。通过步骤2,填充了图像中的孔。因此,我们将两者结合起来得到前景蒙版。

    在这里插入图片描述
    左为二值化取图 右为二值化图
    简单来说就是两张背景不变图像,将轮廓里面的颜色取反,再将两张图片合并,这样就能对轮廓里面的“孔洞”进行填充;
    方法很笨,但是有效!

    重点来啦,上代码!!!!!

    import cv2;
    import numpy as np;
    
    '''
    图像说明:
    图像为二值化图像,255白色为目标物,0黑色为背景
    要填充白色目标物中的黑色空洞
    '''
    imgPath = "H:/image.jpg"
    im_in = cv2.imread(imgPath, cv2.IMREAD_GRAYSCALE);
    
    # 复制 im_in 图像
    im_floodfill = im_in.copy()
    
    # Mask 用于 floodFill,官方要求长宽+2
    h, w = im_in.shape[:2]
    mask = np.zeros((h+2, w+2), np.uint8)
    
    # floodFill函数中的seedPoint必须是背景
    isbreak = False
    for i in range(im_floodfill.shape[0]):
        for j in range(im_floodfill.shape[1]):
            if(im_floodfill[i][j]==0):
                seedPoint=(i,j)
                isbreak = True
                break
        if(isbreak):
            break
    # 得到im_floodfill
    cv2.floodFill(im_floodfill, mask, seedPoint, 255);
    
    # 得到im_floodfill的逆im_floodfill_inv
    im_floodfill_inv = cv2.bitwise_not(im_floodfill)
    # 把im_in、im_floodfill_inv这两幅图像结合起来得到前景
    im_out = im_in | im_floodfill_inv
    cv2.imshow('de',im_out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    在这里插入图片描述
    谢谢点赞评论!

    展开全文
  • 形态学重建:孔洞填充python实现

    千次阅读 多人点赞 2019-07-23 21:00:57
    基于形态学重建的孔洞填充应用。

    主要参考:(美)拉斐尔·C.冈萨雷斯. 数字图像处理 第3版[M]. 阮秋琦,译. 北京:电子工业出版社, 2017: 633.


    形态学重建

    形态学重建涉及两幅图像和一个结构元:

    • Marker 图像:包含变换的起点,将被连续膨胀,直至收敛
    • Mask 图像:用来约束膨胀结果,即 Mask >= Marker
    • 结构单元(Structuring Element,SE):定义连通性

    数学迭代式:
    Marker=(MarkerSE)Mask Marker = (Marker \oplus SE) \cap Mask
    代码示例:

    def imreconstruct(marker, mask, SE=np.ones([3,3])):
        """
        描述:以mask为约束,连续膨胀marker,实现形态学重建,其中mask >= marker
        
        参数:
            - marker 标记图像,单通道/三通道图像
            - mask   模板图像,与marker同型
            - conn   联通性重建结构元,参照matlab::imreconstruct::conn参数,默认为8联通
        """
        while True:
            marker_pre = marker
            dilation = cv.dilate(marker, kernel=SE)
            marker = np.min((dilation, mask), axis=0)
            if (marker_pre == marker).all():
                break
        return marker
    

    孔洞填充

    孔洞定义:被前景(白色)连通域包围的封闭的背景(黑色)区域,不限于圆形。如图所示。
    孔洞定义
    原理:
    以原图像的补集作为Mask,用来限制膨胀结果;以带有白色边框的黑色图像为初始Marker,用SE对其进行连续膨胀,直至收敛;最后对Marker取补即得到最终图像,与原图相减可得到填充图像。

    Marker(x,y)={255,(x,y)Boundary0,others Marker(x, y) = \left\{\begin{matrix} 255 & , & (x,y) \in Boundary\\ 0 & , & others \end{matrix}\right.

    代码示例:

    import numpy as np
    import cv2 as cv
    from matplotlib import pyplot as plt
    
    img = cv.imread("text.jpg")
    
    # 二值化
    imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    imgray[imgray < 100] = 0
    imgray[imgray >= 100] = 255
    
    # 原图取补得到MASK图像
    mask = 255 - imgray
    
    # 构造Marker图像
    marker = np.zeros_like(imgray)
    marker[0, :] = 255
    marker[-1, :] = 255
    marker[:, 0] = 255
    marker[:, -1] = 255
    marker_0 = marker.copy()
    
    # 形态学重建
    SE = cv.getStructuringElement(shape=cv.MORPH_CROSS, ksize=(3, 3))
    while True:
        marker_pre = marker
        dilation = cv.dilate(marker, kernel=SE)
        marker = np.min((dilation, mask), axis=0)
        if (marker_pre == marker).all():
            break
    dst = 255 - marker
    filling = dst - imgray
    
    # 显示
    plt.figure(figsize=(12, 6))  # width * height
    plt.subplot(2, 3, 1), plt.imshow(imgray, cmap='gray'), plt.title('src'), plt.axis("off")
    plt.subplot(2, 3, 2), plt.imshow(mask, cmap='gray'), plt.title('Mask'), plt.axis("off")
    plt.subplot(2, 3, 3), plt.imshow(marker_0, cmap='gray'), plt.title('Marker 0'), plt.axis("off")
    plt.subplot(2, 3, 4), plt.imshow(marker, cmap='gray'), plt.title('Marker'), plt.axis("off")
    plt.subplot(2, 3, 5), plt.imshow(dst, cmap='gray'), plt.title('dst'), plt.axis("off")
    plt.subplot(2, 3, 6), plt.imshow(filling, cmap='gray'), plt.title('Holes'), plt.axis("off")
    plt.show()
    
    

    结果展示:
    Figure_1

    原图 text.jpg
    text.jpg

    选用不同尺寸的SE,进行填充对比:ksize=3x3(左),ksize=7x7(右)
    ksize=3x3(左),ksize=7x7(右)
    由此可见, 如果选择的结构单元过大,膨胀操作会越过边界,膨胀到孔洞中,导致部分孔洞填充失败。就本例来看3x3的SE可以做到准确填充。

    并且,对于大小不一的孔洞,3x3的SE同样可以做到准确填充。如图所示:
    在这里插入图片描述

    注: 关于孔洞填充的其他问题,可以参考博文 形态学填充孔洞的几个问题

    展开全文
  • 今天我们就用python语言基于OpenCV实现孔洞填充。 代码实现: import cv2; import numpy as np; ''' 图像说明: 图像为二值化图像,255白色为目标物,0黑色为背景 要填充白色目标物中的黑色空洞 ''' def FillHole...
  • 做项目需要对灰度图像进行空洞填充,但是网上全都是关于灰度图像的空洞填充,我的图像内容包含重要信息,所以不能转化为灰度图像. 代码如下: import numpy as np import scipy as sp import scipy.ndimage def ...
  • 孔洞填充.py

    2017-10-20 17:58:47
    本工具使用的是python实现,主要的功能就是孔洞填充的实现。
  • 今天我们就用python语言基于OpenCV实现孔洞填充。 代码实现: import cv2; import numpy as np; def FillHole_RGB(imgPath,SavePath): # 读取图像为uint32,之所以选择uint32是因为下面转为0xbbggrr不溢出 im_in_...
  • opencv_python实现二值图像的孔洞填充

    万次阅读 2018-07-24 21:37:20
    在本教程中,我们将学习如何填充二值图像中的孔。参考图1左侧的图像,假设我们想要找到一个二值模板,它将硬币与背景分开,如右图所示。在本教程中,包含硬币的圆形区域也将被称为前景。 请注意,硬币的边界是黑色...
  • 因为左边的图片存在很多噪声点,直接根据阈值去填充会存在问题,所以我就先对图片进行了一次二值化处理,然后调用了opencv的fillPoly函数完成孔洞填充。 import cv2 import os import numpy as np imaPath = r"E:...
  • 今天我们就用python语言基于OpenCV实现孔洞填充。图1 有孔洞的分割图像我们要用到的函数是OpenCV里的floodFill函数。使用floodFill函数可以得到只标记孔洞的像素矩阵(孔洞值为0,非孔洞值为指定值)。有了...
  • 图像处理——孔洞填充算法

    千次阅读 2020-08-28 15:06:48
    3、最后对Marker取补即得到最终图像,与原图相减可得到填充图像。 python代码: # -*- coding:utf-8 -*- import numpy as np import cv2 class kdtc(): def __init__(self): pass def readTif(sel
  • 2019独角兽企业重金招聘Python工程师标准>>> ...
  • 填充二值图像的孔洞是一个非常常见的方法,因为某些原因我不得不用python来写我的程序,当我想要使用类似于MATLAB 中的imfill 方法时, 我最初发现的是opencv 中的cv2.floodFill 的方法,其实现的过程有点麻烦,而且...
  • 这是一个用python做图像处理的教程 里面包含了,阈值化,局部阈值化,各种分割算法,膨胀腐蚀,孔洞填充,批量处理,特征提取,神经网络分类算法等等, 而且有相当全面的中文注释做支撑,欢迎大家学习交流 ...
  • 脑血管医学图像颅内分割尝试——分水岭算法code 1.2 不分割颅内直接分割code 2.0 实验版code 3.0 批量处理版code 3.1 加入孔洞填充总结 本篇博客原目的同...

空空如也

空空如也

1 2 3
收藏数 45
精华内容 18
关键字:

python孔洞填充

python 订阅