<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
影象細化(Image Thinning),一般指二值影象的骨架化(Image Skeletonization)的一種操作運算。細化是將影象的線條從多畫素寬度減少到單位畫素寬度過程的簡稱,一些文章經常將細化結果描述為“骨架化”、“中軸轉換”和“對稱軸轉換”。
細化技術的一個主要應用領域是點陣圖向量化的預處理階段,相關研究表明,利用細化技術生成的點陣圖的骨架質量受到多種因素的影響,其中包括影象自身的噪聲、線條粗細不均勻、端點的確定以及線條交叉點選定等,因而對線劃影象進行細化從而生成高質量骨架的方法進行研究具有現實意義。
根據演演算法處理步驟的不同,細化演演算法分為迭代細化演演算法和非迭代細化演演算法。根據檢查畫素方法的不同,迭代細化演演算法又分為序列細化演演算法和並行細化演演算法。
迭代演演算法:即重複刪除影象邊緣滿足一定條件的畫素,最終得到單畫素寬頻骨架。
迭代方法依據其檢查畫素的方法又可以再分成:
細化演演算法有ZS演演算法和查表法。ZS細化演演算法是一種基於8領域的並行細化演演算法,通過對目標畫素8領域進行分佈的算術邏輯運算,來確定該畫素是否能刪除。八領域如下圖所示。
細化判斷依據為:內部點不能刪除、孤立不能刪除、直線端點不能刪除。
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的次數。在目標點8鄰域P2-P9的範圍內,畫素值由0變1的次數只能為1次。條件(2)保證了影象細化後的連通性。
第二次迭代中,畫素點如果滿足第一次迭代中的條件(1)和(2)及以下條件,則移除該畫素點:
(5)P2×P4×P8=0;
(6)P2×P6×P8=0;
重複以上迭代過程,直至處理完所有畫素點,此時細化完成。
查表法中,由於輸入的影象是一張二值圖,將其歸一化為畫素值只有0和1的影象,然後對其進行折積操作。具體折積操作為:將目標點的八領域和折積進行點乘,接著將所有值相加即可得表的索引M,下一步用索引值M去找表中對應的值,對應的值為0或1,就把目標點的畫素值修改為0或1,其中1為不可刪除點,0位可刪除點。重複上述步驟,遍歷完所有畫素點,對目標點進行查表、修改目標畫素值,最後得到細化結果。
#include<iostream> #include <opencv2opencv.hpp> using namespace std; using namespace cv; //查表法// Mat lookUpTable(Mat& mat, int lut[]) { Mat mat_in; mat.convertTo(mat_in, CV_16UC1); //8 轉 16 int MatX = mat_in.rows; int MatY = mat_in.cols; int num = 512; //表的維數和折積核中的資料有關,小矩陣初始化按行賦值 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區域 mat_in.copyTo(mat_expend_Roi); //將傳入矩陣賦給Roi區域 Mat Mat_conv; //實用折積核和和每一個八鄰域進行點乘再相加,其結果為表的索引,對應值為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; //在數位影像處理時,只有單通道、三通道 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函數返回灰度值不為0的畫素數 bool mat_equal = countNonZero(diff) == 0; //判斷影象是否全黑 if (mat_equal) { break; } } Mat Matout; mat_bool.convertTo(Matout, CV_8UC1); return Matout; } //主函數 int main() { Mat src_img, src_imgBool; //輸入道路二值圖,引數 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); //儲存結果 imwrite("D:\Desktop\......\細化222.png", imgbone * 255); waitKey(); system("pause"); return 0; }
細化前
細化後
到此這篇關於OpenCV實現影象細化演演算法的文章就介紹到這了,更多相關OpenCV 影象細化內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45