亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++ Opencv imfill孔洞填充函數(shù)的實(shí)現(xiàn)思路與代碼

 更新時(shí)間:2021年09月26日 12:43:36   作者:LYK_DoDo  
在Matlab下,使用imfill可以很容易的完成孔洞填充操作,下面這篇文章主要給大家介紹了關(guān)于C++ Opencv imfill孔洞填充函數(shù)的實(shí)現(xiàn)思路與代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下

函數(shù)實(shí)現(xiàn)的中心思想

二值圖

此程序針對(duì)于二值圖,尋找二值圖中 像素值為0的連通域,將所有連通域的像素點(diǎn)分別保存下來(lái),將符合條件的連通域的像素值 置為255;

尋找連通域的關(guān)鍵

針對(duì)填洞功能的實(shí)現(xiàn),也就是0置為255過(guò)程,我們需要以四連通為基本點(diǎn)進(jìn)行尋找。

種子點(diǎn)的確定

尋找種子點(diǎn),其實(shí)就是尋找二值圖中像素值為0的點(diǎn),我們可以直接采取 遍歷 二值圖 中的像素,將第一個(gè)遇見(jiàn)的像素值為0的點(diǎn)確定為 第一個(gè)連通域的種子點(diǎn)。這時(shí)候,有一些朋友可能會(huì)疑惑,因?yàn)榘凑瘴业恼f(shuō)法,在遍歷 的過(guò)程中,遇見(jiàn)的第n個(gè)像素值為0的點(diǎn) 就是第n個(gè)連通域的種子點(diǎn),進(jìn)一步說(shuō),在整個(gè)遍歷過(guò)程中,遇見(jiàn)像素值為0的像素點(diǎn)的個(gè)數(shù),就是連通域的個(gè)數(shù)。
是的!

當(dāng)然,如果要實(shí)現(xiàn)這一點(diǎn),那我們就需要在各個(gè)連通域的尋找的過(guò)程中,將找到的點(diǎn)全部立即置為255,(此處不一定非得是255,只要不是0即可)這樣在尋找結(jié)束后,我們?cè)俦闅v二值圖時(shí),已經(jīng)找到的連通域中的所有像素點(diǎn)的值均為255,當(dāng)再次找到像素值為0 的像素點(diǎn)時(shí),此像素點(diǎn)必是下一個(gè)待尋找的連通域的種子點(diǎn)

連通域的尋找過(guò)程

首先創(chuàng)建四連通的向量,vector<Point> upp;用來(lái)存儲(chǔ)上下前后四個(gè)點(diǎn),創(chuàng)建vector<vector<vector<Point>>> lenm;用來(lái)存儲(chǔ)所有的連通域,至于為什么要?jiǎng)?chuàng)建三維Point數(shù)組,大家可以先看看關(guān)于這個(gè)三維數(shù)組的注釋,(下面的公式就是,程序中也有相應(yīng)的注釋),了解清楚每一維代表的意義,再結(jié)合一下程序,我感覺(jué)大家應(yīng)該可以明白,再簡(jiǎn)要贅述一下,lenm.size()為連通域的個(gè)數(shù)。

如圖所示;函數(shù)為第i個(gè)連通域像素點(diǎn)個(gè)數(shù)的求和。

條件設(shè)定

在經(jīng)過(guò)以上的尋找過(guò)程后,得到的結(jié)果必然是全白的圖像,而我們只想要填充孔洞,所以我們需要去除不符合的連通域。所謂孔洞,其實(shí)就是周?chē)幌袼刂禐?55的點(diǎn)包圍起來(lái)的連通域,但是,有一些連通域,直接和圖像的邊界相連,而這并不是我們想要的, 至少不是我想要的,(如果大家有不同的需求,程序也是很容易改過(guò)去的)。所以,我需要一個(gè)標(biāo)志位,當(dāng)這個(gè)連通域中的像素點(diǎn)接觸到邊界后,給這個(gè)連通域一個(gè)標(biāo)記。在下面的程序中,我用vector<vector<int>> Flag;來(lái)存儲(chǔ)標(biāo)記點(diǎn),其中Flag[i]表示第i個(gè)連通域的標(biāo)記點(diǎn)。在程序中,找到種子點(diǎn)后,首先將第i個(gè)連通域的Flag[i][0] = 1;,如果在此連通域中出現(xiàn)邊界點(diǎn),再Flag[i][0] = 0;(在程序中,此處貌似有一個(gè)小BUG,我就先不改了[😏])

最后賦值

在尋找到的所有連通域中,F(xiàn)lag[i][0] == 1; {其中 i 屬于 [0,F(xiàn)lag.size()) }的連通域?yàn)榉弦蟮倪B通域,因此將lenm[i];中的所有像素點(diǎn)賦值255即可。

話不多說(shuō) 直接上函數(shù)代碼

輸入二值圖;

返回二值圖;

Mat imfill(Mat cop)
{
	Mat fcop;
	cop.copyTo(fcop);
	vector<Point> upp;//定義四連通點(diǎn)集,有必要可以是八連通
	upp.push_back(Point(-1, 0));
	upp.push_back(Point(0, -1));
	upp.push_back(Point(0, 1));
	upp.push_back(Point(1, 0));
	//upp.push_back(Point(1, 1));
	//upp.push_back(Point(-1,-1));
	//upp.push_back(Point(-1, 1));
	//upp.push_back(Point(1, -1));

	vector<vector<vector<Point>>> lenm;//三維point向量 lenm.size()是連通域的個(gè)數(shù)
	/*
	int impixel_sum = 0;
	for (int j = 0,j<lenm[i].size();j++)
	{
	    impixel_sum+= lenm[i][j].size();
	}
	//這段循環(huán) 表示第i個(gè)連通域中 像素點(diǎn)的個(gè)數(shù)。
	*/
	vector<vector<Point>> numim;
	vector<Point> ssinum;
	vector<vector<int>> Flag;
	vector<int> ce;

	int nmss = 0;//連通域的個(gè)數(shù);
	int nums = 0;//中間變量 用來(lái)存儲(chǔ) lenm.size();即 在程序運(yùn)行過(guò)程中 nums始終等于 lenm[i][j][k] 中的j 的 值的大小;
	int s1 = 0;
	//標(biāo)志位 ,每次區(qū)域生長(zhǎng)后 符合條件的像素個(gè)數(shù),當(dāng)?shù)趇個(gè)連通域,在經(jīng)過(guò)第j次生長(zhǎng)后,s1=lenm[i][j].size(),
	//若s1==0,表示生長(zhǎng)結(jié)束,不再有符合條件的點(diǎn),第i連通域中的所有點(diǎn)都已經(jīng)找到。

	for (int row = 0; row < fcop.rows; row++)
	{
		for (int col = 0; col < fcop.cols; col++)
		{
			if (fcop.at<uchar>(row, col) == 0)
			{
				ce.push_back(1);
				Flag.push_back(ce);
				//vector<vector<Point>> numim;
				//vector<Point> ssinum;
				ssinum.push_back(Point(col, row));
				numim.push_back(ssinum);
				fcop.at<uchar>(row, col) = 255;
				ssinum.clear();
				s1 = 1;
				while (s1 > 0)
				{
					//ce.push_back(1);
					//Flag.push_back(ce);
					//vector<Point> ssinum;
					for (int i = 0; i < numim[nums].size(); i++)
					{
						for (int j = 0; j < upp.size(); j++)
						{
							int X = numim[nums][i].x + upp[j].x;
							int Y = numim[nums][i].y + upp[j].y;
							if (X >= 0 && Y >= 0 && X < fcop.cols && Y < fcop.rows)
							{
								if (fcop.at<uchar>(Y, X) == 0)
								{
									ssinum.push_back(Point(X, Y));
									fcop.at<uchar>(Y, X) = 255;
								}
							}

							if (X == 0 || Y == 0 || X == fcop.cols - 1 || Y == fcop.rows - 1)
							{
								Flag[nmss][0] = 0;

							}
						}
					}
					//Flag.push_back(ce);
					numim.push_back(ssinum);
					s1 = ssinum.size();
					nums++;
					ssinum.clear();
					/*ce.clear();*/
				}
				nums = 0;
				lenm.push_back(numim);
				numim.clear();
				nmss++;
				ce.clear();
			}

		}
	}
	//imshow("1",fcop);
	Mat ffcop;
	cop.copyTo(ffcop);
	//ffcop = Mat::zeros(cop.size(),cop.type());
	for (int i = 0; i < Flag.size(); i++)
	{
		if (Flag[i][0] == 1)
		{
			for (int j = 0; j < lenm[i].size(); j++)
			{
				for (int k = 0; k < lenm[i][j].size(); k++)
				{
					int X = lenm[i][j][k].x;
					int Y = lenm[i][j][k].y;
					ffcop.at<char>(Y, X) = 255;
				}
			}
		}
	}
	return ffcop;
}

主函數(shù)代碼

#include<opencv2/opencv.hpp>
#include<iostream>

#include"imfill.h"

using namespace std;
using namespace cv;

Mat src;
vector<vector<Point>>  lunk;
vector<Vec4i> level;

//RNG rn;
int main()
{
	src = imread("5.jpg");
	//imshow("萬(wàn)丈高樓第一步",src);

	Mat dst, gray, erzhi;
	blur(src, dst, Size(3, 3), Point(-1, -1));
	//imshow("均值濾波",dst);

	cvtColor(dst, gray, COLOR_BGR2GRAY);
	//imshow("灰度圖",gray);

	Canny(gray, erzhi, 100, 200, 3, false);
	//imshow("邊緣檢測(cè)",erzhi);

	Mat holef;
	holef = imfill(erzhi);
	imshow("填洞", holef);
	
	waitKey(0);
	return 0;
}

代碼框截圖

實(shí)例圖片

運(yùn)行結(jié)果

總結(jié)

此程序會(huì)填充所有的孔洞,如果想只填充指定閾值范圍內(nèi)的孔洞,需要再多計(jì)算每個(gè)連通域像素的個(gè)數(shù)即可,因?yàn)樗袛?shù)據(jù)都已經(jīng)存了下來(lái),所以計(jì)算會(huì)比較簡(jiǎn)單。

到此這篇關(guān)于C++ Opencv imfill孔洞填充函數(shù)的文章就介紹到這了,更多相關(guān)C++ Opencv imfill孔洞填充函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入分析C語(yǔ)言分解質(zhì)因數(shù)的實(shí)現(xiàn)方法

    深入分析C語(yǔ)言分解質(zhì)因數(shù)的實(shí)現(xiàn)方法

    這篇文章主要介紹了深入分析C語(yǔ)言分解質(zhì)因數(shù)的實(shí)現(xiàn)方法,作者結(jié)合了ACM題目作為相關(guān)拓展,需要的朋友可以參考下
    2015-08-08
  • C語(yǔ)言學(xué)習(xí)筆記之VS2022安裝使用教程

    C語(yǔ)言學(xué)習(xí)筆記之VS2022安裝使用教程

    這篇文章主要介紹了C語(yǔ)言學(xué)習(xí)筆記之VS2022安裝使用教程,在VS2022中,在使用scanf函數(shù)編譯出錯(cuò),本文給大家提到了解決方法,需要的朋友可以參考下
    2022-05-05
  • 利用Matlab繪制地圖的超詳細(xì)教程

    利用Matlab繪制地圖的超詳細(xì)教程

    worldmap和usamap是axesm的子類,worldmap是用于生成世界地圖坐標(biāo)區(qū)域,usamap用于生成美國(guó)地圖坐標(biāo)區(qū)域。本文將詳細(xì)為大家介紹如何利用這兩個(gè)函數(shù)繪制地圖,需要的可以參考一下
    2022-02-02
  • c++ *運(yùn)算符重載

    c++ *運(yùn)算符重載

    運(yùn)算符重載重載運(yùn)算符是C++ 的一個(gè)重要特性,使用運(yùn)算符重載, 的一個(gè)重要特性,使用運(yùn)算符重載, 重載運(yùn)算符是程序員可以把C++ 運(yùn)算符的定義擴(kuò)展到運(yùn)算分量是對(duì)象
    2014-09-09
  • C++?std::array實(shí)現(xiàn)編譯器排序

    C++?std::array實(shí)現(xiàn)編譯器排序

    這篇文章主要介紹了C++?std::array實(shí)現(xiàn)編譯器排序,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • Qt自定義控件實(shí)現(xiàn)簡(jiǎn)易儀表盤(pán)

    Qt自定義控件實(shí)現(xiàn)簡(jiǎn)易儀表盤(pán)

    這篇文章主要為大家詳細(xì)介紹了Qt自定義控件實(shí)現(xiàn)簡(jiǎn)易儀表盤(pán),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • 常用的C語(yǔ)言排序算法(兩種)

    常用的C語(yǔ)言排序算法(兩種)

    本文給大家分享兩種常用的C語(yǔ)言排序算法,代碼非常簡(jiǎn)單,感興趣的朋友可以參考下
    2016-09-09
  • C++ OpenCV實(shí)戰(zhàn)之圖像透視矯正

    C++ OpenCV實(shí)戰(zhàn)之圖像透視矯正

    這篇文章主要介紹了通過(guò)C++ OpenCV實(shí)現(xiàn)圖像的透視矯正,文中的示例代碼講解詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的參考價(jià)值,感興趣的可以了解一下
    2022-01-01
  • C++智能指針之shared_ptr詳解

    C++智能指針之shared_ptr詳解

    這篇文章主要為大家詳細(xì)介紹了C++智能指針之shared_ptr,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • C++中菱形繼承的解釋與處理詳解

    C++中菱形繼承的解釋與處理詳解

    菱形繼承是多重繼承中跑不掉的,Java拿掉了多重繼承,輔之以接口。C++中雖然沒(méi)有明確說(shuō)明接口這種東西,但是只有純虛函數(shù)的類可以看作Java中的接口,下面這篇文章主要給大家介紹了關(guān)于C++中菱形繼承的解釋與處理的相關(guān)資料,需要的朋友可以參考下
    2022-02-02

最新評(píng)論