halcon旋转后坐标_基于FPGA的图像旋转设计
該項(xiàng)目是參加2019屆全國(guó)大學(xué)生FPGA大賽的作品,系統(tǒng)主要實(shí)現(xiàn)視頻任意角度旋轉(zhuǎn)。利用國(guó)產(chǎn)的紫光同創(chuàng)公司的FPGA芯片作為開發(fā)平臺(tái),視頻圖像從攝像頭實(shí)時(shí)采集,經(jīng)過算法旋轉(zhuǎn)后,通過hdmi接口顯示。該項(xiàng)目最終晉級(jí)決賽,并獲得紫光同創(chuàng)企業(yè)特別獎(jiǎng)。
一,圖像旋轉(zhuǎn)原理
圖像旋轉(zhuǎn)是指圖像按照某個(gè)位置轉(zhuǎn)動(dòng)一定角度的過程,旋轉(zhuǎn)中圖像仍保持這原始尺寸。圖像旋轉(zhuǎn)后圖像的水平對(duì)稱軸、垂直對(duì)稱軸及中心坐標(biāo)原點(diǎn)都可能會(huì)發(fā)生變換,因此需要對(duì)圖像旋轉(zhuǎn)中的坐標(biāo)進(jìn)行相應(yīng)轉(zhuǎn)換。
如圖,原圖像經(jīng)過順時(shí)針旋轉(zhuǎn)角度為 θ?后,源圖像的坐標(biāo)為?P0 ( Xo, Yo ) 的點(diǎn)移動(dòng)到了 P1(X1, Y1)。
經(jīng)過推導(dǎo),可以得到上述的 P0 和P1 的坐標(biāo)變換關(guān)系式。
二,MATLAB仿真
方案一:【正向預(yù)設(shè)】從原圖映射到目標(biāo)圖像在此方案中,實(shí)現(xiàn)代碼的方式是正向的思路,將原圖中的像素點(diǎn)的坐標(biāo)進(jìn)行坐標(biāo)的旋轉(zhuǎn),然后直接幅值到輸出的圖像中,此方案旨在找到輸入坐標(biāo)與輸出坐標(biāo)之間的代數(shù)對(duì)應(yīng)關(guān)系。
在該方法中,首先將原始坐標(biāo)以及目標(biāo)坐標(biāo)放入了極坐標(biāo)中,并且通過在極坐標(biāo)中的關(guān)系,找到了同時(shí)滿足X0,Y0,X1,Y1四個(gè)參量的方程組,以此來解出對(duì)應(yīng)的坐標(biāo)關(guān)系,并以此為基礎(chǔ)得到了輸入與輸出之間的矩陣運(yùn)算關(guān)系如下:
Matlab代碼實(shí)現(xiàn)如下:
clear?allclc %?讀入圖片im?=?imread('1.jpg');figure;imshow(im);?%?求出旋轉(zhuǎn)矩陣a = 40 / 180 * pi;R?=?[cos(a),?-sin(a);?sin(a),?cos(a)];?%?求出圖片大小?ch為通道數(shù)?h為高度?w為寬度sz?=?size(im);h?=?sz(1);w?=?sz(2);ch?=?sz(3);c?=?[h;?w]?/?2; %?初始化結(jié)果圖像im2 = uint8(zeros(h, w, 3));for?k?=?1:ch????for?i?=?1:h???????for?j?=?1:w??????????p?=?[i;?j];??????????%?round為四舍五入??????????pp?=?round(R*(p-c)+c); if (pp(1) >= 1 && pp(1) <= h && pp(2) >= 1 && pp(2) <= w)??????????????im2(pp(1),?pp(2),?k)?=?im(i,?j,?k);??????????end???????end????endend?%?顯示圖像figure;imshow(im2);但在實(shí)際的測(cè)試中發(fā)現(xiàn),這種方法所旋轉(zhuǎn)得到的圖像有著較為嚴(yán)重的失真現(xiàn)象,具體情況如下圖所示:??
原圖
旋轉(zhuǎn)后的圖像
很明顯可以看到,在旋轉(zhuǎn)之后這兩張圖片出現(xiàn)了較大的差別,首先是原圖像被裁減了,其次是目標(biāo)圖像中有較多的瑕點(diǎn)(雜點(diǎn))。究其原因在于,從原圖旋轉(zhuǎn)后得到的目標(biāo)圖像的像素位置在原圖中找不到。另外就是邊緣被裁剪的問題,由于在這個(gè)方案中約束了顯示區(qū)域,因此在旋轉(zhuǎn)的過程中,部分像素點(diǎn)就會(huì)由于超出邊界而被裁剪。針對(duì)以上的兩個(gè)問題,進(jìn)行了如下改進(jìn)。
方案二:【逆向預(yù)設(shè)】從目標(biāo)圖像映射到原圖
??由于在之前的方案中出現(xiàn)了雜點(diǎn)以及圖像邊緣裁剪的問題,因此在本方案中,我們采用了逆向思維,用目標(biāo)圖像的坐標(biāo)去與原圖的坐標(biāo)進(jìn)行坐標(biāo)匹配,若在原圖像中能找到匹配的圖像,就顯示該點(diǎn)旋轉(zhuǎn)后的點(diǎn)坐標(biāo),若在原圖中找不到該點(diǎn),則不顯示該點(diǎn),通過這樣就解決了雜點(diǎn)的問題。
??其中,pp為旋轉(zhuǎn)在后的坐標(biāo)對(duì)應(yīng)矩陣,在if語句中限定了原圖的區(qū)域,用此區(qū)域則可以到原圖中的坐標(biāo)點(diǎn),以此來排除不在區(qū)域中的坐標(biāo)點(diǎn),這樣就可以解決雜點(diǎn)的問題。
在這種方案下,坐標(biāo)的對(duì)應(yīng)關(guān)系如下:
MATLAB仿真代碼如下:
clear?allclc?%?讀入圖片im = imread('1.jpg');figure;imshow(im);?%?求出旋轉(zhuǎn)矩陣a?=?20?/?180?*?pi;R?=?[cos(a),?sin(a);?-sin(a),?cos(a)]; % 求出圖片大小 ch為通道數(shù) h為高度 w為寬度sz?=?size(im);h?=?sz(1);w = sz(2);ch?=?sz(3);c?=?[w;h]?/2;?%?初始化結(jié)果圖像im2?=?uint8(zeros(h,?w,?3));for?k?=?1:ch????????????????????%遍歷輸出圖像所有位置的像素????for?i?=?1:h???????for?j?=?1:w??????????p?=?[j;?i];???????????%?p?:輸出圖像的像素坐標(biāo)??????????%?round為四舍五入????????? pp = round(R*(p-c)+c);????%pp :對(duì)應(yīng)到輸入圖像的像素坐標(biāo)??????????%逆向進(jìn)行像素的查找??????????????????if?(pp(1)?>=?1?&&?pp(1)?<=?w?&&?pp(2)?>=?1?&&?pp(2)?<=?h)????????????????im2(i,?j,?k)?=?im(pp(2),?pp(1),?k);????????????end???????end????endend?% 顯示圖像figure;imshow(im2);這樣,該旋轉(zhuǎn)后的圖像就有了較好的還原度,達(dá)到了相應(yīng)的題目要求,具體的方案的效果如下圖所示:
????原圖
旋轉(zhuǎn)后的圖像
如圖所示,相對(duì)方案一而言,圖像的效果就好了很多,但圖像邊緣仍然存在邊緣被切割的現(xiàn)象。
方案三:
考慮到未對(duì)旋轉(zhuǎn)后的圖像進(jìn)行顯示區(qū)域的劃分,因此此類旋轉(zhuǎn)只是對(duì)單一像素點(diǎn)的旋轉(zhuǎn),然后在原圖像的顯示區(qū)域上進(jìn)行坐標(biāo)點(diǎn)的重新組合,得到顯示的圖像。在解決的方法的思路上,采用目標(biāo)顯示區(qū)域的重新劃分來解決該問題。
具體思路是,采用原圖像的長(zhǎng)寬作為基準(zhǔn),再用坐標(biāo)轉(zhuǎn)換的關(guān)系,將長(zhǎng)和寬轉(zhuǎn)換到旋轉(zhuǎn)后的坐標(biāo)系中,得到目標(biāo)圖像在旋轉(zhuǎn)后坐標(biāo)系中的顯示區(qū)域,代碼具體如下:
%?讀入圖片im?=?imread('1.jpg');?figure;imshow(im); %?求出旋轉(zhuǎn)矩陣a?=?30?/?180?*?pi;R?=?[cos(a),?-sin(a);?sin(a),?cos(a)];R?=?R';?%?求出旋轉(zhuǎn)矩陣的逆矩陣進(jìn)行逆向查找?%?計(jì)算原圖大小sz?=?size(im);h?=?sz(1);w?=?sz(2);ch?=?sz(3);c1?=?[h;?w]?/?2;?%?計(jì)算顯示完整圖像需要的畫布大小hh?=?floor(w*sin(a)+h*cos(a))+1;ww?=?floor(w*cos(a)+h*sin(a))+1;c2?=?[hh;?ww]?/?2;?%?初始化目標(biāo)畫布im2?=?uint8(ones(hh,?ww,?3)*128);for k = 1:ch????for?i?=?1:hh???????for?j?=?1:ww??????????p?=?[i;?j];??????????pp?=?(R*(p-c2)+c1);??????????mn?=?floor(pp);??????????ab?=?pp?-?mn;??????????a?=?ab(1); b = ab(2);??????????m?=?mn(1);??????????n?=?mn(2);??????????%?線性插值方法 if (pp(1) >= 2 && pp(1) <= h-1 && pp(2) >= 2 && pp(2) <= w-1)?????????????im2(i,?j,?k)?=?(1-a)*(1-b)*im(m,?n,?k)?+?a*(1-b)*im(m+1,?n,?k)...??????????????????????????+?(1-a)*b*im(m,?n,?k)?????+?a*b*im(m,?n,?k);??????????end???????end????endend%?顯示圖像figure;imshow(im2);這樣,就解決了圖像邊緣被裁剪的問題,是整個(gè)圖像得以完整的顯示,實(shí)際的效果如下:
原圖
旋轉(zhuǎn)后的圖像
從圖示的效果可以看出,邊緣區(qū)域被裁剪的問題被解決了,但問題是圖片加陰影的區(qū)域面積比原圖大很多。
綜合以上三種方案,結(jié)合實(shí)際需求,由于我們的顯示是在一塊固定大小的屏幕上進(jìn)行顯示,整個(gè)圖像的顯示范圍有限,采用CORDIC算法進(jìn)行坐標(biāo)變換產(chǎn)生的延時(shí)太大。最終基于處理速度和資源占用的均衡考慮,最終選擇方案二作為我們圖像旋轉(zhuǎn)的設(shè)計(jì)方案。
三,旋轉(zhuǎn)坐標(biāo)計(jì)算
在該設(shè)計(jì)中,要求圖像擁有0到360的任意角度的旋轉(zhuǎn),坐標(biāo)變換需要角度的正弦和余弦值。
利用matlab生成正余弦表,并將其擴(kuò)大256倍,打印到文件中。利用得到的正余弦表數(shù)值,將其寫入verilog代碼中,生成正余弦查找表。通過輸入角度值來索引其正余弦數(shù)值。Matlab生成正余弦列表的代碼如下;
該正弦,余弦通過MATLAB計(jì)算得到,并預(yù)先儲(chǔ)存到FPGA的片上儲(chǔ)存空間中,在進(jìn)行坐標(biāo)變換時(shí),讀取對(duì)應(yīng)角度的正弦,余弦值,進(jìn)行坐標(biāo)變換。由于計(jì)算得到的正弦和余弦值為浮點(diǎn)數(shù),而FPGA擅長(zhǎng)于進(jìn)行整數(shù)運(yùn)算。故要進(jìn)行浮點(diǎn)數(shù)到整數(shù)的轉(zhuǎn)換,具體的實(shí)現(xiàn)方法是,將計(jì)算得到的浮點(diǎn)正弦,余弦值乘上 256 后再取整,計(jì)算得到的結(jié)果于原結(jié)果相比被擴(kuò)大了256倍,而在數(shù)字電路中,除法操作可以用移位來進(jìn)行。結(jié)果右移8位即等效于除于256 。
坐標(biāo)變換的核心代碼如下:
將坐標(biāo)變換計(jì)算模塊封裝為一個(gè)子模塊,輸入輸出圖像的坐標(biāo)和旋轉(zhuǎn)角度后,即可計(jì)算出對(duì)應(yīng)的輸入圖像對(duì)應(yīng)的像素的坐標(biāo)。然后讀取該坐標(biāo)的像素值,寫入到旋轉(zhuǎn)重建的圖像對(duì)應(yīng)的坐標(biāo)位置即可。
四,效果展示(Results show)
0.原圖 (正常顯示)
1,順時(shí)針旋轉(zhuǎn)22度
2,順時(shí)針旋轉(zhuǎn)90度?
3,順時(shí)針旋轉(zhuǎn)270度?
4,順時(shí)針旋轉(zhuǎn)341度?
五,說明
在公眾號(hào)對(duì)話框回復(fù)?FPGA2019?,即可獲得該項(xiàng)目的工程源代碼,詳細(xì)的文檔說明,MATLAB仿真代碼。
總結(jié)
以上是生活随笔為你收集整理的halcon旋转后坐标_基于FPGA的图像旋转设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序流程图_干货收藏 | Java 程序
- 下一篇: r语言t检验输出检验统计量_数据统计的理