在本教程中,我们将学习如何填充二值图像中的孔。考虑下图左侧的图像。假设我们想要找到一个二值掩模,它将硬币与背景分开,如下图右侧图像所示。在本教程中,包含硬币的圆形区域也将被称为前景。

请注意,硬币的边界是黑色的,与白色背景不同。因此,我们使用简单的图像阈值来将边界与背景分开。换句话说,我们说强度高于某个值(阈值)的像素是背景,其余像素是前景。上图中间图像显示通过阈值分割获得图像(黑色代表背景,白色代表前景)。不幸的是,即使边界被很好地提取(它是纯白色),硬币的内部也具有与背景类似的强度。因此,阈值操作不能将其与背景分开。我们如何用白色填充圆形边界内的所有像素?然后将其分开。

1 imfill in OpenCV

MATLAB有一个名为imfill的函数 ,可以让你填充孔洞。OpenCV中没有imfill功能,但我们肯定可以写一个!我们知道像素点(0,0)连接到背景。因此,我们可以通过从像素(0,0)执行填充操作来提取背景。不受漫水填充操作影响的像素必然位于边界内。阈值图像与漫水填充图像或非运算后图像为前景掩模!

漫水填充算法是用来标记一片区域的:设置一个种子点,然后种子点附近的相似点都被填充同一种颜色。该算法应用性很广,比如目标识别,photoshop 的魔术棒功能等等,是填充类算法中应用最为广泛的一个算法。漫水填充也可以用来从输入图像获取掩码区域,掩码会加速处理过程,或者只处理掩码指定的像素点。其中掩膜Mask用于进一步控制那些区域将被填充颜色。漫水填充在OpenCV中通过floodfill函数实现,具体见:

https://blog.csdn.net/qq_37385726/article/details/82313004

在OpenCV中实现imfill结果类似下图,步骤如下:

1)读取图像,并转换为灰度图像,如下图1所示;

2)对输入图像进行阈值分割以获得二值图像,如下图2所示;

3)对于阈值分割后的图像进行漫水填充,从像素(0,0)填充颜色。请注意,步骤2和步骤3的输出之间的差异在于步骤3中的背景现在是白色的,如下图3所示。

4)反转漫水填充后的图像(即黑色变为白色,白色变为黑色),如下图4所示。

5)使用按位OR运算将阈值图像与反向漫水填充图像组合以获得填充有孔的最终前景掩模。步骤4中的图像在边界内具有一些黑色区域。根据设计,步骤2中的图像填充了这些孔。因此,我们将两者结合起来获得掩模,如下图5所示。

2 完整代码

还有其他方法可以解决同样的问题。一种方法是使用形态学闭运算操作。但是,要进行形态学操作,您需要知道孔的最大尺寸。另一种方法是使用findContours查找轮廓,然后使用drawContours填充它。我更喜欢这篇文章中所描述的技术的简单性和速度。

本文所有代码见:

https://github.com/luohenyueji/OpenCV-Practical-Exercise

C++:

#include "pch.h"
#include <opencv2/opencv.hpp> using namespace cv; int main()
{
// Read image 读取图像
Mat im_in = imread("./image/nickel.jpg", IMREAD_GRAYSCALE); // Threshold.
// Set values equal to or above 220 to 0.
// Set values below 220 to 255.
//阈值分割
Mat im_th;
threshold(im_in, im_th, 220, 255, THRESH_BINARY_INV); // Floodfill from point (0, 0) 以点(0,0)为种子点,进行漫水填充
Mat im_floodfill = im_th.clone();
floodFill(im_floodfill, cv::Point(0,0), Scalar(255)); // Invert floodfilled image 反转图像
Mat im_floodfill_inv;
bitwise_not(im_floodfill, im_floodfill_inv); // Combine the two images to get the foreground. 获得前景
Mat im_out = (im_th | im_floodfill_inv); // Display images 图像展示
imshow("Thresholded Image", im_th);
imshow("Floodfilled Image", im_floodfill);
imshow("Inverted Floodfilled Image", im_floodfill_inv);
imshow("Foreground", im_out);
waitKey(0);
return 0;
}

python:

#!/usr/bin/env python

import cv2;
import numpy as np; # Read image
im_in = cv2.imread("./image/nickel.jpg", cv2.IMREAD_GRAYSCALE); # Threshold.
# Set values equal to or above 220 to 0.
# Set values below 220 to 255. th, im_th = cv2.threshold(im_in, 220, 255, cv2.THRESH_BINARY_INV); # Copy the thresholded image.
im_floodfill = im_th.copy() # Mask used to flood filling.
# Notice the size needs to be 2 pixels than the image.
h, w = im_th.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_th | im_floodfill_inv # Display images.
cv2.imshow("Thresholded Image", im_th)
cv2.imshow("Floodfilled Image", im_floodfill)
cv2.imshow("Inverted Floodfilled Image", im_floodfill_inv)
cv2.imshow("Foreground", im_out)
cv2.waitKey(0)

3 参考

https://www.learnopencv.com/filling-holes-in-an-image-using-opencv-python-c/

[OpenCV实战]30 使用OpenCV实现图像孔洞填充的更多相关文章

  1. [OpenCV实战]45 基于OpenCV实现图像哈希算法

    目前有许多算法来衡量两幅图像的相似性,本文主要介绍在工程领域最常用的图像相似性算法评价算法:图像哈希算法(img hash).图像哈希算法通过获取图像的哈希值并比较两幅图像的哈希值的汉明距离来衡量两幅 ...

  2. [OpenCV实战]44 使用OpenCV进行图像超分放大

    图像超分辨率(Image Super Resolution)是指从低分辨率图像或图像序列得到高分辨率图像.图像超分辨率是计算机视觉领域中一个非常重要的研究问题,广泛应用于医学图像分析.生物识别.视频监 ...

  3. [OpenCV实战]20 使用OpenCV实现基于增强相关系数最大化的图像对齐

    目录 1 背景 1.1 彩色摄影的一个简短而不完整的历史 1.2 OpenCV中的运动模型 2 使用增强相关系数最大化(ECC)的图像对齐 2.1 findTransformECC在OpenCV中的示 ...

  4. [OpenCV实战]46 在OpenCV下应用图像强度变换实现图像对比度均衡

    本文主要介绍基于图像强度变换算法来实现图像对比度均衡.通过图像对比度均衡能够抑制图像中的无效信息,使图像转换为更符合计算机或人处理分析的形式,以提高图像的视觉价值和使用价值.本文主要通过OpenCV ...

  5. [OpenCV实战]50 用OpenCV制作低成本立体相机

    本文主要讲述利用OpenCV制作低成本立体相机以及如何使用OpenCV创建3D视频,准确来说是模仿双目立体相机,我们通常说立体相机一般是指双目立体相机,就是带两个摄像头的那种(目就是指眼睛,双目就是两 ...

  6. [OpenCV实战]29 使用OpenCV实现红眼自动去除

    目录 1 红眼消除 1.1 眼部检测 1.2 红眼遮掩 1.3 清除瞳孔掩模空洞 1.4 红眼修复 2 结果与完整代码 2.1 结果 2.2 代码 3 参考 在本教程中,我们将学习如何完全自动地从照片 ...

  7. [OpenCV实战]48 基于OpenCV实现图像质量评价

    本文主要介绍基于OpenCV contrib中的quality模块实现图像质量评价.图像质量评估Image Quality Analysis简称IQA,主要通过数学度量方法来评价图像质量的好坏. 本文 ...

  8. [OpenCV实战]47 基于OpenCV实现视觉显著性检测

    人类具有一种视觉注意机制,即当面对一个场景时,会选择性地忽略不感兴趣的区域,聚焦于感兴趣的区域.这些感兴趣的区域称为显著性区域.视觉显著性检测(Visual Saliency Detection,VS ...

  9. [OpenCV实战]19 使用OpenCV实现基于特征的图像对齐

    目录 1 背景 1.1 什么是图像对齐或图像对准? 1.2 图像对齐的应用 1.3 图像对齐基础理论 1.4 如何找到对应点 2 OpenCV的图像对齐 2.1 基于特征的图像对齐的步骤 2.2 代码 ...

随机推荐

  1. 使用python制作动图

    利用python制作gif图 引言 当写文章时候,多张图片会影响排版,可以考虑制作gif图 准备 pip install imageio 代码 # This is a sample Python sc ...

  2. 华为交换机GVRP基础配置

    GVRP基础配置 int G0/0/1 port link-type trunk 配置接口类型为trunk port trunk allow-pass vlan all 允许所有VLAN通过 int ...

  3. 关于Springboot启动报错 Whitelabel Error Page: This application has no explicit mapping

    Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as ...

  4. 如何用Virtualbox搭建一个虚拟机

    序言 各位好啊,我是会编程的蜗牛,作为java开发者,我们肯定会接触Linux服务器,除了使用云服务搭建Linux服务器外,我们一般也可以在自己的电脑上安装虚拟机来搭建Linux服务器用于各种功能的验 ...

  5. 使用 etcdadm 快速、弹性部署 etcd 集群

    Etcd 是一个可靠的分布式键值存储, 常用于分布式系统关键数据的存储:而 etcdadm 是一个用于操作 etcd 集群的命令行工具,它可以轻松创建集群.向现有集群添加成员.从现有集群中删除成员等操 ...

  6. 22.-CSRF攻击

    一.CSRF-跨站伪造请求攻击 某些恶意网站上包含链接.表单按钮或者JavaScript,它们会利用登录过的用户在浏览器中的认证信息视图在你的网站上完成某些操作 这就是跨站请求伪造(CSRF,即Cro ...

  7. Python 多重继承时metaclass conflict问题解决与原理探究

    背景 最近有一个需求需要自定义一个多继承abc.ABC与django.contrib.admin.ModelAdmin两个父类的抽象子类,方便不同模块复用大部分代码,同时强制必须实现所有抽象方法,没想 ...

  8. Ubuntu安装Docker及镜像加速器

    一.安装Docker sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificate ...

  9. .NET 7 AOT 的使用以及 .NET 与 Go 互相调用

    目录 背景 C# 部分 环境要求 创建一个控制台项目 体验 AOT 编译 C# 调用库函数 减少体积 C# 导出函数 C# 调用 C# 生成的 AOT Golang 部分 安装 GCC Golang ...

  10. Java使用lamda表达式简化代码

    代码,自然写的越简洁越好啦,写的人舒服,看的人也舒服,一切为了高效. 要把有限的时间花到其它有意思的事情上去. 目的 学习简化代码的思路,使用jdk8新特性lamada表达式. 使用 某接口,只有一个 ...