opencv实现二值图像孔洞填充

Posted matlab和opencv数字图像处理笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv实现二值图像孔洞填充相关的知识,希望对你有一定的参考价值。

      matlab中的imfill函数可以方便得实现二值图像的孔洞填充,而在opencv中并没有相同功能的函数。因此,在opencv的基础上编写实现孔洞填充的函数,并且能够设定阈值,对面积大于阈值的孔洞不进行填充。使用形态学重建的算法能够有效地实现孔洞填充,具体算法原理参照《数字图像处理》第三版9.5.9节,孔洞填充。

    主要实现代码如下所示:其中imfill函数即为空洞填充的实现函数,第一个参数是二值图像(0~1),第二个参数是填充孔洞的阈值。若孔洞面积大于阈值则不填充,反之则填充。

  1. #include "iostream"  

  2. #include <opencv2\opencv.hpp>  

  3. using namespace std;  

  4. using namespace cv;  

  5. Mat inv_board(Mat src);  

  6. Mat inv_img(Mat src);  

  7. void delarea(Mat& bw, int max);  

  8. Mat imfill(Mat I, int max);  

  9. void main()  

  10. {  

  11.     Mat scr = imread("2.png");  

  12.     Mat I, src_gray, F_B, F_BI_C, temp, H, I_fill;  

  13.     cvtColor(scr, src_gray, COLOR_BGR2GRAY);  

  14.     threshold(src_gray, I, 0.1, 1,0);  

  15.     I_fill = imfill(I,40);  

  16.     imshow("原二值图", I * 255);  

  17.     imshow("填充图", I_fill*255);  

  18.     waitKey(0);  

  19. }  

  20.   

  21.   

  22. Mat imfill(Mat I,int max)  

  23. {  

  24.     Mat  src_gray, F_B, F_BI_C, temp, H, I_fill;  

  25.     I_fill = I.clone();  

  26.     Mat F = inv_board(I);  

  27.     Mat I_C = inv_img(I);  

  28.     Mat element = getStructuringElement(0, Size(3, 3), Point(1, 1));  

  29.     while (1)  

  30.     {  

  31.   

  32.   

  33.         dilate(F, F_B, element);  

  34.         F_BI_C = F_B.mul(I_C);  

  35.         temp = F_BI_C - F;  

  36.         if (sum(temp) == Scalar(0))  

  37.             break;  

  38.         else  

  39.             F = F_BI_C.clone();  

  40.     }  

  41.     H = inv_img(F_BI_C);  

  42.     Mat H_IC = H.mul(I_C);  

  43.     delarea(H_IC, max);  

  44.     for (int i = 0; i < H_IC.rows; i++)  

  45.     {  

  46.         for (int j = 0; j < H_IC.cols; j++)  

  47.         {  

  48.             if (H_IC.at<uchar>(i, j) == 1)  

  49.                 I_fill.at<uchar>(i, j) = 1;  

  50.         }  

  51.     }  

  52.     return I_fill;  

  53. }  

  54. Mat inv_board(Mat src)  

  55. {  

  56.       

  57.     int rows = src.rows;  

  58.     int cols = src.cols;  

  59.     Mat dst = Mat::zeros(rows, cols, CV_8UC1);  

  60.     for (int i = 0; i < cols; i++)  

  61.     {  

  62.         dst.at<uchar>(0, i) = 1 - src.at<uchar>(0, i);  

  63.     }  

  64.     for (int i = 0; i < cols; i++)  

  65.     {  

  66.         dst.at<uchar>(rows-1, i) = 1 - src.at<uchar>(rows - 1, i);  

  67.     }  

  68.     for (int i = 1; i < rows-1; i++)  

  69.     {  

  70.         dst.at<uchar>(i, 0) = 1 - src.at<uchar>(i, 0);  

  71.     }  

  72.     for (int i = 1; i < rows - 1; i++)  

  73.     {  

  74.         dst.at<uchar>(i, cols-1) = 1 - src.at<uchar>(i, cols-1);  

  75.     }  

  76.     return dst;  

  77. }  

  78.   

  79.   

  80. Mat inv_img(Mat src)  

  81. {  

  82.     int rows = src.rows;  

  83.     int cols = src.cols;  

  84.     Mat dst = src.clone();  

  85.     for (int i = 0; i < rows; i++)  

  86.         for (int j = 0; j < cols; j++)  

  87.             dst.at<uchar>(i, j) = 1 - src.at<uchar>(i, j);  

  88.     return dst;  

  89. }  

  90.   

  91.   

  92. void delarea(Mat& bw, int max )  

  93. {  

  94.     Mat bw_copy = bw.clone();  

  95.     int flag = 0;   

  96.     Mat H_b, H_bw, temp;  

  97.     Mat H = Mat::zeros(bw.size(), bw.type());  

  98.     for (int i = 0; i < bw.rows; i++)  

  99.     {  

  100.         for (int j = 0; j < bw.cols; j++)  

  101.         {  

  102.             if (bw_copy.at<uchar>(i, j) == 1)  

  103.             {  

  104.                 H.at<uchar>(i, j) = 1;  

  105.     Mat element = getStructuringElement(0, Size(3, 3), Point(1, 1));  

  106.     while (1)  

  107.     {  

  108.         dilate(H, H_b, element);   

  109.         H_bw = H_b.mul(bw);  

  110.         temp = H_bw - H;  

  111.         if (sum(temp) == Scalar(0))  

  112.             break;  

  113.         else  

  114.             H = H_bw.clone();  

  115.     }  

  116.     bw_copy = bw_copy - H_bw;  

  117.     if (sum(H_bw).val[0] > max)  

  118.     {  

  119.         bw = bw - H_bw;  

  120.     }  

  121.     H = Mat::zeros(bw.size(), bw.type());  

  122.             }  

  123.               

  124.         }  

  125.     }  

  126. }  

效果图如下:


以上是关于opencv实现二值图像孔洞填充的主要内容,如果未能解决你的问题,请参考以下文章

使用openCV去除二值图像中的噪声

python + opnencv实现图像孔洞填充

元器件图像识别计数

二值形态学——开闭运算

用opencv如何将一个二值化图像反色

opencv学习-图像二值化操作