想要在這個連通域函式后續處理得到每個連通域的周長,面積等等
有相關的函式可以操作嗎?
還是需要自己手寫
或者用findContours函式?
用findContours函式感覺相當于分析了兩次很浪費。
uj5u.com熱心網友回復:
我推薦這個特征提取的綜合實驗(多種角度比較SIFT、SURF、BRISK、ORB演算法)
https://www.cnblogs.com/jsxyhelu/p/7813629.html
此外還包括:
https://zzk.cnblogs.com/my/s/blogpost-p?Keywords=%E7%89%B9%E5%BE%81%E7%82%B9
uj5u.com熱心網友回復:
上面發錯了,我推薦這個OpenCV中的新函式connectedComponentsWithStats使用
https://www.cnblogs.com/jsxyhelu/p/7439655.html
主要內容:對比新舊函式,用于過濾原始影像中輪廓分析后較小的區域,留下較大區域。
關鍵字 :connectedComponentsWithStats
在以前,常用的方法是”是先呼叫 cv::findContours() 函式(傳入cv::RETR_CCOMP 標志),隨后在得到的連通區域上回圈呼叫 cv::drawContours() “
比如,我在GOCVHelper中這樣進行了實作
//尋找最大的輪廓
VP FindBigestContour(Mat src){
int imax = 0; //代表最大輪廓的序號
int imaxcontour = -1; //代表最大輪廓的大小
std::vector<std::vector<Point>>contours;
findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
for (int i=0;i<contours.size();i++){
int itmp = contourArea(contours[i]);//這里采用的是輪廓大小
if (imaxcontour < itmp ){
imax = i;
imaxcontour = itmp;
}
}
return contours[imax];
}
//尋找并繪制出彩色聯通區域
vector<VP> connection2(Mat src,Mat& draw){
draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
vector<VP>contours;
findContours(src.clone(),contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
//由于給大的區域著色會覆寫小的區域,所以首先進行排序操作
//冒泡排序,由小到大排序
VP vptmp;
for(int i=1;i<contours.size();i++){
for(int j=contours.size()-1;j>=i;j--){
if (contourArea(contours[j]) < contourArea(contours[j-1]))
{
vptmp = contours[j-1];
contours[j-1] = contours[j];
contours[j] = vptmp;
}
}
}
在OpenCV3中有了新的專門的函式 cv::connectedComponents() 和函式 cv::connectedComponentsWithStats()
定義:
int cv::connectedComponents (
cv::InputArrayn image, // input 8-bit single-channel (binary)
cv::OutputArray labels, // output label map
int connectivity = 8, // 4- or 8-connected components
int ltype = CV_32S // Output label type (CV_32S or CV_16U)
);
int cv::connectedComponentsWithStats (
cv::InputArrayn image, // input 8-bit single-channel (binary)
cv::OutputArray labels, // output label map
cv::OutputArray stats, // Nx5 matrix (CV_32S) of statistics:
// [x0, y0, width0, height0, area0;
// ... ; x(N-1), y(N-1), width(N-1),
// height(N-1), area(N-1)]
cv::OutputArray centroids, // Nx2 CV_64F matrix of centroids:
// [ cx0, cy0; ... ; cx(N-1), cy(N-1)]
int connectivity = 8, // 4- or 8-connected components
int ltype = CV_32S // Output label type (CV_32S or CV_16U)
);
其中,新出現的引數
stats:長這樣
分別對應各個輪廓的x,y,width,height和面積。注意0的區域標識的是background
而centroids則對應的是中心點
而label則對應于表示是當前像素是第幾個輪廓
例子:
對于影像
Mat img = cv::imread( "e:/sandbox/rect.png",0);
cv::Mat img_edge, labels, img_color, stats,centroids;
cv::threshold(img, img_edge, 128, 255, cv::THRESH_BINARY);
bitwise_not(img_edge,img_edge);
cv::imshow("Image after threshold", img_edge);
int i, nccomps = cv::connectedComponentsWithStats (
img_edge, labels,
stats, centroids
);
cout << "Total Connected Components Detected: " << nccomps << endl;
vector<cv::Vec3b> colors(nccomps+1);
colors[0] = Vec3b(0,0,0); // background pixels remain black.
for( i = 1; i < nccomps; i++ ) {
colors[i] = Vec3b(rand()%256, rand()%256, rand()%256);
if( stats.at<int>(i, cv::CC_STAT_AREA) < 200 )
colors[i] = Vec3b(0,0,0); // small regions are painted with black too.
}
img_color = Mat::zeros(img.size(), CV_8UC3);
for( int y = 0; y < img_color.rows; y++ )
for( int x = 0; x < img_color.cols; x++ )
{
int label = labels.at<int>(y, x);
CV_Assert(0 <= label && label <= nccomps);
img_color.at<cv::Vec3b>(y, x) = colors[label];
}
cv::imshow("Labeled map", img_color);
cv::waitKey();
注意:
1、對于OpenCV來說,白色代表有資料,黑色代表沒有資料,所以影像輸入之前要轉換成”黑底白圖“
2、看labels 和 stats,其中第1 2 6 個的面積小于200
而labels中
完全對的上號,結果為
uj5u.com熱心網友回復:
大佬 我也遇到這個問題了,找到連通域后我自己寫了個影像遍歷,然后找了邊緣的坐標,現在要求邊緣的周長什么的了,arclength函式又要求坐標是按順時針或者逆時針排序的。請問下你是怎么解決的噢,能分享下嗎?uj5u.com熱心網友回復:
樓主這個問題解決了嗎,我也遇到這個問題不知道該如何處理了。轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/132392.html
標籤:OpenCV
上一篇:軟體測驗偶發BUG如何復現
下一篇:如何抓取RTP資料包
