首頁 > 軟體

OpenCV透視變換應用之書本檢視矯正+廣告螢幕切換

2022-08-03 18:03:43

一、透視變換的實際應用場景

我們在出門坐車時,經常會看到司機會使用一種行車輔助工具,這其中就使用到了透視變換的相關操作,協助司機安全行車。

可以看出,自身小車周圍路況的正常顯示,便利了司機的行車操作 

像這種透視變換的實際生活應用,其實還有許多,接下來,我們就來學習一下OpenCV的透視變換

二、案例瞭解透視變換--書本檢視矯正

原圖:

目標:需要使用透視變換 將書桌上的課本 正視視角檢視

結果展示:

書本檢視矯正完整程式碼如下:【這裡是滑鼠點選從左上角開始順時針選取4個點透視變換】

#include <iostream>
#include <opencv2/opencv.hpp>
#include<vector>
using namespace cv;
using namespace std;
 
//滑鼠操作 自己準備結構體
struct imagedata
{
    Mat img;//目標影象 用於點選 確定座標
    vector<Point2f> points;//存放原圖的座標 通過滑鼠的點選進行存放
};
 
//滑鼠操作的回撥函數:用於選擇四個角的點(使用方法:從左上角開始順時針選擇四個點,選完之後回車操作)
void mouseHundle(int event,int x,int y,int flag,void *arg)
{
    //強制轉換
    struct imagedata * d = (struct imagedata*)arg;
    //如果按下的是滑鼠左鍵
    if(event==EVENT_LBUTTONDOWN)
    {
        //用圓形來標記下滑鼠按下左鍵標記的位置
        circle(d->img,Point(x,y),3,Scalar(255,0,0),3,CV_AA);//在圖上標記,圓心為點選的位置
        imshow("image",d->img);//原視窗上進行顯示標記點
        //透視變換 需要使用四個點的座標
        if(d->points.size()<4)
        {
            d->points.push_back(Point2f(x,y));//把點選下來的座標進行儲存
        }
    }
}
 
void example_1()
{
    Mat image=imread("D:/00000000000003jieduanshipincailliao/book2.jpg");
    Mat result=Mat::zeros(400,500,CV_8UC1);//最終結果顯示 單通道
 
    //準備座標:存放四個轉換以後的座標
    vector<Point2f>obj;
    //座標一定要相反 映象座標
    obj.push_back(Point2f(0,0));
    obj.push_back(Point2f(500,0));
    obj.push_back(Point2f(500,400));
    obj.push_back(Point2f(0,400));
 
    imshow("image",image);
    struct imagedata data;
    data.img=image;
 
    //滑鼠操作  滑鼠處理的回撥函數
    setMouseCallback("image",mouseHundle,&data);
 
    //按任意鍵關閉當前顯示的視窗,顯示下一個視窗
    waitKey(0);
 
    //利用RANSAC演演算法  計算得到轉換對映矩陣3*3
    Mat res=findHomography(data.points,obj,CV_RANSAC);
    //檢視轉換矩陣
    //imshow("res",res);
 
    //原圖轉換出來結果圖
    warpPerspective(image,result,res,result.size());
    //檢視轉換結果圖 透視變換
    imshow("result",result);
 
    waitKey(0);
}
 
int main(int argc, char *argv[])
{
    example_1();
    return 0;
}

以上是使用滑鼠點選確定座標,當然,我們也可以在程式碼中寫上選定的座標進行透視變換的相關操作。 依然選取左上角開始順時針座標選取,這裡以左上角為例,其他三個點可以類比左上角座標選擇來確定下座標選取

可以看到左上角座標 x=282,y=43

自己定下透視變換使用到的四個座標 直接回車 即可檢視透視變換結果

    //滑鼠操作  滑鼠處理的回撥函數
    //setMouseCallback("image",mouseHundle,&data);
 
    //不使用滑鼠點選,自己定下透視變換的四個座標
    vector<Point2f>src;
    src.push_back(Point2f(283,134));
    src.push_back(Point2f(745,234));
    src.push_back(Point2f(578,463));
    src.push_back(Point2f(61,299));
 
    //按任意鍵關閉當前顯示的視窗,顯示下一個視窗
    waitKey(0);
 
    //利用RANSAC演演算法  計算得到轉換對映矩陣3*3
    Mat res=findHomography(src,obj,CV_RANSAC);
    //檢視轉換矩陣
    //imshow("res",res);

程式執行 直接回車操作 檢視

三、案例瞭解透視變換--廣告螢幕切換

背景圖片: 

想要切換的廣告圖片: 

目標:選擇廣告螢幕 切換 廣告螢幕內容

結果:廣告屏上面的 內容推薦 成功切換成自己想要切換的廣告圖片

實現方法:處理後兩張圖片的疊加,就是先將想要更換的廣告屏填充黑色背景圖,再將自己想要的廣告圖片 兩張圖片疊加就能達到切換廣告螢幕的效果

廣告螢幕切換完整程式碼如下:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
 
struct imagedata
{
    Mat img;//目標影象
    vector <Point2f> points;//3D點
};
 
//滑鼠操作函數:用於選擇四個角的點(使用方法有順序的,從左上角順時針選擇,選完之後回車)
void mouseHundle(int event,int x,int y,int flag,void *ptr)
{
    struct imagedata * d=(struct imagedata*)ptr;
    if(event==EVENT_LBUTTONDOWN)
    {
        //確定按下的是滑鼠左鍵
        //用圓形標記一下滑鼠按下左鍵標記的位置
        circle(d->img,Point(x,y),3,Scalar(255,0,0),3,CV_AA);//在圖上標記,圓心為點選的位置
 
        imshow("dst",d->img);//在dst背景圖中顯示滑鼠選取的圖片
 
        if(d->points.size()<4)//只存下來,最先點的前四個點
        {
            d->points.push_back(Point2f(x,y));//把滑鼠操作點選的點存起來
        }
    }
}
 
void example_2()
{
    Mat image1=imread("D:/00000000000003jieduanshipincailliao/0802.jpg");//想要切換的廣告內容
    Mat image2=imread("D:/00000000000003jieduanshipincailliao/city.jpg");//紐約時代廣場圖片背景
 
    Mat dst=image2.clone();//背景圖片 克隆
 
    //存放原圖座標 想要切換的廣告屏圖片
    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",dst);
    struct imagedata data;
    data.img =dst;
 
    //滑鼠操作 滑鼠處理的回撥函數
    setMouseCallback("dst",mouseHundle,&data);
    //按任意鍵關閉當前顯示的視窗,顯示下一個視窗
    waitKey(0);
 
    //計算得到轉換對映矩陣 3*3  原圖座標轉換為滑鼠選擇
    Mat res = findHomography(obj,data.points,CV_RANSAC);
    //imshow("res",res);
    //透視變換
    warpPerspective(image1,dst,res,dst.size());
    //僅有的卻換後的廣告圖圖片
    //imshow("image1",dst);
 
    Point pts[4];
    for(int i=0;i<4;i++)
    {
        pts[i]=data.points[i];
    }
    //滑鼠點選的四個座標的區域填充成黑色
    fillConvexPoly(image2,pts,4,Scalar(0),CV_AA);
    //imshow("image2",image2);
 
    //將僅有的卻換後的廣告圖圖片 和  滑鼠點選的四個座標的區域填充成黑色的背景圖圖片 疊加
    image2+=dst;
    //顯示出最後廣告換屏結果圖片
    imshow("final",image2);
 
    waitKey(0);
}
 
int main(int argc, char *argv[])
{
    example_2();
    return 0;
}

到此這篇關於OpenCV透視變換應用之書本檢視矯正+廣告螢幕切換的文章就介紹到這了,更多相關OpenCV透視變換應用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com