最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

OpenCV實現(xiàn)圖像細化算法

 更新時間:2022年08月02日 11:36:54   作者:龍蝦在剝我的殼  
本文主要介紹了OpenCV實現(xiàn)圖像細化算法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

1.基礎概念

圖像細化(Image Thinning),一般指二值圖像的骨架化(Image Skeletonization)的一種操作運算。細化是將圖像的線條從多像素寬度減少到單位像素寬度過程的簡稱,一些文章經(jīng)常將細化結(jié)果描述為“骨架化”、“中軸轉(zhuǎn)換”和“對稱軸轉(zhuǎn)換”。

細化技術的一個主要應用領域是位圖矢量化的預處理階段,相關研究表明,利用細化技術生成的位圖的骨架質(zhì)量受到多種因素的影響,其中包括圖像自身的噪聲、線條粗細不均勻、端點的確定以及線條交叉點選定等,因而對線劃圖像進行細化從而生成高質(zhì)量骨架的方法進行研究具有現(xiàn)實意義。

根據(jù)算法處理步驟的不同,細化算法分為迭代細化算法和非迭代細化算法。根據(jù)檢查像素方法的不同,迭代細化算法又分為串行細化算法和并行細化算法。

迭代算法:即重復刪除圖像邊緣滿足一定條件的像素,最終得到單像素寬帶骨架。

迭代方法依據(jù)其檢查像素的方法又可以再分成:

  • 串行算法:在串行算法中,通過在每次迭代中用固定的次序檢查像素來判斷是否刪除像素,在第n次迭代中像素p的刪除取決于到執(zhí)行過的所有操作,也就是必須在第(n-1)次迭代結(jié)果和第n次檢測像素的基礎之上進行像素刪除操作;即是否刪除像素在每次迭代的執(zhí)行中是固定順序的,它不僅取決于前次迭代的結(jié)果,也取決于本次迭代中已處理過像素點分布情況。
  • 并行算法:在并行算法中,第n次迭代中像素的刪除只取決于(n-1)次迭代后留下的結(jié)果,因此所有像素能在每次迭代中以并行的方式獨立的被檢測;即像素點刪除與否與像素值圖像中的順序無關,僅取決于前次迭代效果。

2.細化過程

細化算法有ZS算法和查表法。ZS細化算法是一種基于8領域的并行細化算法,通過對目標像素8領域進行分布的算術邏輯運算,來確定該像素是否能刪除。八領域如下圖所示。

在這里插入圖片描述

細化判斷依據(jù)為:內(nèi)部點不能刪除、孤立不能刪除、直線端點不能刪除。
ZS細化過程如下:

第一次迭代,若P1滿足以下四個條件,說明P1為邊界點,可以刪除,將P1值設為0:
(1)2 小于等于 Pi從i=2到i=9的和 小于等于6
(2)S(P1)=1;
(3)P2×P4×P6=0;
(4)P4×P6×P8=0;

條件(1)中若P2至P9的和在2至6之間,說明P1為邊界點。S(P1)表示目標像素P1的8鄰域中,順時針變化一周像素由0變1的次數(shù)。在目標點8鄰域P2-P9的范圍內(nèi),像素值由0變1的次數(shù)只能為1次。條件(2)保證了圖像細化后的連通性。
第二次迭代中,像素點如果滿足第一次迭代中的條件(1)和(2)及以下條件,則移除該像素點:

(5)P2×P4×P8=0;
(6)P2×P6×P8=0;

重復以上迭代過程,直至處理完所有像素點,此時細化完成。
查表法中,由于輸入的圖像是一張二值圖,將其歸一化為像素值只有0和1的圖像,然后對其進行卷積操作。具體卷積操作為:將目標點的八領域和卷積進行點乘,接著將所有值相加即可得表的索引M,下一步用索引值M去找表中對應的值,對應的值為0或1,就把目標點的像素值修改為0或1,其中1為不可刪除點,0位可刪除點。重復上述步驟,遍歷完所有像素點,對目標點進行查表、修改目標像素值,最后得到細化結(jié)果。

3.代碼實現(xiàn)

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

using namespace std;
using namespace cv;

//查表法//
Mat lookUpTable(Mat& mat, int lut[])
{
	Mat mat_in;
	mat.convertTo(mat_in, CV_16UC1);		 //8 轉(zhuǎn) 16
	int MatX = mat_in.rows;
	int MatY = mat_in.cols;
	int num = 512;
	//表的維數(shù)和卷積核中的數(shù)據(jù)有關,小矩陣初始化按行賦值
	Mat kern = (Mat_<int>(3, 3) << 1, 8, 64, 2, 16, 128, 4, 32, 256);		//卷積核
	Mat mat_out = Mat::zeros(MatX, MatY, CV_16UC1);
	Mat mat_expend = Mat::zeros(MatX + 2, MatY + 2, CV_16UC1);

	Rect Roi(1, 1, MatY, MatX);				//(列,行,列,行)

	Mat mat_expend_Roi(mat_expend, Roi);	//確定擴展矩陣的Roi區(qū)域
	mat_in.copyTo(mat_expend_Roi);			//將傳入矩陣賦給Roi區(qū)域

	Mat Mat_conv;

	//實用卷積核和和每一個八鄰域進行點乘再相加,其結(jié)果為表的索引,對應值為0能去掉,為1則不能去掉
	filter2D(mat_expend, Mat_conv, mat_expend.depth(), kern);				//卷積
	Mat mat_index = Mat_conv(Rect(1, 1, MatY, MatX));
	for (int i = 0; i < MatX; i++)
	{
		for (int j = 0; j < MatY; j++)
		{
			int matindex = mat_index.at<short>(i, j);

			if ((matindex < num) && (matindex > 0))
			{
				mat_out.at<short>(i, j) = lut[matindex];
			}
			else if (matindex > num)
			{
				mat_out.at<short>(i, j) = lut[num - 1];
			}
		}
	}
	return mat_out;
}

//道路細化查表法//
Mat img_bone(Mat& mat)
{
	// mat 為細化后的圖像
	Mat mat_in = mat;

	//在數(shù)字圖像處理時,只有單通道、三通道 8bit 和 16bit 無符號(即CV_16U)的 mat 才能被保存為圖像
	mat.convertTo(mat_in, CV_16UC1);

	int lut_1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };

	int lut_2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 };

	Mat mat_bool;

	threshold(mat_in, mat_bool, 0, 1, THRESH_BINARY);	//二值圖像歸一化

	Mat mat_out;

	Mat image_iters;

	while (true)
	{
		mat_out = mat_bool;

		//查表:水平、垂直
		image_iters = lookUpTable(mat_bool, lut_1);
		mat_bool = lookUpTable(image_iters, lut_2);

		Mat diff = mat_out != mat_bool;

		//countNonZero函數(shù)返回灰度值不為0的像素數(shù)
		bool mat_equal = countNonZero(diff) == 0;		//判斷圖像是否全黑

		if (mat_equal)
		{
			break;
		}
	}
	Mat Matout;

	mat_bool.convertTo(Matout, CV_8UC1);

	return Matout;
}

//主函數(shù)
int main()
{
	Mat src_img, src_imgBool;

	//輸入道路二值圖,參數(shù) 0 是指imread按單通道的方式讀入圖像,即灰白圖像
	src_img = imread("......png", 0);
	
	//去掉噪,例如過濾很小或很大像素值的圖像點
	//threshold(src_img, src_imgBool, 0, 255, THRESH_OTSU);
	//threshold(src_img, src_imgBool, 0, 155, THRESH_OTSU);
	//imshow("Binary Image", src_imgBool);

	Mat imgbone = img_bone(src_img);

	//保存結(jié)果
	imwrite("D:\\Desktop\\......\\細化222.png", imgbone * 255);
	
	waitKey();
	system("pause");
	return 0;
}

4.實驗結(jié)果

細化前

在這里插入圖片描述

細化后

在這里插入圖片描述

到此這篇關于OpenCV實現(xiàn)圖像細化算法的文章就介紹到這了,更多相關OpenCV 圖像細化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 淺談Qt信號槽與事件循環(huán)的關系

    淺談Qt信號槽與事件循環(huán)的關系

    本文主要介紹了Qt信號槽與事件循環(huán)的關系,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • c語言連接mysql數(shù)據(jù)庫的實現(xiàn)方法

    c語言連接mysql數(shù)據(jù)庫的實現(xiàn)方法

    C語言連接mysql數(shù)據(jù)庫,需要相應的頭文件和lib文件,如果你安裝Mysql數(shù)據(jù)庫,會在安裝目錄下找到這些庫文件,如果沒有安裝,也可以在網(wǎng)上找到
    2012-05-05
  • 基于Matlab實現(xiàn)離散系統(tǒng)分岔圖的繪制

    基于Matlab實現(xiàn)離散系統(tǒng)分岔圖的繪制

    這篇文章主要介紹了如何利用Matlab實現(xiàn)離散分岔圖的繪制,文中的示例代碼講解詳細,對我們學習Matlab有一定的幫助,需要的可以參考一下
    2022-04-04
  • OpenCV實現(xiàn)馬賽克和毛玻璃濾鏡效果

    OpenCV實現(xiàn)馬賽克和毛玻璃濾鏡效果

    這篇文章主要為大家詳細介紹了OpenCV實現(xiàn)馬賽克和毛玻璃濾鏡效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • QT與MATLAB混合編程的詳細教程

    QT與MATLAB混合編程的詳細教程

    最近項目需要,matlab的一些算法需要工程用,因此需要直接轉(zhuǎn)成Qt能夠調(diào)用的形式,下面這篇文章主要給大家介紹了關于QT與MATLAB混合編程的相關資料,需要的朋友可以參考下
    2023-01-01
  • Cocos2d-x學習筆記之CCLayerColor層的使用實例

    Cocos2d-x學習筆記之CCLayerColor層的使用實例

    這篇文章主要介紹了Cocos2d-x學習筆記之CCLayerColor層的使用實例,CCLayerColor是一個顏色布景層類,本文依然使用Hello World作為例子講解,需要的朋友可以參考下
    2014-09-09
  • C++實現(xiàn)簡單圖書館管理系統(tǒng)

    C++實現(xiàn)簡單圖書館管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡單圖書館管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C語言零基礎入門(2)

    C語言零基礎入門(2)

    這篇文章主要為大家詳細介紹了C語言零基礎入門的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • C語言之飛機大戰(zhàn)游戲

    C語言之飛機大戰(zhàn)游戲

    這篇文章主要為大家詳細介紹了C語言之飛機大戰(zhàn),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • C++中頭文件和源文件詳細介紹

    C++中頭文件和源文件詳細介紹

    這篇文章主要介紹了C++中頭文件和源文件詳細介紹的相關資料,需要的朋友可以參考下
    2017-02-02

最新評論

嘉兴市| 隆昌县| 周口市| 叶城县| 勐海县| 出国| 邯郸县| 茌平县| 林甸县| 岑溪市| 平和县| 台湾省| 达拉特旗| 玉环县| 吴旗县| 镇平县| 东安县| 综艺| 广灵县| 翼城县| 西充县| 台南县| 临沭县| 昭苏县| 磴口县| 思南县| 平安县| 虎林市| 平阳县| 石阡县| 哈巴河县| 沁源县| 永康市| 枝江市| 日照市| 武宣县| 平安县| 英德市| 延长县| 牡丹江市| 铁岭县|