1. 程式人生 > >仿射變換和透射變換

仿射變換和透射變換

仿射變換

定義:仿射變換的功能是從二維座標到二維座標之間的線性變換,且保持二維圖形的“平直性”和“平行性”。仿射變換可以通過一系列的原子變換的複合來實現,包括平移,縮放,翻轉,旋轉和剪下。

這類變換可以用一個3*3的矩陣M來表示,其最後一行為(0,0,1)。該變換矩陣將原座標為(x,y)變換為新座標(x',y'),

void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue

=Scalar())

Parameters:

  • src – input image.
  • dst – output image that has the size dsize and the same type as src .
  • M –  transformation matrix,最重要的東東了,本文中著重講M的構造
  • dsize – size of the output image.ansformation (  ).
  • borderMode – pixel extrapolation method (see borderInterpolate()); when borderMode=BORDER_TRANSPARENT
     , it means that the pixels in the destination image corresponding to the “outliers” in the source image are not modified by the function.
  • borderValue – value used in case of a constant border; by default, it is 0.

 下面介紹一些典型的仿射變換:

(1)平移,將每一點移到到(x+t , y+t),變換矩陣為

(2)縮放變換  將每一點的橫座標放大或縮小sx倍,縱座標放大(縮小)到sy

倍,變換矩陣為

(3)旋轉變換原點:目標圖形圍繞原點順時針旋轉Θ 弧度,變換矩陣為

(4) 旋轉變換  :目標圖形以(x , y )為軸心順時針旋轉θ弧度,變換矩陣為

相當於兩次平移與一次原點旋轉變換的複合,即先將軸心(x,y)移到到原點,然後做旋轉變換,最後將圖片的左上角置為圖片的原點,即

有的人可能會說為什麼這麼複雜呢,那是因為在opencv的影象處理中,所有對影象的處理都是從原點進行的,而影象的原點預設為影象的左上角,而我們對影象作旋轉處理時一般以影象的中點為軸心,因此就需要做如下處理

 如果你覺得這樣很麻煩,可以使用opencv中自帶的Mat getRotationMatrix2D(Point2f center, double angle, double scale)函式獲得變換矩陣M,

  center:旋轉中心

  angle:旋轉弧度,一定要將角度轉換成弧度

  scale:縮放尺度

它得到的矩陣是:

 其中α = scale * cos( angle ) , β = scale  * sing( angle )  , ( center.x , center.y ) 表示旋轉軸心

但是不得不說opencv的文件以及相關書籍中都把這個矩陣寫錯了,如下:

建議大家自己通過下式驗證一下,即首先將軸心(x,y)移到原點,然後做旋轉平綻放變換,最後再將影象的左上角轉換為原點

沒有去研究該函式的原始碼,不曉得原始碼中到底怎麼寫的,但是在別人的部落格中看到這個函式貌似需要修正

opencv中還有一個函式:Mat getAffineTransform(InputArray src, InputArray dst)

 它通過三組點對就可以獲得它們之間的仿射變換,如果我們在一組影象變換中知道變換後的三組點,那麼我們就可以利用該函式求得變換矩陣,然後對整張圖片進行仿射變換

還有一種與仿射變換經常混淆的變換為透視變換,透視變換需要四組點對才能確定變換矩陣,由於仿射變換保持“平直性”與“平行性”,因此只需要三組點對,而透視變換沒有這種約束,故需要四組點對


warpPerspective函式

主要作用:對影象進行透視變換,就是變形

函式的呼叫形式:

C++:void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())

引數詳解:

InputArray src:輸入的影象

OutputArray dst:輸出的影象

InputArray M:透視變換的矩陣

Size dsize:輸出影象的大小

int flags=INTER_LINEAR:輸出影象的插值方法,

combination of interpolation methods (INTER_LINEAR or INTER_NEAREST) and the optional flagWARP_INVERSE_MAP, that sets M as the inverse transformation ( \texttt{dst}\rightarrow\texttt{src} )

int borderMode=BORDER_CONSTANT:影象邊界的處理方式

const Scalar& borderValue=Scalar():邊界的顏色設定,一般預設是0

函式原理:

透視變換(Perspective Transformation)是將圖片投影到一個新的視平面(Viewing Plane),也稱作投影對映(Projective Mapping)。通用的變換公式為:


u,v是原始圖片左邊,對應得到變換後的圖片座標x,y,其中
變換矩陣可以拆成4部分,表示線性變換,比如scaling,shearing和ratotion。用於平移,產生透視變換。所以可以理解成仿射等是透視變換的特殊形式。經過透視變換之後的圖片通常不是平行四邊形(除非對映視平面和原來平面平行的情況)。

重寫之前的變換公式可以得到:


所以,已知變換對應的幾個點就可以求取變換公式。反之,特定的變換公式也能新的變換後的圖片。簡單的看一個正方形到四邊形的變換:
變換的4組對應點可以表示成:

根據變換公式得到:


定義幾個輔助變數:


都為0時變換平面與原來是平行的,可以得到:


不為0時,得到:


求解出的變換矩陣就可以將一個正方形變換到四邊形。反之,四邊形變換到正方形也是一樣的。於是,我們通過兩次變換:四邊形變換到正方形+正方形變換到四邊形就可以將任意一個四邊形變換到另一個四邊形。

 opencv程式碼:

  1. #include<cv.h>
  2. #include<highgui.h>
  3. #pragma comment(lib, "cv.lib")
  4. #pragma comment(lib, "cxcore.lib")
  5. #pragma comment(lib, "highgui.lib")
  6. int main()  
  7. {  
  8.     CvPoint2D32f srcTri[4], dstTri[4];  
  9.     CvMat*       warp_mat = cvCreateMat (3, 3, CV_32FC1);  
  10.     IplImage*    src = NULL;  
  11.     IplImage*    dst = NULL;  
  12.     src = cvLoadImage ("test.png", 1);  
  13.     dst = cvCloneImage (src);  
  14.     dst->origin = src->origin;  
  15.     cvZero (dst);  
  16.     srcTri[0].x = 0;  
  17.     srcTri[0].y = 0;  
  18.     srcTri[1].x = src->width - 1;  
  19.     srcTri[1].y = 0;  
  20.     srcTri[2].x = 0;  
  21.     srcTri[2].y = src->height - 1;  
  22.     srcTri[3].x = src->width - 1;  
  23.     srcTri[3].y = src->height - 1;  
  24.     dstTri[0].x = src->width * 0.05;  
  25.     dstTri[0].y = src->height * 0.33;  
  26.     dstTri[1].x = src->width * 0.9;  
  27.     dstTri[1].y = src->height * 0.25;  
  28.     dstTri[2].x = src->width * 0.2;  
  29.     dstTri[2].y = src->height * 0.7;  
  30.     dstTri[3].x = src->width * 0.8;  
  31.     dstTri[3].y = src->height * 0.9;  
  32.     cvGetPerspectiveTransform (srcTri, dstTri, warp_mat);  
  33.     cvWarpPerspective (src, dst, warp_mat);  
  34.     cvNamedWindow("src", 1);  
  35.     cvShowImage("src", src);  
  36.     cvNamedWindow ("Affine_Transform", 1);  
  37.     cvShowImage ("Affine_Transform", dst);  
  38.     cvWaitKey (0);  
  39.     cvReleaseImage (&src);  
  40.     cvReleaseImage (&dst);  
  41.     cvReleaseMat (&warp_mat);  
  42.     return 0;  
  43. }  

1.仿射變換

仿射變換代表是兩幅影象之間的對映關係,可以表達為乘以一個矩陣再加上一個向量的形式;通常使用2×3的矩陣來表示仿射變換。


仿射變換可表達為Y=A×X+B的形式,在效果上等價於將向量X拓展成X,並且只是將X左乘T,即:


   仿射變換可以表達成以下形式。一個平面內的任意平行四邊形ABCD可以被仿射變換對映為另一個平行四邊形ABCD。如果這些平行四邊形的面積不等於0,這個隱含的仿射變換就被兩個平行四邊形唯一定義。可以把仿射變換想象成把一幅影象畫到一個膠板上,在膠板的角上任意推拉改變形狀得到不同型別的平行四邊形。

2.透視變換

仿射變換可以將影象轉換為平行四邊形,透視變換提供了更大的靈活性,一個透視變換可以將矩形轉變為梯形,平行四邊形也是梯形,所以仿射變換是透視變換的子集。設透視變換矩陣:


則,透視變換的原影象與目標影象的對映關係為:

 \texttt{dst} (x,y) =  \texttt{src} \left ( \frac{M_{11} x + M_{12} y + M_{13}}{M_{31} x + M_{32} y + M_{33}} ,     \frac{M_{21} x + M_{22} y + M_{23}}{M_{31} x + M_{32} y + M_{33}} \right )

  1. #include "opencv2/highgui/highgui.hpp"
  2. #include "opencv2/imgproc/imgproc.hpp"
  3. #include <iostream>
  4. usingnamespace cv;  
  5. usingnamespace std;  
  6. #define WINDOW_NAME1 "Original Image"                    
  7. #define WINDOW_NAME2 "Affine transformation"             
  8. #define WINDOW_NAME3 "Perspective transformation"     
  9. int main(  )  
  10. {  
  11.     bool  Affine=true;     
  12.     bool  Perspective=true;  
  13.     Mat srcImage, dstImage_Aff, dstImage_Per;  
  14.     //載入源影象並作一些初始化
  15.     srcImage = imread( "lena.png", 1 );  
  16.     if(!srcImage.data ) { printf("讀取圖片錯誤\n"); returnfalse; }   
  17.     dstImage_Aff = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());  
  18.     dstImage_Per = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());  
  19.     if(Affine){  
  20.         //仿射變換三個點的對映關係
  21.         Point2f srcTriangle[3];  
  22.         Point2f dstTriangle[3];  
  23. 相關推薦

    Opencv中的仿變換透射變換

    OpenCV提供了一些關於透視變換的介面,例如getPerpectiveTransform, warpPerspective等。這裡主要說明一下warpPerspective是如何工作的。  其實OpenCV中很多影象變換的對映關係都是反直覺的,如這裡的warpPerspe

    OpenCV練習:仿變換透射變換

    #coding=utf-8</code> import cv2 import numpy as np from matplotlib import pyplot as plt img=cv2.imread('1.jpg') rows,cols,ch=img.shape pts1=np.

    仿變換透射變換

    仿射變換 定義:仿射變換的功能是從二維座標到二維座標之間的線性變換,且保持二維圖形的“平直性”和“平行性”。仿射變換可以通過一系列的原子變換的複合來實現,包括平移,縮放,翻轉,旋轉和剪下。 這類變換可以用一個3*3的矩陣M來表示,其最後一行為(0,0,1)。該變換矩陣

    影象處理二:仿變換透視變換

    一、仿射變換(Affine Transformation)         放射變換(平面變換、二維座標變換):是空間直角座標系的變換,從一個二維座標變換到另一個二維座標,仿射變換是一個線性變換,保持了影象的“平行性”和“平直性”,即影象中原來的直線和

    仿變換投影變換

    1. 仿射變換 1) 用途 旋轉 (線性變換),平移 (向量加).縮放(線性變換),錯切,反轉 2) 方法 仿射變換是一種二維座標到二維座標之間的線性變換,它保持了二維圖形的“平直性”(直線經過變換之後依然是直線)和“平行性”(二維圖形之間的相對位置關係保持不變,平行線依然是平行線,

    影象離散餘弦變換變換

    使用的函式:B = dct(A); 功能:實現影象的二維離散餘弦變換。  A為原影象,B為變換後的影象。 使用的函式:B=idct2(A); 功能:實現影象的二維離散餘弦反變換 A為原影象,B為變換後的影象。 原始碼:clc; clear all; I=imread(

    傅立葉變換拉普拉斯變換

    尤拉公式 證明過程如下 首先是泰勒展開 參考cosX和sinX的泰勒展開可以證明這個問題。 還有下面這個號稱宇宙最美公式 “自然底數e,自然數1和0,虛數i還有圓周率pi,它是這麼簡潔,這麼美麗啊!” 傅立葉級數 傅立葉在提出傅立葉變換時,堅持認為任何一個週期訊號都可

    opencv3 離線餘弦變換變換

    程式碼如下 #include<opencv.hpp> int main() { cv::Mat image; cv::Mat dctimage; image = cv::imread("F:\\ebook\\opencv\\LearningOpenCV3\\tes

    OpenCV下利用傅立葉變換變換實現影象卷積演算法,並附自己對於卷積核/模板核算子的理解!

    學過訊號與系統的人都知道,卷積運算一般是轉化成頻率乘積再求逆來計算,因為這樣可以減少計算量,提高程式碼的效率。 影象卷積操作廣泛應用在影象濾波技術中。 影象卷積運算中一個重要概念是卷積核算子,它是模板核算子的一種,模板核算子實際上就是一個視窗矩陣,用這個視窗按畫素點滑動去

    傅立葉變換變換公式的我理解意義

    f(t)的傅立葉變換F(w)=∫  f(t) *e(-iwt)dt ,由於(1,sinwx,coswx,sin2wx,cos2wx,... sinnwx,cosnwx,....)是一組正交函式,傅立葉變換從公式來看就是內積,只有f(t)中含有對應w分 量才能有內積不為零,有

    用opencv實現圖片的仿變換旋轉

    import cv2 import numpy as np img = cv2.imread('1.jpg',1) cv2.imshow('old',img) imgInfo = img.shape height = imgInfo[0] width = imgInfo[1] matSrc = n

    仿變換旋轉放縮變換

    #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/core/core.hpp> #include <opencv2/

    iOS動畫特效(七)仿變換-CGAffineTransform

    仿射變換 AffineTransform,在iOS中他的實現類是CGAffineTransform和CATransform3D,很多動畫效果都需要用到仿射去完成 所以仿射是動畫基礎,不能熟練使用也肯定玩不好動畫特效的 在iOS動畫和特效專題(六)中有用到仿射變換的內容,這一篇專門來研究一下仿射變

    OpenCV3之——影象仿變換warpAffine()getRotationMatrix2D()

    #include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; #define WINDOW_NAME1 "原始圖視窗" #defi

    OpenCV中二維點求取進行仿透視變換之後的座標點方法

    我使用的是OpenCV 2.2版本。得到了一個透視矩陣,想把螢幕上的一個二維點經過這個透視矩陣進行變換,本身很簡單的一個事情,卻頗費了一番周折。原因是剛接觸OpenCV,而且使用了OpenCV新新增的C++部分的矩陣類Mat,使用起來還真有點不順手,因為OpenCV中沒有向

    學習OpenCV範例(十六)——重對映仿變換

    重對映在影象處理中主要的功能為:將一個影象中一個位置的畫素放置到另一個影象指定位置的過程,可以根據自己設定的函式將影象進行變換,較常見的功能有關於x軸翻轉,關於y軸翻轉,關於x、y軸翻轉;仿射變換在影象處理中的主要功能為:對影象進行縮放、旋轉、平移、扭曲等。 1、原理 從下

    透視變換仿變換(下)

    其實說白了仿射變換是透視變換的特殊形式,只不過透視變換的角度擴充套件到了z座標,相當於從空間中另一個平面看這個圖,仿射變換在同一個平面不同角度看同一個圖,一下是透視變換的一個例子,通過一個原圖(一個原圖,一個做了相應變換的圖),來確定變換的方位,思想還是上節的思想: 1.通

    仿變換透射變換單應性矩陣

    estimateRigidTransform():計算多個二維點對或者影象之間的最優仿射變換矩陣 (2行x3列),H可以是部分自由度,比如各向一致的切變。getAffineTransform():計算3個二維點對之間的仿射變換矩陣H(2行x3列),自由度為6.warpAffine():對輸入影象進行仿射變

    AGG第十八課 agg::trans_affine仿變換

    agg agg::trans_affine 仿射變換1 affine仿射變換概念在幾何上定義為兩個向量空間之間的一個仿射變換或者仿射映射(來自拉丁語,affinis,"和。..相關")由一個線性變換接上一個平移組成。2 agg::trans_affine成員函數說明2.1 縮放inline const t

    Halcon 學習筆記3 仿變換

    continue use net example handle region blog enter this 像素的減少 開運算(較少) 腐蝕(去除更多) 對灰度圖像的開運算或腐蝕 相當於將灰度圖像變暗 像素增加 閉運算(較少) 膨脹(較多) 對灰度圖像的閉運算或膨脹