contour在opencv中是一個基礎的資料結構,靈活運用的話,作用很大。以contour為關鍵字,在answerOpenCV中能夠發現很多有趣的東西。

The problem is that. I just want to take the external contours of the main leaf in the image. Or If it is possible, The image can be cleaned. The second important point is that the process should be standard for all images.
解析:這個提問者希望從上面的葉子圖檔,得到葉子的輪廓。但實際上這是不可能完成的任務,這個圖檔品質達不到要求,關于這一點,是圖像處理的常識。
也就是根本無法輪廓分析,因為沒有穩定的輪廓。
2、如何從圖像中獲得完整輪廓
How to find dimensions of an object in the image
http://answers.opencv.org/question/195807/how-to-find-dimensions-of-an-object-in-the-image/?answer=196027#post-id-196027這道題厲害了,一看這個需求就是專業的:
I want to find the length of an object in the image (image length not the real physical length). My first idea is was to use
boundingRect
to find the dimensions, but some of the masks I have split in between them so the
boundingRect
method fails. Can someone suggest me a robust method to find the length of the object in the given mask
他需要從這個圖中活動輪廓的長度(這個應該是一個腳印),但是因為圖上輪廓可能有多個,是以不知道怎麼辦。
解析:這道題的關鍵,就在于實際上,每張圖的輪廓隻有一個。這是重要的先驗條件。那怎麼辦?把識别出來的輪廓連起來呀。
連的方法有多種,我給出兩種比較保險:
1、形态學變化
dilate(bw,bw,Mat(11,11,CV_8UC1));
erode(bw,bw,Mat(11,11,CV_8UC1));
2、實在距離太遠,靠不上了,直接把中線連起來吧
由于這道題目前還沒有比較好的解決方法,是以我實作了一個,應該是可以用的,這是結果:
網站代碼也已經送出到網站上了
//程式主要部分
int main( int argc, char** argv )
{
//讀入圖像,轉換為灰階
Mat img = imread("e:/sandbox/1234.png");
Mat bw;
bool dRet;
cvtColor(img, bw, COLOR_BGR2GRAY);
//門檻值處理
threshold(bw, bw, 150, 255, CV_THRESH_BINARY);
bitwise_not(bw,bw);
//形态學變化
dilate(bw,bw,Mat(11,11,CV_8UC1));
//尋找輪廓
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(bw, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
/// 計算矩
vector<Moments> mu(contours.size() );
for( int i = 0; i < contours.size(); i++ )
mu[i] = moments( contours[i], false );
/// 計算中心矩:
vector<Point2f> mc( contours.size() );
mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 );
//connect all contours into ONE
for (int i = 0; i < contours.size(); ++i)
{
Scalar color = Scalar( rng12345.uniform(0, 255), rng12345.uniform(0,255), rng12345.uniform(0,255) );
drawContours( img, contours, i, color, 2, 8, hierarchy, 0, Point() );
circle( img, mc[i], 4, color, -1, 8, 0 );
//connect
if (i+1 <contours.size())
line(bw,mc[i],mc[i+1],Scalar(255,255,255));
}
contours.clear();
hierarchy.clear();
//尋找結果
for (int i = 0;i<contours.size();i++)
RotatedRect minRect = minAreaRect( Mat(contours[i]) );
Point2f rect_points[4];
minRect.points( rect_points );
for( int j = 0; j < 4; j++ )
line( img, rect_points[j], rect_points[(j+1)%4],Scalar(255,255,0),2);
float fshort = std::min(minRect.size.width,minRect.size.height); //short
float flong = std::max(minRect.size.width,minRect.size.height); //long
imshow("img",img);
waitKey();
return 0;
}
3、新函數
Orientation of two contours
http://answers.opencv.org/question/113492/orientation-of-two-contours/這個topic希望能夠獲得兩個輪廓之間的角度。并且後期通過旋轉将兩者重合。
I try to calculate the orientation of 2 contours. At the end i want to rotate one contour, so it is in cover with the other one. With my code I get a result, but it isn't that accurate. Also I get the same orientations although the contours is rotated around 90 degrees.
解析:如果是我,一定會直接使用pca分别求出兩個輪廓的角度,然後算差。但是原文中使用了,并且提出了獨特的解決方法。
Shape Distance and Common Interfaces
https://docs.opencv.org/3.0-beta/modules/shape/doc/shape_distances.html#shapecontextdistanceextractor
Shape Distance algorithms in OpenCV are derivated from a common interface that allows you toswitch between them in a practical way for solving the same problem with different methods.Thus, all objects that implement shape distance measures inherit the
ShapeDistanceExtractorinterface.
當然,有了這個函數,做輪廓比對也是非常友善:
http://answers.opencv.org/question/28489/how-to-compare-two-contours-translated-from-one-another/
4、發現opencv的不足
I need a maxEnclosingCircle function
http://answers.opencv.org/question/958/i-need-a-maxenclosingcircle-function/?answer=196029#post-id-196029opencv目前是沒有最大内接圓函數的(當然它還沒有很多函數),但是這個隻有研究要一定程度的人才會發現。這裡他提問了,我幫助解決下:
#
include"stdafx.h"
<iostream>
using namespacestd;
cv;
VP FindBigestContour(Mat src){
intimax = 0; //代表最大輪廓的序号
imaxcontour = -1; //代表最大輪廓的大小
std::vector<std::vector<cv::Point>>contours;
findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
for(
i=0;i<contours.size();i++){
itmp = contourArea(contours[i]);//這裡采用的是輪廓大小
if(imaxcontour < itmp ){
imax = i;
imaxcontour = itmp;
}
returncontours[imax];
main(
argc,
char* argv[])
Mat src = imread("e:/template/cloud.png");
Mat temp;
cvtColor(src,temp,COLOR_BGR2GRAY);
threshold(temp,temp,100,255,THRESH_OTSU);
imshow("src",temp);
//尋找最大輪廓
VP VPResult = FindBigestContour(temp);
//尋找最大内切圓
dist = 0;
maxdist = 0;
Point center;
(
i=0;i<src.cols;i++)
j=0;j<src.rows;j++)
{
dist = pointPolygonTest(VPResult,cv::Point(i,j),
true);
(dist>maxdist)
{
maxdist=dist;
center=cv::Point(i,j);
}
//繪制結果
circle(src,center,maxdist,Scalar(0,0,255));
imshow("dst",src);
另過程中,發現了pyimagesearch上的一些不錯文章,感謝這個blog的作者的長期、高品質的付出,向他學習。
1、Removing contours from an image using Python and OpenCV
https://www.pyimagesearch.com/2015/02/09/removing-contours-image-using-python-opencv/2、Sorting Contours using Python and OpenCV
https://www.pyimagesearch.com/2015/04/20/sorting-contours-using-python-and-opencv/3、Finding extreme points in contours with OpenCV
https://www.pyimagesearch.com/2016/04/11/finding-extreme-points-in-contours-with-opencv/
結語:
實際上,最近我正在做關于輪廓的事情,這也是今天我做這個研究的直接原因。
我的問題是:如何識别出輪廓準确的長和寬
比如這張,其中2的這個外輪廓明顯是識别錯誤的,這樣它的長寬也是錯誤的(注意裡面我标紅的1和2)
代碼:
//read the image
Mat img = imread("e:/sandbox/leaf.jpg");
//resize
pyrDown(img,img);
//morphology operation
//bitwise_not(bw,bw);
//find and draw contours
我們要得到這樣的結果
當然,這個代碼我已經差不多寫出來了,如何獲得輪廓的真實的長寬?這個問題很實際,opencv沒有實作,目前看來answeropencv也人問?
就是這張圖檔?想看看大家的想法。也可以直接在answeropencv上進行讨論。
answerOpencv的讨論位址為:
http://answers.opencv.org/question/196032/how-to-find-the-real-width-and-height-of-contours/感謝閱讀至此,希望有所幫助。
來自為知筆記(Wiz)目前方向:圖像拼接融合、圖像識别
聯系方式:[email protected]