0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

OpenCV筑基之圖像的透視變換

OpenCV學(xué)堂 ? 來源:OpenCV學(xué)堂 ? 2024-03-15 09:51 ? 次閱讀

1. 圖像的透視變換

1.1 簡介

圖像的透視變換(Perspective Transformation)是指將圖像投影到一個新的視平面(Viewing Plane),也稱作投影映射(Projective Mapping)。

透視變換是一種非線性變換,它可以將一個二維坐標(biāo)系中的點(diǎn)映射到三維坐標(biāo)系中的點(diǎn),然后再將其投影到另一個二維坐標(biāo)系中的點(diǎn)。透視變換可以改變圖像中的形狀,并可以模擬真實(shí)世界中的透視效果。

仿射變換可以看成是透視變換的特殊情況,下圖是對幾何變換的總結(jié)。

6e3c19b2-e216-11ee-a297-92fbcf53809c.jpg

幾何變換的總結(jié).png

透視變換的應(yīng)用:

圖像矯正透視變換可以用于矯正圖像的透視失真,例如由于拍攝角度或鏡頭畸變導(dǎo)致的圖像傾斜或拉伸。

圖像配準(zhǔn)透視變換可以用于將兩張或多張圖像進(jìn)行配準(zhǔn),使其具有相同的幾何形狀。這在醫(yī)學(xué)圖像處理、衛(wèi)星圖像處理等領(lǐng)域有著重要的應(yīng)用。

3D 建模透視變換可以用于將二維圖像投影到三維空間,從而生成三維模型。

圖像增強(qiáng)透視變換可以用于調(diào)整圖像的視角,使其看起來更具吸引力。

圖像合成透視變換可以用于將不同的圖像合成在一起,創(chuàng)建新的圖像。

特效透視變換可以用于創(chuàng)建各種特效,例如虛擬場景、3D 動畫等。

1.2 原理

透視變換的定義為將圖像中的所有點(diǎn)按照一定的透視關(guān)系映射到新的圖像中。

6e529552-e216-11ee-a297-92fbcf53809c.jpg

透視變換.png

透視關(guān)系可以由一個3x3的透視變換矩陣來表示,透視變換的矩陣如下:

其中,、、、 表示線性變換,、 表示平移變換,、 表示透視變換。

透視變換的過程為:

此時,得到的不是最后的坐標(biāo),還需要進(jìn)一步轉(zhuǎn)換:

最終的坐標(biāo)為:

重新回顧一下整個透視變換的過程:

不難看出看出仿射變換是透視變換的一種特殊情況。

2. 透視變換的應(yīng)用

2.1 商品圖位置矯正

下面的代碼,對圖中的沒有擺正的商品通過透視變換將其對齊,然后在原圖中將商品放正。主要用到了 OpenCV 的 findHomography()、warpPerspective()函數(shù)進(jìn)行透視變換。findHomography()函數(shù)用于計(jì)算兩個平面之間進(jìn)行透視變換的矩陣,warpPerspective() 函數(shù)用于對圖像進(jìn)行透視變換。

#include
#include
#include
#include

usingnamespacestd;
usingnamespacecv;

boolascendSort(vectora,vectorb)
{
returncontourArea(a)>contourArea(b);
}

longpointSideLine(Point&lineP1,Point&lineP2,Point&point){
longx1=lineP1.x;
longy1=lineP1.y;
longx2=lineP2.x;
longy2=lineP2.y;
longx=point.x;
longy=point.y;
return(x-x1)*(y2-y1)-(y-y1)*(x2-x1);
}

vectorsortPointByClockwise(vectorpoints){
if(points.size()!=4){
returnpoints;
}
PointunFoundPoint;
vectorresult={unFoundPoint,unFoundPoint,unFoundPoint,unFoundPoint};
longminDistance=-1;
for(autopoint:points){
longdistance=point.x*point.x+point.y*point.y;
if(minDistance==-1||distance0){
result[1]=points[0];
result[3]=points[1];
}else{
result[1]=points[1];
result[3]=points[0];
}
}

if(result[0]!=unFoundPoint&&result[1]!=unFoundPoint&&result[2]!=unFoundPoint&&result[3]!=unFoundPoint){
returnresult;
}

returnpoints;
}

intmain(intargc,char*argv[])
{
Matsrc=imread(".../product.jpg");
imshow("src",src);

Matgray,binary;
cvtColor(src,gray,COLOR_BGR2GRAY);
threshold(gray,binary,0,255,THRESH_BINARY|THRESH_OTSU);
imshow("binary",binary);

vector>contours;
vectorhierarchy;
findContours(binary,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE);

sort(contours.begin(),contours.end(),ascendSort);//ascendingsort

RotatedRectrrt=minAreaRect(contours[0]);
Rectbbox=rrt.boundingRect();

if(bbox.height>2000){
rrt=minAreaRect(contours[1]);
bbox=rrt.boundingRect();
}

Matroi;
try{
roi=src(bbox);
}
catch(...){
}
imshow("roi",roi);

intwidth=static_cast(rrt.size.width);
intheight=static_cast(rrt.size.height);
floatangle=rrt.angle;

printf("height%d,width:%d,angle:%f
",height,width,angle);

Point2fvertices[4];
rrt.points(vertices);
vectorsrc_pts;

for(inti=0;idst_pts;
dst_pts.push_back(Point(0,0));
dst_pts.push_back(Point(width,0));
dst_pts.push_back(Point(width,height));
dst_pts.push_back(Point(0,height));

MatM=findHomography(src_pts,dst_pts);
Matresult=Mat::zeros(Size(width,height),CV_8UC3);
warpPerspective(src,result,M,result.size());

imshow("result",result);

resize(result,result,roi.size());

result.copyTo(roi);

imshow("final",src);
waitKey(0);
return0;
}
簡單介紹一下 warpPerspective() 函數(shù):

voidwarpPerspective(InputArraysrc,OutputArraydst,

InputArrayM,Sizedsize,
intflags=INTER_LINEAR,
intborderMode=BORDER_CONSTANT,
constScalar&borderValue=Scalar());

第一個參數(shù) src: 輸入圖像。

第二個參數(shù) dst: 輸出圖像,與 src 具有相同的類型和大小。

第三個參數(shù) M: 3x3 的透視變換矩陣。

第四個參數(shù) dsize: 輸出圖像的大小。

上述代碼,還需要注意調(diào)用 findHomography() 函數(shù)時,輸入點(diǎn)的集合和輸出點(diǎn)的集合順序要一致。

2.2 廣告牌內(nèi)容替換

透視變換還有一個比較經(jīng)典的例子,就是替換一張圖像中廣告牌的內(nèi)容,下面的代碼展示了這個例子:

#include
#include
#include
#include

usingnamespacestd;
usingnamespacecv;

boolascendSort(vectora,vectorb)
{
returncontourArea(a)>contourArea(b);
}

longpointSideLine(Point&lineP1,Point&lineP2,Point&point){
longx1=lineP1.x;
longy1=lineP1.y;
longx2=lineP2.x;
longy2=lineP2.y;
longx=point.x;
longy=point.y;
return(x-x1)*(y2-y1)-(y-y1)*(x2-x1);
}

vectorsortPointByClockwise(vectorpoints){
if(points.size()!=4){
returnpoints;
}
PointunFoundPoint;
vectorresult={unFoundPoint,unFoundPoint,unFoundPoint,unFoundPoint};
longminDistance=-1;
for(autopoint:points){
longdistance=point.x*point.x+point.y*point.y;
if(minDistance==-1||distance0){
result[1]=points[0];
result[3]=points[1];
}else{
result[1]=points[1];
result[3]=points[0];
}
}

if(result[0]!=unFoundPoint&&result[1]!=unFoundPoint&&result[2]!=unFoundPoint&&result[3]!=unFoundPoint){
returnresult;
}

returnpoints;
}

intmain(){
Matbillboard=imread(".../billboard.jpg");
imshow("billboard",billboard);

Mathsv;
cvtColor(billboard,hsv,cv::COLOR_BGR2HSV);//BGR轉(zhuǎn)換到HSV色彩空間
imshow("hsv",hsv);

cv::Scalarlower_white(0,0,0);
cv::Scalarupper_white(180,30,255);

Matmask;
inRange(hsv,lower_white,upper_white,mask);//通過inRange函數(shù)實(shí)現(xiàn)二值化
imshow("mask",mask);

MatstructureElement=getStructuringElement(MORPH_RECT,Size(105,105),Point(-1,-1));
morphologyEx(mask,mask,MORPH_OPEN,structureElement,Point(-1,-1),1);

imshow("mask2",mask);

vector>contours;
vectorhierarchy;
findContours(mask,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);
sort(contours.begin(),contours.end(),ascendSort);//ascendingsort

RotatedRectrrt=minAreaRect(contours[0]);//獲取最大輪廓的最小外接矩形
Rectbbox=rrt.boundingRect();
intwidth=static_cast(rrt.size.width);
intheight=static_cast(rrt.size.height);

printf("width%d,height:%d
",width,height);

Point2fpt[4];
rrt.points(pt);

Matroi;
try{
roi=billboard(bbox);
}
catch(...){
}
imshow("roi",roi);

Matgirl=imread(".../girl.jpg");
imshow("girl",girl);

intwidth_girl=girl.cols;
intheight_girl=girl.rows;

vectorsrc_pts;
src_pts.push_back(Point(0,0));
src_pts.push_back(Point(width_girl,0));
src_pts.push_back(Point(width_girl,height_girl));
src_pts.push_back(Point(0,height_girl));

vectordst_pts;
for(inti=0;i
3. 總結(jié)

透視變換是一種重要的圖像處理技術(shù),它具有廣泛的應(yīng)用價值。它可以改變圖像的視角,從而使圖像更加符合人眼的視覺感受,或滿足特定的應(yīng)用需求。它可以用于圖像矯正、圖像配準(zhǔn)、3D 建模、增強(qiáng)現(xiàn)實(shí)等領(lǐng)域。

透視變換是一種非線性變換,因此它可能會導(dǎo)致圖像變形。例如,如果透視變換矩陣不合適,可能會使圖像中的物體看起來拉伸或壓縮。此外,透視變換也可能會導(dǎo)致圖像中的物體出現(xiàn)重疊或遮擋。在使用透視變換時,需要考慮這些局限性,并選擇合適的參數(shù)來獲得最佳效果。

審核編輯:黃飛

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • OpenCV
    +關(guān)注

    關(guān)注

    31

    文章

    635

    瀏覽量

    41350
  • 透視變換
    +關(guān)注

    關(guān)注

    0

    文章

    3

    瀏覽量

    1354

原文標(biāo)題:OpenCV筑基之圖像的透視變換

文章出處:【微信號:CVSCHOOL,微信公眾號:OpenCV學(xué)堂】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    【Rayeager PX2分享】OpenCV入門線段檢測

    )。最基本的霍夫變換是從黑白圖像中檢測直線(線段)。在OpenCV編程中,實(shí)現(xiàn)線段檢測主要使用cvHoughLines2函數(shù)。函數(shù)原型:CvSeq* cvHoughLines2(CvArr* image
    發(fā)表于 05-26 11:22

    【DragonBoard 410c試用體驗(yàn)】 OpenCV圖像角點(diǎn)檢測實(shí)現(xiàn)

    ( WINDOW_NAME2, scaledImage );}這里代碼稍微有點(diǎn)多,不過我們主要看cornerHarris 函數(shù),它這才是用于在OpenCV中運(yùn)行Harris角點(diǎn)檢測算子處理圖像函數(shù)
    發(fā)表于 09-13 19:46

    OpenCV圖像

    之前學(xué)過一段時間OpenCV,跟著網(wǎng)上的資料,自己瞎搞了個上位機(jī),可以對攝像頭采集的圖像簡單處理,在此獻(xiàn)丑了,hhhhhh
    發(fā)表于 07-11 19:07

    圖像頻率域分析傅里葉變換

    文章目錄傅里葉變換基礎(chǔ)傅里葉級數(shù)傅里葉積分傅里葉變換一維連續(xù)傅里葉變換一維離散傅里葉變換二維離散傅里葉變換
    發(fā)表于 05-22 07:41

    【EASY EAI Nano開源套件試用體驗(yàn)】3. OpenCV 圖像處理開發(fā)測試

    :素描效果:邊緣掃描效果:浮雕效果:立體效果:圖像白平衡效果: 六、OpenCV 紅外偽彩變換 有了上面開發(fā)測試的基礎(chǔ),可以進(jìn)一步,利用openc
    發(fā)表于 03-08 00:03

    基于透視變換的車輛位置和方向提取方法

    利用快速標(biāo)定模型進(jìn)行了車載成像裝置的標(biāo)定,研究了基于導(dǎo)引標(biāo)志的車輛位置和方向參數(shù)提取,其中改進(jìn)了一種基于透視變換提取車輛位置方向的方法,即利用圖像中車道平行線和滅影點(diǎn)
    發(fā)表于 02-08 15:46 ?31次下載
    基于<b class='flag-5'>透視</b><b class='flag-5'>變換</b>的車輛位置和方向提取方法

    最全OpenCV教程及圖像處理、目標(biāo)跟蹤、識別案例

    本專題主要幫助讀者快速入門 OpenCV,而無需到處搜尋參考資料,為你免除大量自行搜索的時間,本專題主要給大家介紹OpenCV基礎(chǔ)知識及應(yīng)用領(lǐng)域設(shè)計(jì),包含OpenCV教程、OpenCV
    發(fā)表于 07-06 14:11
    最全<b class='flag-5'>OpenCV</b>教程及<b class='flag-5'>圖像</b>處理、目標(biāo)跟蹤、識別案例

    使用opencv進(jìn)行圖像處理

    使用opencv進(jìn)行圖像處理_于仕琪,感興趣的可以看看。
    發(fā)表于 05-03 14:45 ?0次下載

    基于圖像透視畸變校正的調(diào)炮速度測量系統(tǒng)

    基于圖像透視畸變校正的調(diào)炮速度測量系統(tǒng)基于圖像透視畸變校正的調(diào)炮速度測量系統(tǒng)
    發(fā)表于 05-20 15:37 ?0次下載

    opencv透視變換原理及實(shí)例

    透視變換(Perspective Transformation)是將圖片投影到一個新的視平面(Viewing Plane),也稱作投影映射(Projective Mapping)。
    發(fā)表于 12-04 15:15 ?1.9w次閱讀
    <b class='flag-5'>opencv</b><b class='flag-5'>透視</b><b class='flag-5'>變換</b>原理及實(shí)例

    OpenCV圖像修復(fù)

    OpenCV圖像修復(fù)技術(shù)原理就是利用那些已經(jīng)被破壞的區(qū)域的邊緣, 即邊緣的顏色和結(jié)構(gòu),根據(jù)這些圖像留下的信息去推斷被破壞的信息區(qū)的信息內(nèi)容,然后對破壞區(qū)進(jìn)行填補(bǔ) ,以達(dá)到圖像修補(bǔ)的目的
    發(fā)表于 01-17 09:22 ?3121次閱讀

    淺析OpenCV中的透視變換

    透視變換是將圖像從一個視平面投影到另外一個視平面的過程,所以透視變換也被稱為投影映射(Projection Mapping)。
    的頭像 發(fā)表于 05-18 16:18 ?1727次閱讀
    淺析<b class='flag-5'>OpenCV</b>中的<b class='flag-5'>透視</b><b class='flag-5'>變換</b>

    OpenCV庫在圖像處理和深度學(xué)習(xí)中的應(yīng)用

    本文深入淺出地探討了OpenCV庫在圖像處理和深度學(xué)習(xí)中的應(yīng)用。從基本概念和操作,到復(fù)雜的圖像變換和深度學(xué)習(xí)模型的使用,文章以詳盡的代碼和解釋,帶領(lǐng)大家步入
    的頭像 發(fā)表于 08-18 11:33 ?891次閱讀

    淺談透視變換的硬件實(shí)現(xiàn)策略

    需要著重說明地是,(u,v)是透視變換圖像的坐標(biāo),(x,y)是源圖像坐標(biāo)。我們進(jìn)行實(shí)際的透視變換
    的頭像 發(fā)表于 03-05 10:19 ?464次閱讀
    淺談<b class='flag-5'>透視</b><b class='flag-5'>變換</b>的硬件實(shí)現(xiàn)策略

    OpenCV圖像的仿射變換方法總結(jié)

    圖像的幾何變換是指將一幅圖像中的坐標(biāo)位置映射到另一幅圖像中的新坐標(biāo)位置,其實(shí)質(zhì)是改變像素的空間位置,估算新空間位置上的像素值。
    的頭像 發(fā)表于 03-19 11:11 ?1588次閱讀
    <b class='flag-5'>OpenCV</b><b class='flag-5'>筑</b><b class='flag-5'>基</b><b class='flag-5'>之</b><b class='flag-5'>圖像</b>的仿射<b class='flag-5'>變換</b>方法總結(jié)