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

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

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. Oh My Life~

    作者:HChan 链接:https://zhuanlan.zhihu.com/p/47084162 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. Part 1 那年 ...

  2. 【JavaScript排序】 sort()方法(解决null、undefined、0之间的排序(混乱)问题)

    JavaScript排序 - sort()方法 --解决null.undefined.0之间的排序(混乱)问题 一.普通的数组排序 ​ JavaScript中用方法sort()为数组排序.sort() ...

  3. Linux Block模块之IO合并代码解析

    1 IO路径 从内核角度看,进程产生的IO路径主要有三条: 缓存IO:系统绝大部分IO走的这种形式,充分利用文件系统层的page cache所带来的优势.应用程序产生的IO经系统调用落入page ca ...

  4. logback.xml详解

    介绍 之前博文有专门介绍过基于Log4j Appender 实现大数据平台组件日志的采集, 本篇主要对java项目中经常会接触到的logback.xml文件的配置做一个介绍和总结. logback.x ...

  5. numba jit加速python程序

    numba numba加速循环.numpy的一些运算,大概是将python和numpy的一些代码转化为机器代码,速度飞快! 加速耗时很长的循环时: from numba import jit # 在函 ...

  6. JSP脚本知识

    JSP脚本元素 1.在jsp中嵌入的服务端运行的小程序称为脚本.实质是java程序. 2.脚本元素可以分为三类:表达式.Scriptlet.声明. 表达式 计算java表达式的值,得到的结果转化为字符 ...

  7. docker-compose编排启动LNMP

    2-1.docker-compose启动php #生成php镜像  [root@rocky8 data]#vim /data/dockerfile/ubuntu_php/Dockerfile  FRO ...

  8. springboot整合mybatisplus遇到的错误

    完全跟着mybatis_plus官网的案例一步一步来的,但是到junit的时候突然报错 Internal Error occurred. org.junit.platform.commons.JUni ...

  9. 表驱动法在STM32中的应用

    1.概念 所谓表驱动法(Table-Driven Approach)简而言之就是用查表的方法获取数据.此处的"表"通常为数组,但可视为数据库的一种体现.根据字典中的部首检字表查找读 ...

  10. 接入监控视频,为啥还需要对接厂商的SDK呢,不是有onvif这样的标准协议吗?

    不少人问过我这个问题,这真是一个好问题. 我举两个例子,让您仔细品: ① 快速打开视频和极致操控的问题. onvif协议很科班,但厂商的sdk可能会给你一些独特的方法,譬如先make一个I帧,这样第一 ...