**OpenCV:二值图像中填充孔洞**
本文介绍一种用OpenCV再二值化图像中填充孔洞的办法,如上图最左侧的硬币照片,我们想要用二值化图像来表示出硬币所在的位置(如右图所示),直接进行二值化分割的结果往往如中间的结果所示,在硬币所在位置内也包含和背景一样的灰度。
注意到硬币的边缘和背景颜色是黑色的,可以和背景明显的区分开来。所以我们可以先利用简单的二值化将边缘从背景中分割出来。
imfill in OpenCV
matlab里边由一个imfill函数可以很好的实现由最左图到最右图的转换,而OpenCV却没有这样现成的函数可以用,我们可以采用以下步骤来实现matlab中的imfill函数:
- 首先读取原始图片:
- 对原始图片进行二值化操作得到二值化图像:
- 从(0,0)点开始进行洪水填充,注意图3和图2之间的差异,背景部分一个是白色,一个是黑色:
- 对洪水填充后的结果取反:
- 将图2和图4进行逻辑或操作,将会得到最终空洞被填充的二值化图像如下
C++程序:
#include "opencv2/opencv.hpp"
using namespace cv;
int main(int argc, char **argv)
{
// Read image
Mat im_in = imread("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)
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);
}