圖像旋轉後的還原圖像坐標

2023-10-12 00:18
文章标签 圖像 旋轉 還原 坐標

本文主要是介绍圖像旋轉後的還原圖像坐標,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://www.cnblogs.com/slysky/archive/2012/03/30/2426059.html

需求:對每個新圖像中的像素進行遍歷。計算像素點在原圖像中對應的位置。

 

由於在求邊界時,假定圖像進行順時針旋轉,因此此處進行反推新像素位置在原圖像中的對應位置時,需要用逆時針計算。

順時針計算方法是:

X = xcos(theta) + y sin(theta)

Y = y cos(theta) – x sin(theta)

逆時針計算方法是:

X= x cos(theta) – ysin(theta)

Y = xsin(theta) + ycos(theta)。

 

而圖像的坐標軸與平常所用的坐標軸不同。

也就是說,圖像的旋轉順時針和逆時針的坐標變換公式與常見坐標的變換公式相反:

逆時針計算方法是:

X = xcos(theta) + y sin(theta)

Y = y cos(theta) – x sin(theta)

順時針計算方法是:

X= x cos(theta) – ysin(theta)

Y = xsin(theta) + ycos(theta)。

邊界xmin,xmax,ymin,ymax的計算方法:

void bound(int x, int y, float ca, float sa, int *xmin, int *xmax, int *ymin, int *ymax)

/* int x,y;

 float ca,sa;

 int *xmin,*xmax,*ymin,*ymax;*/

{  

    int rx,ry;

     // 以左上角為中心逆時針旋轉

    rx = (int)floor(ca*(float)x+sa*(float)y);

    ry = (int)floor(-sa*(float)x+ca*(float)y);

    if (rx<*xmin) *xmin=rx; if (rx>*xmax) *xmax=rx;

    if (ry<*ymin) *ymin=ry; if (ry>*ymax) *ymax=ry;

}

計算出邊界來之後,就可以用下式子計算出新圖像的高度和寬度。

xmin = xmax = ymin = ymax = 0;

     bound(nx-1,0,ca,sa,&xmin,&xmax,&ymin,&ymax);

     bound(0,ny-1,ca,sa,&xmin,&xmax,&ymin,&ymax);

     bound(nx-1,ny-1,ca,sa,&xmin,&xmax,&ymin,&ymax);

 

     sx = xmax-xmin+1;

     sy = ymax-ymin+1;

 

然後就可以利用cvWarpAffine( src, rotImage, &M,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,

cvScalarAll(0) )進行旋轉。

其實,方法cvWarpAffine看起來的效果,貌似是按照圖像左上角旋轉,然後,平移矩陣a13,a23得到的。

即:

     xp = ca * x + sa * y - xtrans;

     yp = ca * y – sa * x - ytrans;

M矩陣為:

     m[0] = ca;

     m[1] = sa;

     m[2] =-(float)xmin;

     m[3] =-m[1];

     m[4] = m[0];

     m[5] =-(float)ymin;

繞了好幾天,終於搞清楚了。

上文中提到的都是從原圖計算旋轉後新圖的問題。

怎樣進行復原。

首先,需要找出原圖像的原點。此處就是原圖像左上角的點,在新圖像中的位置。旋轉超過90°和不超過需要分開處理。

void compensate_affine_coor1(int *x0, int *y0, int w1, int h1, float t1, float t2, float Rtheta)

{

     // 逆時針旋轉時的復原

     float x_ori, y_ori;   

     float x_tmp, y_tmp;

 

     float x1 = *x0;

     float y1 = *y0;

 

     Rtheta = Rtheta*CV_PI/180;

 

     if ( Rtheta <= CV_PI/2 )

     {

         x_ori = 0;

         y_ori = w1 * sin(Rtheta) / t1;

     }

     else

     {

         x_ori = -w1 * cos(Rtheta) / t2;

         y_ori = ( w1 * sin(Rtheta) + h1 * sin(Rtheta-CV_PI/2) ) / t1;

     }

     float sin_Rtheta = sin(Rtheta);

     float cos_Rtheta = cos(Rtheta);

 

 

     /* project the coordinates of im1 to original image before tilt-rotation transform */

     /* Get the coordinates with respect to the 'origin' of the original image before transform */

     x1 = x1 - x_ori;

     y1 = y1 - y_ori;

     /* Invert tilt */

     x1 = x1 * t2;

     y1 = y1 * t1;

     /* Invert rotation (Note that the y direction (vertical) is inverse to the usual concention. Hence Rtheta instead of -Rtheta to inverse the rotation.) */

     x_tmp = cos_Rtheta*x1 - sin_Rtheta*y1;

     y_tmp = sin_Rtheta*x1 + cos_Rtheta*y1;

 

     x1 = x_tmp+1;

     y1 = y_tmp+1;     

 

     *x0 = x1;

     *y0 = y1;

}

旋轉不超過90度時,

因此,O`的x_ori = 0; y_ori = w1 * sin(Rtheta) / t1;

 

如果超過90度時,

x_ori = -w1 * cos(Rtheta) / t2;

y_ori = ( w1 * sin(Rtheta) + h1 * sin(Rtheta-CV_PI/2) ) / t1;

 

首先將所需要還原的坐標點平移,使之變為相對於O`點的坐標。然後,以O`點,即原來的O點按相反的方向旋轉theta角度。注意,w1和h1是旋轉前新圖像的高寬,而不是旋轉後新圖像的高和寬。


这篇关于圖像旋轉後的還原圖像坐標的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/191861

相关文章

圖像處理算法

http://blog.csdn.net/shen_wei/article/details/5432566 1)將256*256分辨率的圖像變為128*128分辨率可以將源圖像劃分成2*2的子圖像塊,然後將2*2的 子圖像塊的所有像素顏色均按照F(i,j)的顏色值進行設定,達到降低分辨率的目的。 如: F(i,j)    F(i,j+1)                  F(i,j)

雙線性插值(Bilinear interpolation)的圖像旋轉在mobile上面的C++實現

http://blog.csdn.net/cay22/article/details/5555585  雙線性插值(Bilinear interpolation)的圖像旋轉在mobile上面的C++實現   我們找來了圖像旋轉的公式:   X' =  X cosθ -  Y sinθ;   Y' =  X sinθ  + Y cosθ;   這個圖像公式大家在高中數學課都是會算滴。 然後我

旋轉變換矩陣

http://blog.csdn.net/as3_flash/article/details/2378483  利用矩陣能完成旋轉。對於圖中的點S(j,0),可以看作矩陣A[j,0],令點S旋轉a度得到點T(m,n),可以看作矩陣C[m,n],顯然可以存在變換矩陣B,令A×B=C成立。由簡單的幾何知識就能得出變換矩陣B的構造。 因為點S位於坐標軸上,使得計算矩陣B的過程極大的簡化了。如果

圖像處理基本算法-直方圖均衡

http://blog.csdn.net/renshengrumenglibing/article/details/7065330 直方圖是多種空間處理技術的基礎,可以用於圖像增強。同時在其他的處 理方法中也十分有用,比如圖像壓縮和分割。 基本的原理: Ni = 255*(N0 + N1 + N2 +……Ni)/(width*height) 程序流程: 1、統計各個像素值的個數 2、建立映

圖像相似度算法的C#實現及測評

http://www.cnblogs.com/wuchaodong/archive/2009/04/28/1444792.html 近日逛博客的時候偶然發現了一個有關圖片相似度的Python算法實現。想著很有意思便搬到C#上來了,給大家看看。 閒言碎語   才疏學淺,只把計算圖像相似度的一個基本算法的基本實現方式給羅列了出來,以至於在最後自己測評的時候也大發感慨,這個算法有點不靠譜。

查找圖像中橢圓輪廓的快速隨機hough變換

http://www.cnblogs.com/cvart/archive/2011/07/07/2100564.html 查找圖像中橢圓輪廓的快速隨機hough變換   圖像中橢圓輪廓的查找在視頻監控等領域有著廣泛的應用,經典hough變換給我們提供了一種查找各種圖形輪廓的方法,特別是在直線查找方面具有非常高的精確度。但是由於經典hough變換的基本原理是將圖像空間轉換到參數空間,所以

dog算子处理图片边界matlab代码,圖像邊緣檢測——二階微分算子(上)Laplace算子、LOG算子、DOG算子(Matlab實現)...

如果圖像灰度變化劇烈,進行一階微分則會形成一個局部的極值,由數學上的知識,對圖像進行二階微分則會形成一個過零點,並且在零點兩邊產生一個波峰和波谷,我們要設定一個閾值,檢測到這個過零點,如下圖所示: 帶來了兩個好處: 1. 二階微分關心的是圖像灰度的突變而不強調灰度緩慢變化的區域,對邊緣的定位能力更強。 2. Laplace算子是各項同性的,即具有旋轉不變性(后面會證明),在一階微分里,我們是用