基於C#和Opencv的機器視覺9點標定

很多初學者,都對標定概念模糊不清,分不清座標系之間的關係,搞不清相機標定和機械手相機標定有什麼關係,想當初自己也是一個人摸索了很久,本文將盡量給大家解釋。

我們通常所說的相機標定分為兩種,一種是相機參數的標定,這一般用到標定的作用是校正相機自身的畸變,利用校正得到的參數對圖形進行處理後再呈現出來。關於這方面的資料,網上大把,我也不再此說明。一般的機械手定位也不會進行這個標定,因為現在的相機畸變還是很小的,精度可以滿足大多數要求。

本文要介紹的是第二種,相機和機械手之間的標定,作用:建立相機座標系和機械手座標系之間的關係,即給機械手裝上眼睛,讓它去哪就去哪。

常用的方法是9點標定,所用到函數是EstimateRigidTransform,網上關於 estimateRigidTransform 的詳細說明很少,Emgucv的幾乎沒有。當時找了N久,一度以為opencv沒有座標系轉換的算法,差點就投奔halcon去了,不得不說,opencv在機器視覺方面的應用是完全不如halcon的。EstimateRigidTransform有兩個方法。

方法一:Mat EstimateRigidTransform(PointF[] sourcePoints, PointF[] destinationPoints, bool fullAffine);返回的是一個2*3的double的矩陣 。

第一個參數sourcePoints:換之前圖像上的點(相機座標系下的點)

第二個參數destinationPoints:換之後圖像上的點(機械手座標系下的點)

第三個參數fullAffine: TRUE(全仿射變換,包括:rotation, translation, scaling,shearing

,reflection)

FALSE(帶有約束的仿射變換)

方法二:Mat EstimateRigidTransform(IInputArray src, IInputArray dst, bool fullAffine); //返回的是圖像

第一個參數src:變換之前的圖像

第二個參數dst:變換之前的圖像

第三個參數fullAffine: TRUE(全仿射變換,包括:rotation, translation, scaling,shearing,reflection)

FALSE(帶有約束的仿射變換)

因為我們需要的是座標點,所以選用第一個函數。採用9點標定是因為點數越多越精確,但也不是越多越好,因為點數越多標定也會越麻煩,所選取的9個點在相機中間不要太靠近邊緣,能夠照顧到要定位的點即可。最少需要機械手和相機系下各2組點。

0.準備工作:相機位置,機械手位置全部固定好,標定針固定在機械手上,固定好後不能夠再移動。標定針的位置一定要與夾手或吸盤之內的工具同一位置高度。

1.製作標定板,條件不行的,用普通的紙繪製9個圓,打印出來就行。

2.將標定板放到相機下方,位置區域要與機械手工作的區域一樣,包括高度必須儘量一致,這是標定準確度的關鍵。

3.調整好相機焦距,拍照,然後識別9個點的座標,關於如何找圓,opecv的霍夫變換找圓非常容易誤判,比較好的方法是採用輪廓找圓法。這個我也想寫篇博客講一講。

4.將機械手依次移動到9的圓的中心,記下機械手座標

基於C#和Opencv的機器視覺9點標定

5.將機械手座標destinationPoints與相機座標sourcePoints代入方法EstimateRigidTransform,即可算出一個2*3的矩陣。

private void CalRobot()

{

Mat warpMat;

warpMat = CvInvoke.EstimateRigidTransform(points_camera, points_robot, true);

Image img = warpMat.ToImage();

A = img.Data[0, 0, 0];

B = img.Data[0, 1, 0];

C = img.Data[0, 2, 0];

D = img.Data[1, 0, 0];

E = img.Data[1, 1, 0];

F = img.Data[1, 2, 0];

}

#視覺6.根據所得到的標定參數,可將圖像下的所有座標轉換為機器人的座標,機器人即可移動到圖像上指定的位置。

座標轉換方法:

private void CalRobot()

{

Mat warpMat;

warpMat = CvInvoke.EstimateRigidTransform(points_camera, points_robot, true);

Image img = warpMat.ToImage();

A = img.Data[0, 0, 0];

B = img.Data[0, 1, 0];

C = img.Data[0, 2, 0];

D = img.Data[1, 0, 0];

E = img.Data[1, 1, 0];

F = img.Data[1, 2, 0];

}

至此,標定結束,可以隨意玩耍機械手,對著物體拍張照,定位要夾取的點,然後根據以上標定得到的參數將換算為機械手座標系下的座標,然後將座標通過通信協議傳送給機械手,就大功告成了!

#c# #機器人# #OpenCV#


分享到:


相關文章: