opencv实现二值图像孔洞填充
生活随笔
收集整理的這篇文章主要介紹了
opencv实现二值图像孔洞填充
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
? ? ? matlab中的imfill函數(shù)可以方便得實現(xiàn)二值圖像的孔洞填充,而在opencv中并沒有相同功能的函數(shù)。因此,在opencv的基礎(chǔ)上編寫實現(xiàn)孔洞填充的函數(shù),并且能夠設(shè)定閾值,對面積大于閾值的孔洞不進行填充。使用形態(tài)學(xué)重建的算法能夠有效地實現(xiàn)孔洞填充,具體算法參照《數(shù)字圖像處理》第三版9.5.9節(jié),孔洞填充。
? ? 主要實現(xiàn)代碼如下所示:其中imfill函數(shù)即為空洞填充的實現(xiàn)函數(shù),第一個參數(shù)是二值圖像(0~1),第二個參數(shù)是填充孔洞的閾值。若孔洞面積大于閾值則不填充,反之則填充。
#include "iostream" #include <opencv2\opencv.hpp> using namespace std; using namespace cv; Mat inv_board(Mat src); Mat inv_img(Mat src); void delarea(Mat& bw, int max); Mat imfill(Mat I, int max); void main() {Mat scr = imread("2.png");Mat I, src_gray, F_B, F_BI_C, temp, H, I_fill;cvtColor(scr, src_gray, COLOR_BGR2GRAY);threshold(src_gray, I, 0.1, 1,0);I_fill = imfill(I,40);imshow("原二值圖", I * 255);imshow("填充圖", I_fill*255);waitKey(0); }Mat imfill(Mat I,int max) {Mat src_gray, F_B, F_BI_C, temp, H, I_fill;I_fill = I.clone();Mat F = inv_board(I);Mat I_C = inv_img(I);Mat element = getStructuringElement(0, Size(3, 3), Point(1, 1));while (1){dilate(F, F_B, element);F_BI_C = F_B.mul(I_C);temp = F_BI_C - F;if (sum(temp) == Scalar(0))break;elseF = F_BI_C.clone();}H = inv_img(F_BI_C);Mat H_IC = H.mul(I_C);delarea(H_IC, max);for (int i = 0; i < H_IC.rows; i++){for (int j = 0; j < H_IC.cols; j++){if (H_IC.at<uchar>(i, j) == 1)I_fill.at<uchar>(i, j) = 1;}}return I_fill; } Mat inv_board(Mat src) {int rows = src.rows;int cols = src.cols;Mat dst = Mat::zeros(rows, cols, CV_8UC1);for (int i = 0; i < cols; i++){dst.at<uchar>(0, i) = 1 - src.at<uchar>(0, i);}for (int i = 0; i < cols; i++){dst.at<uchar>(rows-1, i) = 1 - src.at<uchar>(rows - 1, i);}for (int i = 1; i < rows-1; i++){dst.at<uchar>(i, 0) = 1 - src.at<uchar>(i, 0);}for (int i = 1; i < rows - 1; i++){dst.at<uchar>(i, cols-1) = 1 - src.at<uchar>(i, cols-1);}return dst; }Mat inv_img(Mat src) {int rows = src.rows;int cols = src.cols;Mat dst = src.clone();for (int i = 0; i < rows; i++)for (int j = 0; j < cols; j++)dst.at<uchar>(i, j) = 1 - src.at<uchar>(i, j);return dst; }void delarea(Mat& bw, int max ) {Mat bw_copy = bw.clone();int flag = 0; Mat H_b, H_bw, temp;Mat H = Mat::zeros(bw.size(), bw.type());for (int i = 0; i < bw.rows; i++){for (int j = 0; j < bw.cols; j++){if (bw_copy.at<uchar>(i, j) == 1){H.at<uchar>(i, j) = 1;Mat element = getStructuringElement(0, Size(3, 3), Point(1, 1));while (1){dilate(H, H_b, element); H_bw = H_b.mul(bw);temp = H_bw - H;if (sum(temp) == Scalar(0))break;elseH = H_bw.clone();}bw_copy = bw_copy - H_bw;if (sum(H_bw).val[0] > max){bw = bw - H_bw;}H = Mat::zeros(bw.size(), bw.type());}}} }總結(jié)
以上是生活随笔為你收集整理的opencv实现二值图像孔洞填充的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式 | 装饰模式
- 下一篇: 微信扫一扫支付怎么弄?