使用opencv对图像进行透视变换
一.什么是透視變換
透視變換就是透視變換(Perspective Transformation)是指利用透視中心、像點(diǎn)、目標(biāo)點(diǎn)三點(diǎn)共線(xiàn)的條件,按透視旋轉(zhuǎn)定律使承影面(透視面)繞跡線(xiàn)(透視軸)旋轉(zhuǎn)某一角度,破壞原有的投影光線(xiàn)束,仍能保持承影面上投影幾何圖形不變的變換。簡(jiǎn)單的來(lái)說(shuō)就是把一張斜著看的二維圖形變?yōu)楦╊亩S圖像,透視變換再計(jì)算機(jī)視覺(jué)中相當(dāng)常用,因?yàn)橛?jì)算機(jī)采集的圖形并非規(guī)整的圖像,比如再使用自動(dòng)倒車(chē),賽道識(shí)別等方面都需要使用透視變換來(lái)改變計(jì)算機(jī)所采集的的信息,比如:
二.代碼演示:?
目標(biāo)是把這張圖片:
變?yōu)?#xff1a;
?
?首先是打開(kāi)圖片
frame = imread("test3.jpg", 1); frame1 = frame.clone();這里先定義兩張一樣的圖片,一張用于用戶(hù)輸入,一張用于數(shù)據(jù)處理
然后調(diào)整一下圖片的大小,這里我測(cè)試了一下,把圖片都變成正方形可以使變換的更加準(zhǔn)確
Size a = frame.size(); resize(frame, frame, Size(max(a.height,a.width), max(a.height ,a.width))); resize(frame1, frame1, Size(max(a.height, a.width), max(a.height, a.width)));然后使確定矩形的四個(gè)點(diǎn),這里我們讓用戶(hù)自己再圖片上進(jìn)行點(diǎn)擊,我們可以使用openCV自帶的函數(shù)setmousecallback,用法如下:
這里共有三個(gè)參數(shù):
第一個(gè):窗口名稱(chēng)
第二個(gè):鼠標(biāo)的響應(yīng)函數(shù)和回調(diào)函數(shù)
第三個(gè):回調(diào)函數(shù)的參數(shù)
我們?cè)诘诙€(gè)參數(shù)中寫(xiě)一個(gè)返回值void的函數(shù)On_mouse,其中識(shí)別鼠標(biāo)按下的回調(diào)的參數(shù)是:EVENT_LBUTTONDOWN
setMouseCallback("test", On_mouse, 0);然后我們期望用戶(hù)點(diǎn)擊后在用戶(hù)點(diǎn)擊的地方顯示一個(gè)點(diǎn),我們可以使用circle函數(shù),所以O(shè)n_mouse函數(shù)如下:
int num_point = 0, out_size = 0; void On_mouse(int event, int x, int y, int flags, void*) {if (event == EVENT_LBUTTONDOWN) {in_point[num_point] = Point(x, y);cout << x << ' ' << y << endl;circle(frame1, in_point[num_point], 6, Scalar(0, 255, 0), -1);imshow("test", frame1);num_point++;} }然后我們把輸入的四個(gè)點(diǎn)的坐標(biāo)存在in_point這個(gè)數(shù)組里
最后我們使用getPerspectiveTransform和warpPerspective函數(shù)進(jìn)行透視變換:
temp = getPerspectiveTransform(in_point, out_point); warpPerspective(frame, result, temp, frame.size());這里注意我們輸入點(diǎn)的順序是:左上,右上,左下,右下。
完整代碼:
#include<opencv2/opencv.hpp> #include<iostream> using namespace std; using namespace cv; Mat frame,frame1; Point2f in_point[4]; Point2f out_point[4]; int num_point = 0, out_size = 0; void On_mouse(int event, int x, int y, int flags, void*) {if (event == EVENT_LBUTTONDOWN) {in_point[num_point] = Point(x, y);cout << x << ' ' << y << endl;circle(frame1, in_point[num_point], 6, Scalar(0, 255, 0), -1);imshow("test", frame1);num_point++;} } int main(){cout << "請(qǐng)依次點(diǎn)擊需要變換的四邊形的左上角,右上角,左下角,右下角" << endl;cout << "點(diǎn)選取好后單擊Enter" << endl;frame = imread("test3.jpg", 1); //test3.jpg是我自己在這個(gè)目錄下的文件,也可以替換為圖片的絕對(duì)路徑,但是要注意使用雙斜杠frame1 = frame.clone();Size a = frame.size();resize(frame, frame, Size(max(a.height,a.width), max(a.height ,a.width)));resize(frame1, frame1, Size(max(a.height, a.width), max(a.height, a.width)));imshow("test", frame);setMouseCallback("test", On_mouse, 0);while (1) {if (waitKey(10) == 13) {out_size = std::max(in_point[1].x - in_point[0].x, in_point[3].x - in_point[2].x);out_point[0] = Point2f(0.0, 0.0);out_point[1] = Point2f(out_size * 1.0, 0.0);out_point[2] = Point2f(0.0, out_size * 1.0);out_point[3] = Point2f(out_size * 1.0, out_size * 1.0);Mat temp, result;temp = getPerspectiveTransform(in_point, out_point);warpPerspective(frame, result, temp, frame.size());imshow("result", result);cout << "轉(zhuǎn)換完成" << endl;waitKey(0);} }return 0; }?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的使用opencv对图像进行透视变换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: html中marquee标签添加2条,H
- 下一篇: CISAW信息安全保障人员