圖像學習一:圖像的旋轉

A:旋轉原理和旋轉公式:
推導旋轉公式:

這裏寫圖片描述
有: tg(b)=y/x —-(1)
tg(a+b)=y’/x’ —-(2)
x*x + y*y = x’*x’ + y’*y’ —-(3)
有公式:tg(a+b) = ( tg(a)+tg(b) ) / ( 1-tg(a)*tg(b) ) —-(4)
把(1)代入(4)從而消除參數b;
tg(a)+y/x = y’/x’*( 1-tg(a)*y/x ) —-(5)
由(5)可以得x’=y’*(x-y*tg(a))/( x*tg(a)+y ) —-(6)
把(6)代入(3)從而消除參數x’,化簡後求得:
y’=x*sin(a)+y*cos(a); —-(7)
把(7)代入(6),有:
x’=x*cos(a)-y*sin(a); —-(8)
OK,旋轉公式有了,那麼來看看在圖片旋轉中的應用;
假設對圖片上任意點(x,y),繞一個座標點(rx0,ry0)逆時針旋轉RotaryAngle角度後的新的座標設爲(x’, y’),有公式:
(x平移rx0,y平移ry0,角度a對應-RotaryAngle , 帶入方程(7)、(8)後有: )
x’= (x - rx0)*cos(RotaryAngle) + (y - ry0)*sin(RotaryAngle) + rx0 ;
y’=-(x - rx0)*sin(RotaryAngle) + (y - ry0)*cos(RotaryAngle) + ry0 ;
那麼,根據新的座標點求源座標點的公式爲:
x=(x’- rx0)*cos(RotaryAngle) - (y’- ry0)*sin(RotaryAngle) + rx0 ;
y=(x’- rx0)*sin(RotaryAngle) + (y’- ry0)*cos(RotaryAngle) + ry0 ;
旋轉的時候還可以順便加入x軸和y軸的縮放和平移,而不影響速度,那麼完整的公式爲:
x=(x’- move_x-rx0)/ZoomX*cos(RotaryAngle) - (y’- move_y-ry0)/ZoomY*sin(RotaryAngle) + rx0 ;
y=(x’- move_x-rx0)/ZoomX*sin(RotaryAngle) + (y’- move_y-ry0)/ZoomY*cos(RotaryAngle) + ry0 ;
其中: RotaryAngle爲逆時針旋轉的角度;
ZoomX,ZoomY爲x軸y軸的縮放係數(支持負的係數,相當於圖像翻轉);
move_x,move_y爲x軸y軸的平移

#include <iostream>
#include <cv.h>
#include <highgui.h>
#include <imgproc/imgproc.hpp>
#include <iostream>
#include <math.h>


using namespace std;
using namespace cv;
#define  PI 3.1415926



int main(int argc, const char * argv[])
{

    //1:load source image
    Mat image = imread("/Users/hanoi/Desktop/1.jpg",0);
    if(image.empty())
    {
        printf("it can not load image\n");
        return 0;
    }

    int height = image.rows;
    int width = image.cols;


    Mat destImage;
    destImage.create(height*2, width*2, image.type());
    memset(destImage.data, 255, height*2 * width*2);

    double angle = 30;
    double degree = angle * PI / 180;
    int new_width = width*2;
    int new_height = height*2;

    for(int j=0; j<new_height; j++)
    {
        for(int i=0; i<new_width; i++)
        {
            if(i>new_width/4 && i<new_width*3/4 && j>new_height/4 && j<new_height*3/4)
            {
                *(destImage.data + j*destImage.step + i) = *(image.data + (j-new_height/4)*image.step + (i-new_width/4));
            }
        }
    }
    imwrite("/Users/hanoi/Desktop/test.bmp", destImage);


    Mat onedestImage;
    onedestImage.create(height*2, width*2, image.type());
    memset(onedestImage.data, 255, height*2 * width*2);
    int centerx = new_width/2;
    int centery = new_height/2;
    int newx=0,newy=0;
    for(int j=0; j<new_height; j++)
    {
        for(int i=0; i<new_width; i++)
        {
            newx = (i-centerx)/2*cos(degree) + (j-centery)/2*sin(degree) + centerx;
            newy = -(i-centerx)/2*sin(degree) + (j-centery)/2*cos(degree) + centery;

            if(newx >=0 && newx < new_width && newy>=0 && newy < new_height)
            {
                *(onedestImage.data + newy*destImage.step + newx) = *(destImage.data + j*destImage.step + i);
            }
        }
    }

    imwrite("/Users/hanoi/Desktop/t22est.bmp", onedestImage);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章