圓形標定板標定的opencv c++實現
作者:Oto_G
源代碼
源碼見github:CircleCalibrationTarget
實現環境
-
平台:win10
-
VSCode V1.63.2
-
cmake V3.18.4
-
opencv V4.5.2
-
mingw64 V8.1.0
文件說明
-
Calibrating.h
- Calibration類、所有使用的方法的聲明
-
Calibrating.cpp
- Calbrating.h的實現
-
AutoCalibrating.cpp
- 主程序
實現步驟
圖像預處理模塊
目的是獲得可標定的二值圖像
讀取待標定圖像
使用imread函數讀取需要標定的圖像

創建灰度圖像
使用cvtColor函數將彩色圖像轉為灰度圖像COLOR_BGR2GRAY

進行均值模糊
使用blur函數對圖像進行均值濾波處理,目的是減弱原圖像中噪聲對接下來的標定產生的影響
不預先進行均值模糊可能會導致之后找不到標定板輪廓

OTSU自適應閾值二值化
使用OTSU自適應閾值算法獲得獲取二值圖像,原理就是切割原圖像為多個子圖,對每個子圖進行OTSU
這里使用自適應OTSU算法而不是標准二值化或是全局OTSU是考慮到圖像拍攝時可能存在光照等影響,會導致尋找全局性質的閾值進行二值化會效果不佳,如使標定板圖像殘缺等,於是綜合考慮實現難度和效果,選擇使用自適應閾值的OTSU算法進行圖像二值化

開操作和閉操作
對圖像依次進行一次開操作和閉操作,將內部空點填補並連接邊緣斷點處
這一步並不是在整個標定過程中起到決定性作用,但增加對圖像的開閉操作后能夠對圖片中的一些噪點和邊緣殘缺的現象進行抑制和修補,使后面要進行的邊緣提取算法能夠更加高效和准確(因為消除了小的獨立噪點並連接了斷點)

將二值圖像反色,創建Calibration對象
使用bitwise_not函數進行反色處理,並創建未透視變換的Calibration對象
這里的Calibration是自定義的一個類,為了更加方便地管理尋找到的標定板邊緣和內圓點的坐標,不用多次將這些坐標寫入內存,造成內存的浪費

識別頂點模塊
基於上一個模塊得到的二值圖像,在圖像內尋找標定板位置
查找內五邊形頂點
先通過findContours查找輪廓,然后獲得當前圖片能夠正常標定的標定板面積下限,再由面積下限作為閾值來進行多邊形擬合,確定圖像內是否存在大的多邊形
如果存在則查找這些多邊形是否是標定板的內五邊形,這里通過邊長關系進行限制。若存在則對五邊形的各個頂點進行排序和標記,若不存在則返回相應提示並退出程序

確定內四邊形四點
通過計算與五邊形最短邊兩頂點的歐式距離之和的最小值獲得四邊形的四個頂點,並在圖像上畫出四邊形的輪廓

透視變換
對圖像進行透視變換,將四邊形變換為正四邊形,置於左上角,並通過原圖內四邊形四點獲得透視變換后正方形四點
這一步的目的是方便后一步獲得理想的圓心,因為標定板的各長度比值是固定的,所以很容易求出透視變換后的理想圓心得位置

獲取圓心模塊
獲得標定板內圓形的圓心坐標
獲得所有理想圓心
創建透視變換后的Calibration對象,根據透視變換后的內四邊形獲得所有理想中心點,並標記在圖像中
理想圓心和實際的圓心還是存在較大差距的,當然理想圓心仍然有用,以理想圓心為中心圈出一個矩形框,作為每一個需要標定的圓心的感興趣區域

灰度重心法確定圓心
截取矩形區域,與二值圖相與,使用灰度重心法確定實際圓心,標記在圖中
這一步灰度重心法之前我們進行了改良,將一開始得到的二值圖像與我們的灰度圖像進行相與的操作,這樣我們就只保留了圖像圓中的灰度信息,消除了圓外的灰度變化對接下來的灰度重心算法造成的影響
同時這里采用灰度重心法也是因為考慮到標定板圖像拍攝時可能由於光線問題和具體畸變問題導致拍攝后的圖像存在陰影和形狀畸變的影響,使用灰度重心法能夠較好的規避上述兩種情況帶來的影響

反透視變換
對確定的中點進行反透視變換,得到完成圓點標記后的圖像

校准圖像
獲取相機參數,結合標定板數據,校准原始圖像的畸變

實現缺陷
直接使用兩條延長線交點確定第四個點的方法存在誤差,因為圖像存在畸變
使用透視變換后再進行灰度重心法標定圓心存在一定誤差,因為圖像存在畸變
