本文廢棄,算法更新於:如何判斷輪廓是否為圓(算法更新)
判斷一個輪廓是否為圓?這看似簡單的問題,在opencv中並沒有現成的函數。當我真正想運用的時候,卻發現還是有許多內容在里面的。

比如這幅圖片,由於瓶口是有缺陷的,造成找到的最大外輪廓不閉合。那么該如何判斷這個輪廓是否是圓了。
我認為從兩點來考慮。
一個是圓的定義:
“平面上到定點的距離等於定長的所有點組成的圖形叫做圓.定點稱為圓心,定長稱為半徑.”
那么就來判斷當前輪廓到一個定點的距離是否為定長。這里這個定點就可以采用外接圓圓心。而這里的度量是標准差。
經過試驗發現,對於這些有缺陷的情況,其標准差都是比較大的(一般大於5),而對於沒有缺陷的情況來說,其標准差都比較小(小於1)。
但是這並不能完全地解決問題,比如存在這樣的情況,其輪廓上所有點到定點的標准差也是不大的,但是這個輪廓沒有構成一個閉合曲線,所以也沒有構成圓。

//根據輪廓點和圓心計算方差
float ComputeVariance(std::vector<cv::Point> theContour,Point2f theCenter)
{
int a[65535],n;
float aver,s;
float sum=0,e=0;
n = theContour.size();
for(int i=0;i<n;i++)
{
a[i] = GetDistance(theContour[i],theCenter);
sum+=a[i];
}
aver=sum/n;
for(int i=0;i<n;i++)
e+=(a[i]-aver)*(a[i]-aver);
e/=n-1;
s=sqrt(e);
return e;
}
那么二點就是曲線閉合的定義.
閉曲線:起點與終點重合的曲線。平面(或空間)中的閉曲線即為單位圓周到平面(或空間)中的連續映射的像。
不是很好理解,但是可以這樣簡化,就是對於閉曲線中的任意一點,遍歷閉曲線,都能夠回到這一點。換句話說,就是不存在“端點”。這里可以再轉換為這樣的理解:
“對於閉曲線中的所有點,除了它本身之外,和這個點距離為最小值(比如1)的點都有兩個。”
//判斷輪廓是否閉合。閉合曲線返回為0
intComputeClose(std::vector<cv::Point>MaxContour)
{
//TODO 計算第一個點和最后一個點相對於圓心的角度.最后變成計算這兩點的距離
int itmp =0;
int iret =0;
for(int i=0;i<MaxContour.size();i++)
{
for(int j=0;j<MaxContour.size();j++)
{
if(i!=j)
{
if(GetDistance(MaxContour[i],MaxContour[j])<1)
{
itmp++;
}
}
}
if(itmp ==1)//存在端點
{
iret ++;
}
itmp=0;
}
return iret;
}
小結一下:數學還是很強的,很多時候,借助定義本身,能夠解決問題。