图像学习一:图像的旋转

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章