1. 程式人生 > >OpenCV 最小二乘擬合方法求取直線傾角

OpenCV 最小二乘擬合方法求取直線傾角

工業相機拍攝的影象中,由於攝像質量的限制,影象中的直線經過處理後,會表現出比較嚴重的鋸齒。在這種情況下求取直線的傾角(其實就是直線的斜率),如果是直接選取直線的開始點和結束點來計算,或是用opencv自帶的哈夫曼直線方法,都會引起較大的角度偏差,一般會達到好幾度。誤差這麼大,顯然達不到工控要求。後來嘗試採取直線點集做最小二乘擬合,誤差縮小到0.5以下。以下是演算法的程式碼:

	//最小二乘擬合計算直線的傾角
	int pointCount = pointVect.size();
	if (pointCount > 0)
	{
		int xCount = 0;
		int yCount = 0;
		int xyCount = 0;
		int xxCount = 0;
		for (int i = 0; i< pointCount; i++)
		{
			xCount += pointVect.at(i).x;
			yCount += pointVect.at(i).y;
			xyCount += (pointVect.at(i).x * pointVect.at(i).y);
			xxCount += (pointVect.at(i).x * pointVect.at(i).x);
		}
		double k = (double)(pointCount * xyCount - xCount * yCount) / (double)(pointCount * xxCount - xCount * xCount);
		double sinValue = - k / (sqrt(1 + k * k));
		double radian = asin(sinValue);
	        double pi = 3.1415926535;
	        double angle = radian * 180.0 / pi;
	}

下面是最小二乘的理論基礎:

曲線擬合中最基本和最常用的是直線擬合。設xy之間的函式關係為:

                   ya+bx

式中有兩個待定引數,a代表截距,b代表斜率。對於等精度測量所得到的N組資料xiyi),i12……,Nxi值被認為是準確的,所有的誤差只聯絡著yi下面利用最小二乘法把觀測資料擬合為直線。    

用最小二乘法估計引數時,要求觀測值yi的偏差的加權平方和為最小。對於等精度觀測值的直線擬合來說,可使下式的值最小:

最小二乘法擬合直線

上式分別對a、b求偏導得:
    最小二乘法擬合直線

整理後得到方程組

最小二乘法擬合直線


    解上述方程組便可求得直線引數ab的最佳估計值。

最小二乘法擬合直線

相關係數r:

最小二乘法處理資料除給出ab外,常常還給出相關係數r, r定義為

最小二乘法擬合直線

最小二乘法擬合直線 

算例:我用一篇論文中的已知資料作為算例。最小二乘法擬合直線

計算:

最小二乘法擬合直線

代入上面推匯出來的計算公式可得:

a=13.6284394650024    b=-0.0799231779033084