机器视觉标定(calibration)关键尝试(标定的重要意义度量衡)(A)
learning opencv開篇便談視覺病態(tài)畸變的問題,我們?nèi)祟愂澜绲倪M(jìn)步和度量衡有莫大的關(guān)系,而工業(yè)自動(dòng)化以及人工智能(AI)的度量衡又是什么呢?那就是標(biāo)定,其意義是非凡的,也可以說是偉大的,人工智能對(duì)度量衡要求低的很,而識(shí)別是重頭戲,但是沒有度量衡的工業(yè)自動(dòng)化,那是不可想象的,這就是標(biāo)定,沒有標(biāo)定度量,一切都是扯淡(蛋?),更就談不上準(zhǔn)確度了。可以這樣毫不遜色的說,標(biāo)定是工業(yè)自動(dòng)化技術(shù)應(yīng)用的基礎(chǔ)。你想一想,在年輕的AI面前,自動(dòng)化已經(jīng)走了很久了。但是AI給自動(dòng)化識(shí)別也帶來了強(qiáng)勁的動(dòng)力,自動(dòng)化的識(shí)別逐漸在向AI識(shí)別演變。
? ? ? ? 舉一個(gè)和標(biāo)定相關(guān)的例子,有很多人用過激光打字(標(biāo))在銘牌上,一般人都不會(huì)感到標(biāo)定的存在,原因是,這樣的工作對(duì)精度要求不高,我搞過一段時(shí)間自動(dòng)化控制激光應(yīng)用,正是這樣的經(jīng)歷更加確認(rèn)了我對(duì)標(biāo)定的熱情,研究是這樣的,在偏離激光鏡頭中心一定距離的地方,有一個(gè)九宮格,里邊有九個(gè)圓,你讓激光去填充這九個(gè)圓,你會(huì)發(fā)現(xiàn),越遠(yuǎn)偏差越大,每列都不一樣,當(dāng)你給每列嘗試補(bǔ)償一個(gè)固定偏差,漸漸這個(gè)值穩(wěn)定后,激光填充的圓也就飽滿了,想說明什么呢?當(dāng)你把整個(gè)鏡頭(場(chǎng)鏡頭)下整個(gè)能打標(biāo)填充的區(qū)域的固定偏差都做出來,那么你想要的激光打標(biāo)準(zhǔn)確度全都有了,這是我最初發(fā)現(xiàn)標(biāo)定最笨的方法,但是他解決了激光鏡頭給精度帶來的偏差,我也發(fā)現(xiàn)了標(biāo)定原來是這么一回事。搞激光的,通常使用矯正鏡頭(標(biāo)定)的方法是,平面上放上一張白紙,讓激光去打一個(gè)矩形,剛開始肯定是桶狀的,很像電視機(jī)的桶狀失真,然后你去調(diào)整激光的參數(shù),直至打標(biāo)一個(gè)ok的矩形,那么在矩形區(qū)域內(nèi),你打標(biāo),至少是線性的。(下圖為九宮格測(cè)試激光畸變)
? ? ? ? 用習(xí)慣了機(jī)器視覺的標(biāo)定,你會(huì)很驚詫激光的標(biāo)定,世間變化真神奇,變個(gè)樣,就不認(rèn)識(shí)了,這能叫學(xué)會(huì)了嗎?當(dāng)你要求更高精度的標(biāo)定時(shí),你就會(huì)用機(jī)器視覺的相機(jī)標(biāo)定去要求激光,標(biāo)定到底是什么?實(shí)質(zhì)就是校正失真的鏡頭,相機(jī)的,激光的,那么有沒有比剛才標(biāo)定激光好一些的方法,有,這就是泰勒級(jí)數(shù)(多項(xiàng)式逼近)上場(chǎng)的時(shí)候了。
? ? ? 因?yàn)殓R頭基本都是中心對(duì)稱的,參考learning opencv的標(biāo)定,泰勒級(jí)數(shù)f(r)=a0+a1*r+a2*r*r+...,r以鏡頭中心為圓的半徑,f(0)=0,所以a0=0;因?yàn)閒(-r)=f(r),所以f(r)實(shí)質(zhì)等于a2*r^2+a4*r^4+...,也就是說,泰勒級(jí)數(shù)的偶數(shù)項(xiàng)有意義,,?以上泰勒級(jí)數(shù)描述的鏡頭畸變被定義為徑向畸變(可不可以這樣理解?過圓心(鏡頭中心)的直徑上的畸變),我們的標(biāo)定也只談徑向畸變,起拋磚引玉的作用。所以learning opencv給出這樣的計(jì)算公式:xc=x*(1+k1*r^2+k2*r^2*r^2+...),k1和k2為徑向畸變參數(shù)。而我令z=(1+k1*r^2+k2*r^2*r^2+...),在xc和x已知情況下z=xc/x(z顯然是大于1的,故桶形畸變中xc是亞像素角點(diǎn),即畸變點(diǎn),x為標(biāo)準(zhǔn)點(diǎn),參考點(diǎn)),程序中我只求z,不求k1,k2.
以下是C#代碼,我們這里直接使用hariss亞像素角點(diǎn)提供的結(jié)果,這個(gè)已講過,此處不再重復(fù),另外這里使用黑白棋盤格標(biāo)定片。(棋盤格見下圖)
? ? ? ? ? ? int cx = 1024 / 2; int cy = 768 / 2;//此處舉例為1024*768相機(jī),即80萬像素。
? ? ? ? ? ? double A = 0; double B = 0; double C = 0; double D = 0;
? ? ? ? ? ? List<Point> correct=new List<Point>();
? ? ? ? ? ? correct.Add(new Point(15,11));//以下只示范了左上角16個(gè)亞像素角點(diǎn)來求徑向畸變參數(shù)
? ? ? ? ? ? ?correct.Add(new Point(75,11));//
? ? ? ? ? ? ?correct.Add(new Point(135,11));//
? ? ? ? ? ? ?correct.Add(new Point(195,11));//
? ? ? ? ? ? ?correct.Add(new Point(15,71));//? ? ? ? ?15? 75? 135? 195
? ? ? ? ? ? ?correct.Add(new Point(75,71));//? ? 11? 一? 二? ?三? ? ?四
? ? ? ? ? ? ?correct.Add(new Point(135,71));//? 71? 五? ?六? 七? ? ?八
? ? ? ? ? ? ?correct.Add(new Point(195,71));//130? 九? ?十? ?11? ?12
? ? ? ? ? ? ?correct.Add(new Point(15,130));//189? 十3? 14? 15? ?16
? ? ? ? ? ? ?correct.Add(new Point(75,130));
? ? ? ? ? ? ?correct.Add(new Point(135,130));
? ? ? ? ? ? ?correct.Add(new Point(195,130));
? ? ? ? ? ? ?correct.Add(new Point(15,189));
? ? ? ? ? ? ?correct.Add(new Point(75,189));
? ? ? ? ? ? ?correct.Add(new Point(135,189));
? ? ? ? ? ? ?correct.Add(new Point(195,189));
? ? ? ? ? ? ?for (int m = 0; m < jibianyong1.Count; m++)// jibianyong1.Count=16
? ? ? ? ? ? ?{//correct為x//jibianyong1為亞像素角點(diǎn)為xc
? ? ? ? ? ? ? ? ?A += (jibianyong1[m].X - cx) * (correct[m].X - cx);
? ? ? ? ? ? ? ? ?B += (correct[m].X - cx) * (correct[m].X - cx);
? ? ? ? ? ? ? ? ?C += (jibianyong1[m].Y - cy) * (correct[m].Y - cy);
? ? ? ? ? ? ? ? ?D += (correct[m].Y - cy) * (correct[m].Y - cy);
? ? ? ? ? ? ?}
? ? ? ? ? ? double 徑向參數(shù) = A / B;//xc*x/(x*x)如此處理,不會(huì)出現(xiàn)負(fù)號(hào)
? ? ? ? ? ? double 徑向參數(shù)1 = C/ D;//這里使用了兩次求平均值的方法,改進(jìn)版本用最小二乘法
? ? ? ? ? ? double pingjun = (徑向參數(shù)?+徑向參數(shù)1) / 2;
? ? ? ? ? ? byte[] buffer24 = new byte[1024*768*3];
? ? ? ? ? ? for (int j = 0; j < 768; j++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int i = 0; i < 1024; i = i + 1)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? int xcorrect = 0, ycorrect = 0;
? ? ? ? ? ? ? ? ? ? xcorrect = cx + (int)((i - cx) / pingjun);
? ? ? ? ? ? ? ? ? ? ycorrect = cy + (int)((j - cy) / pingjun);
? ? ? ? ? ? ? ? ? ? //2,再賦值
? ? ? ? ? ? ? ? ? ? buffer24[ycorrect * 1024 * 3 + xcorrect * 3] = rgbValues[j * 1024 * 3 + i * 3];
? ? ? ? ? ? ? ? ? ? buffer24[ycorrect * 1024 * 3 + xcorrect * 3 + 1] = rgbValues[j * 1024 * 3 + i * 3 + 1];
? ? ? ? ? ? ? ? ? ? buffer24[ycorrect * 1024 * 3 + xcorrect * 3 + 2] = rgbValues[j * 1024 * 3 + i * 3 + 2];
? ? ? ? ? ? ? ? }//完成圖像校正
? ? ? ? ? ? }//注釋,如果不說明,所有圖像均以buffer【y*w+x】代替
機(jī)器視覺中,標(biāo)定板一般有兩種,另外一種標(biāo)定板是九宮格上的'十'字交叉全部換成圓(我們給他個(gè)名字吧,就叫象棋標(biāo)定板(以此紀(jì)念青騷年時(shí)對(duì)象棋的熱愛),是否與棋盤格很對(duì)稱?),我們可以使用前面講過的方法來找到圓心,方法一,找斑的方法,方法二,使用找圓工具匹配的方法,有了圓心(相當(dāng)以上亞像素角點(diǎn)),就可以用上面相同的方法求徑向畸變參數(shù),然后來校正圖像。在工業(yè)上,標(biāo)定通常使用自動(dòng)化方式,手動(dòng)也可以(像激光那樣),但是會(huì)太麻煩。
標(biāo)定一般為工程提供三項(xiàng)便利:1,坐標(biāo)系;2,比例尺;3,圖像校正(鏡頭校正)。提個(gè)問題?我們的眼睛看到的世界是真的?還是畸變的?顯然,眼睛中心看到的是真實(shí)的,而,其他就不可靠。
讓你再一次驚詫機(jī)器視覺標(biāo)定與learning opencv計(jì)算機(jī)視覺標(biāo)定(數(shù)學(xué)設(shè)想推理復(fù)雜度)的巨大差別。你可以看到工業(yè)機(jī)器視覺極大的標(biāo)準(zhǔn)化帶來的便利(基本消除病態(tài)視覺)。什么是工業(yè)機(jī)器視覺極大的標(biāo)準(zhǔn)化?有必要解釋一下:只要你做過機(jī)器視覺項(xiàng)目,你會(huì)發(fā)現(xiàn),標(biāo)定幾乎可以忽略,但并不是說沒有標(biāo)定,只是你沒發(fā)覺,他在你所有的硬件選型中已經(jīng)被消化掉了,一般我們選的鏡頭,幾乎工作在無畸變狀態(tài),在這里你就可以看到別人制定工業(yè)機(jī)器視覺標(biāo)準(zhǔn)的用苦良心,不是隨便一個(gè)相機(jī)鏡頭就可以在工業(yè)上用,這里邊的心血以價(jià)格的溢出而體現(xiàn),這也是用苦良心的回報(bào)。這也是機(jī)器視覺大面積應(yīng)用的基礎(chǔ),計(jì)算機(jī)視覺以learning opencv的方式展現(xiàn),看是美好的未來AI世界,卻是舉步維艱,當(dāng)你習(xí)慣了機(jī)器視覺的簡(jiǎn)單,要改變,必須挖掘這種簡(jiǎn)單習(xí)慣(簡(jiǎn)單,只是有人負(fù)重前行,消除了復(fù)雜度,簡(jiǎn)單沒那么簡(jiǎn)單,當(dāng)你負(fù)重前行的時(shí)候)。所有的隱形,并非能掩蓋標(biāo)定度量衡的偉大意義。
待續(xù)(慢慢來!...........)每天一點(diǎn)小改變?
我的郵箱liuganggang_1978@163.com;734523623@qq.com
總結(jié)
以上是生活随笔為你收集整理的机器视觉标定(calibration)关键尝试(标定的重要意义度量衡)(A)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 离散小波变换公式_一维离散小波
- 下一篇: 职场小白做短视频,用好了这些辅助工具,每