【OpenCV】透视变换应用——实现鸟瞰图与贴图
生活随笔
收集整理的這篇文章主要介紹了
【OpenCV】透视变换应用——实现鸟瞰图与贴图
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
透視變換是3D轉換,透視變換的本質是將圖像投影到一個新的視平面;
據此,我們可以使用透視變化來實現鳥瞰圖和圖形貼圖的效果;
一、鳥瞰圖
實現前:
?實現效果:
?
1.準備一個空的mat對象 用于保存轉換后的圖
Mat image=imread("road.jpg");imshow("image",image);Mat result=Mat::zeros(500,600,CV_8UC1);//存儲轉換后的圖像坐標 按順時針 左上、右上、右下、左下(可自己定順序)vector<Point2f> obj;obj.push_back(Point2f(0,0));obj.push_back(Point2f(600,0));obj.push_back(Point2f(600,500));obj.push_back(Point2f(0,500));2.在原圖窗口里做鼠標操作,通過setMouseCallback鼠標回調函數,獲取原圖四個坐標
在原圖中點擊四個點獲取四個坐標,順序與上述1中設置的坐標對應,如果1中是順時針,按選擇坐標時也應該按順時針操作,并且按照左上、右上、右下、左下順序;
//2.在原圖窗口里做鼠標操作,通過鼠標回調函數,獲取原圖四個坐標struct imagedata data;data.img=image;//將原圖傳入setMouseCallback("image",mouseHundle,&data);//鼠標回調函數waitKey(0);//鍵盤輸入 向下執行//點擊按鍵之后結束鼠標操作,得到原圖四個坐標和轉換后的坐標 //用到的結構體和鼠標處理函數 struct imagedata {Mat img;vector<Point2f>points;//該points是test1原圖需要做轉換的坐標//在test2中是原圖轉換后的坐標 };void mouseHundle(int event,int x,int y,int flag,void *arg) {struct imagedata* ind=(struct imagedata *)arg;if(event==EVENT_LBUTTONDOWN)//鼠標左鍵按下{//畫圓circle(ind->img,Point(x,y),3,Scalar(0,0,255),3,CV_AA);imshow("image",ind->img);//test1鳥瞰圖顯示原圖帶圓點//imshow("dst",ind->img);//test2貼圖顯示city圖帶圓點if(ind->points.size()<4){ind->points.push_back(Point2f(x,y));//轉換的坐標只需要收集四個}} }3.開始計算坐標映射矩陣
Mat res=findHomography(data.points,obj,CV_RANSAC);4.進行透視轉換
將原圖轉變為效果圖進行顯示
warpPerspective(image,result,res,result.size()); imshow("result",result); waitKey(0);二、貼圖
city圖實現前:?
?貼圖實現后:
左邊大屏幕更改
?貼圖與鳥瞰圖有些不同,鳥瞰圖是將一張原圖,通過選擇四個點轉換成鳥瞰圖;
轉換后的坐標固定的,轉換前的4個坐標由鼠標選擇;
而貼圖的話,是將原圖通過選擇的點進行轉換,再貼到city圖中;
轉換前的坐標固定的,就是普通的圖片,轉換后的坐標由鼠標選擇;
1.準備原圖要貼上去的圖,即1.jpg
Mat image1=imread("1.jpg");//原圖Mat image2=imread("city.jpg");//city圖Mat dst=image2.clone();//克隆一份城市圖//1.準備原圖要貼上去的圖,即1.jpg//Mat result=Mat::zeros(image1.rows,image1.cols,CV_8UC1);//存儲轉換前的圖像坐標vector<Point2f> obj;obj.push_back(Point2f(0,0));obj.push_back(Point2f(image1.cols,0));obj.push_back(Point2f(image1.cols,image1.rows));obj.push_back(Point2f(0,image1.rows));imshow("dst",image2);2.在city窗口里做鼠標操作,通過鼠標回調函數,獲取轉換后的四個坐標
struct imagedata data;data.img=dst;//將city圖傳入setMouseCallback("dst",mouseHundle,&data);//鼠標回調函數waitKey(0);?3.開始計算坐標映射矩陣
//點擊按鍵之后結束鼠標操作,得到原圖四個坐標和轉換后的坐標Mat res=findHomography(obj,data.points,CV_RANSAC);?4.透視轉換
warpPerspective(image1,dst,res,dst.size());imshow("image1",dst);?做到這一步,將原圖變成這樣子
?
5.?獲取四個坐標,將city圖中選擇的位置填充成黑色,防止兩個圖片顏色沖突
最后通過image2+=dst把圖片貼到city圖上,這樣就完成了
Point pts[4];for(int i=0;i<4;i++){pts[i]=data.points[i];}//在city圖中選擇的位置填充成黑色,防止兩圖顏色沖突fillConvexPoly(image2,pts,4,Scalar(0),CV_AA);image2+=dst;//把圖片貼到city圖上imshow("final",image2);waitKey(0);?完整源碼
#include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv;struct imagedata {Mat img;vector<Point2f>points;//該points是test1原圖需要做轉換的坐標//在test2中是原圖轉換后的坐標 };void mouseHundle(int event,int x,int y,int flag,void *arg) {struct imagedata* ind=(struct imagedata *)arg;if(event==EVENT_LBUTTONDOWN)//鼠標左鍵按下{//畫圓circle(ind->img,Point(x,y),3,Scalar(0,0,255),3,CV_AA);//imshow("image",ind->img);//test1顯示原圖帶圓點imshow("dst",ind->img);//test2顯示city圖帶圓點if(ind->points.size()<4){ind->points.push_back(Point2f(x,y));//轉換的坐標只需要收集四個}} }void test1() {Mat image=imread("road.jpg");imshow("image",image);//1.準備空的mat對象 用于保存轉換后的圖Mat result=Mat::zeros(500,600,CV_8UC1);//存儲轉換后的圖像坐標 按順時針 左上、右上、右下、做下(可自己定順序)vector<Point2f> obj;obj.push_back(Point2f(0,0));obj.push_back(Point2f(600,0));obj.push_back(Point2f(600,500));obj.push_back(Point2f(0,500));//2.在原圖窗口里做鼠標操作,通過鼠標回調函數,獲取原圖四個坐標struct imagedata data;data.img=image;//將原圖傳入setMouseCallback("image",mouseHundle,&data);//鼠標回調函數waitKey(0);//點擊按鍵之后結束鼠標操作,得到原圖四個坐標和轉換后的坐標//3.開始計算坐標映射矩陣Mat res=findHomography(data.points,obj,CV_RANSAC);//4.透視轉換warpPerspective(image,result,res,result.size());imshow("result",result);waitKey(0); } void test2() {Mat image1=imread("1.jpg");Mat image2=imread("city.jpg");Mat dst=image2.clone();//克隆一份城市圖//1.準備原圖要貼上去的圖,即1.jpg//Mat result=Mat::zeros(image1.rows,image1.cols,CV_8UC1);//存儲轉換前的圖像坐標vector<Point2f> obj;obj.push_back(Point2f(0,0));obj.push_back(Point2f(image1.cols,0));obj.push_back(Point2f(image1.cols,image1.rows));obj.push_back(Point2f(0,image1.rows));imshow("dst",image2);//2.在city窗口里做鼠標操作,通過鼠標回調函數,獲取需要四個坐標struct imagedata data;data.img=dst;//將city圖傳入setMouseCallback("dst",mouseHundle,&data);//鼠標回調函數waitKey(0);//點擊按鍵之后結束鼠標操作,得到原圖四個坐標和轉換后的坐標//3.開始計算坐標映射矩陣Mat res=findHomography(obj,data.points,CV_RANSAC);//4.透視轉換warpPerspective(image1,dst,res,dst.size());imshow("image1",dst);Point pts[4];for(int i=0;i<4;i++){pts[i]=data.points[i];}//在city圖中選擇的位置填充成黑色,防止兩圖顏色沖突fillConvexPoly(image2,pts,4,Scalar(0),CV_AA);image2+=dst;//把圖片貼到city圖上imshow("final",image2);waitKey(0); }int main() {//test1();test2();return 0; }感謝觀看!!!!
以上就是全部內容,如果對您有幫助,歡迎點贊評論,或者發現有哪里寫錯的,歡迎指正!
?
總結
以上是生活随笔為你收集整理的【OpenCV】透视变换应用——实现鸟瞰图与贴图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 毕业设计 单片机超声波雷达系统 - 嵌入
- 下一篇: 浅谈nginx反向代理问题