图像的连通域检测的堆栈算法
生活随笔
收集整理的這篇文章主要介紹了
图像的连通域检测的堆栈算法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?? 圖像的連通域尋找在直覺上可使用遞歸的方法,進而可以使用堆棧數據結構進行改進。本文描述了一個圖像尋找連通域的堆棧方法,四連通域和八聯通域的選擇可以使用一個參數來確定。
???? 以下是代碼:
//根據種子點尋找8連通域//使用兩遍掃描//查找所有的連通域 //劃分為前景、背景、和無關位置 //一個點 也必須當做連通域 bool CD2DetectInPic::searchConBy8Con(const cv::Mat& _binImg, cv::Mat& _lableImg,float valueForeB,float valueForeUp, int GlintSizeLowerBound, int GlintSizeUpperBound,std::vector<std::vector<cv::Point > > &foreAreas) { // connected component analysis (8-component) // use seed filling algorithm // 1. begin with a foreground pixel and push its foreground neighbors into a stack; // 2. pop the top pixel on the stack and label it with the same label until the stack is empty if (_binImg.channels()>1){cv::cvtColor(_binImg,_lableImg,cv::COLOR_BGR2GRAY);}foreAreas.resize(0);尋找4連通域//int xNum[4] = {1,0,-1,0}; ?//int yNum[4] = {0,1,0,-1};? //尋找8連通域int xNum[8] = {1,1,0,-1,-1,-1,0,1}; int yNum[8] = {0,1,1,1,0,-1,-1,-1}; //一遍掃描,得出前景和背景點,進行標記//背景點標記為0,前景點標記為1,其他標記為255//cv::imshow("",_lableImg);//cv::waitKey(0);IplImage imageLabel = _lableImg;for (int i=0;i< imageLabel.height;++i){char* pI = (char*)imageLabel.imageData + i * imageLabel.widthStep;for (int j=0;j<imageLabel.width;++j ){if ( *pI >=valueForeB &&*pI <=valueForeUp)//避開單一值失誤!{*pI = 1;} else{*pI = 255;}++pI;}}//對label圖像進行遍歷,尋找連通域//對Mark矩陣,進行修改,不修改標識矩陣cv::Mat imageMark(&imageLabel);cv::Mat imageMarkRe = imageMark.clone();#if SHOW_TEMPcv::imshow("imageMarkRe",imageMarkRe);//cv::waitKey(0); #endifstd::stack<std::pair<int,int> > neighborPixels; //對圖片每個點進行尋找連通域,必須遍歷for (int m =0; m<imageMark.rows; ++m ){for (int n=0; n< imageMark.cols; ++n){//亮點,使用數組取代條件查找。。。 CvPoint seedT; if (imageMarkRe.at<uchar>(m,n) <120 )//遍歷前景{std::vector<cv::Point > foreArea;int x = seedT.x = n; //遍歷當前點int y = seedT.y = m; neighborPixels.push(std::pair<int,int>(x,y) ) ; cv::Point P(x,y); foreArea.push_back(P);//要把第一個點當做連通域while (!neighborPixels.empty()) { // get the top pixel on the stack and label it with the same label std::pair<int,int> curPixel = neighborPixels.top() ; int curX = seedT.x = curPixel.first ; int curY = seedT.y = curPixel.second ; neighborPixels.pop(); //標記取出,同時標記已遍歷imageMarkRe.at<uchar>(curY,curX) = 255;//標記為已遍歷//尋找前景8連通域//if (imageMark.at<uchar>(seedT.y,seedT.x) <120 && imageMarkRe.at<uchar>(seedT.y,seedT.x) <120){for(int k=0 ;k<8 ;k++) //四聯通要修改為4{ int yy = curY + yNum[k]; int xx = curX + xNum[k]; if (yy <0 || xx <0 ||yy >= imageMarkRe.rows || xx >= imageMarkRe.cols ){continue;} else{if (imageMark.at<uchar>(yy,xx) <120 && imageMarkRe.at<uchar>(yy,xx) <120 ){cv::Point P(xx,yy);std::pair<int,int> seedCur; seedCur.first =seedT.x = xx; seedCur.second =seedT.y = yy; foreArea.push_back(P);neighborPixels.push(seedCur);imageMarkRe.at<uchar>(yy,xx) = 255;//標記為已遍歷} }}}}if (foreArea.size()>=GlintSizeLowerBound && foreArea.size()<=GlintSizeUpperBound){foreAreas.push_back(foreArea);}}}}return true; }二值化圖像的結果:
? ?
除去小的邊緣的效果:
????
總結
以上是生活随笔為你收集整理的图像的连通域检测的堆栈算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 口袋妖怪剑盾有多少精灵
- 下一篇: ICCV2015上的GazeTracke