图像处理之几何变换

#include "cv.h"
#include "highgui.h"

using namespace cv;

#define PI 3.1415926
#define RADIAN(angle) ((angle)*PI/180.0)

//平移
void Translate(Mat& image,int xOffset,int yOffset)
{
	int M=image.rows;
	int N=image.cols;

	Mat temp=image.clone();
	for(int i=0;i<M;i++)
	{
		uchar* p=image.ptr<uchar>(i);
		memset(p,0,N);
	}

	for(int i=0;i<M;i++)
	{
		int newi=i-xOffset;
		if(newi<0||newi>=M)
			continue;
		uchar* p=image.ptr<uchar>(i);
		uchar* p1=temp.ptr<uchar>(newi);
		
		int j=0;
		while(j<M)
		{
			if(j-yOffset>=0)
			{
				memcpy(p+j,p1+j-yOffset,min(N-j,N-j+yOffset));
				break;
			}
			j++;
		}
	}
}

//旋转
Mat Rotate(Mat& image,int angle)
{
	int M=image.rows;
	int N=image.cols;

	//角度到弧度的转换
	float rotateAngle=(float)RADIAN(angle);
	float cosa=(float)cos((double)rotateAngle);
	float sina=(float)sin((double)rotateAngle);

	//原图四个角坐标
	float srcX1=(float)(-0.5*N),srcY1=(float)(0.5*M);
	float srcX2=(float)(0.5*N),srcY2=(float)(0.5*M);
	float srcX3=(float)(-0.5*N),srcY3=(float)(-0.5*M);
	float srcX4=(float)(0.5*N),srcY4=(float)(-0.5*M);

	//新图四个角坐标
	float dstX1=cosa*srcX1+sina*srcY1,dstY1=-sina*srcX1+cosa*srcY1;
	float dstX2=cosa*srcX2+sina*srcY2,dstY2=-sina*srcX2+cosa*srcY2;
	float dstX3=cosa*srcX3+sina*srcY3,dstY3=-sina*srcX3+cosa*srcY3;
	float dstX4=cosa*srcX4+sina*srcY4,dstY4=-sina*srcX4+cosa*srcY4;

	//计算新图的宽度和高度
	int newN=(int)(max(fabs(dstX4-dstX1),fabs(dstX3-dstX2))+0.5);
	int newM=(int)(max(fabs(dstY4-dstY1),fabs(dstY3-dstY2))+0.5);

	float num1=(float)(-0.5*newN*cosa-0.5*newM*sina+0.5*N);
	float num2=(float)(0.5*newN*sina-0.5*newM*cosa+0.5*M);

	Mat ret(newM,newN,CV_8U);
	for(int y1=0;y1<newM;y1++)
	{
		for(int x1=0;x1<newN;x1++)
		{
			int x0=(int)(x1*cosa+y1*sina+num1);
			int y0=(int)(-1.0f*x1*sina+y1*cosa+num2);
			if(x0>=0&&x0<N&&y0>=0&&y0<M)
			{
				uchar* p=ret.ptr<uchar>(y1);
				uchar* p1=image.ptr<uchar>(y0);
				p[x1]=p1[x0];
			}
		}
	}

	return ret;
}

//镜像
void Mirror(Mat& image,bool flag)
{
	int M=image.rows;
	int N=image.cols;

	//水平
	if(flag)
	{
		for(int i=0;i<M;i++)
		{
			uchar* p=image.ptr<uchar>(i);
			for(int j=0;j<N/2;j++)
			{
				uchar temp=p[j];
				p[j]=p[N-j-1];
				p[N-j-1]=temp;
			}
		}
	}
	else//垂直
	{
		for(int j=0;j<N;j++)
		{
			for(int i=0;i<M/2;i++)
			{
				uchar temp=image.ptr<uchar>(i)[j];
				image.ptr<uchar>(i)[j]=image.ptr<uchar>(M-i-1)[j];
				image.ptr<uchar>(M-i-1)[j]=temp;
			}
		}
	}
}

//转置
Mat Transpose(Mat& image)
{
	int M=image.rows;
	int N=image.cols;

	Mat ret(N,M,CV_8U);
	for(int i=0;i<N;i++)
		for(int j=0;j<M;j++)
			ret.ptr<uchar>(i)[j]=image.ptr<uchar>(j)[i];
	
	return ret;
}

//缩放
Mat Zoom(Mat& image,float ratio)
{
	int M=image.rows;
	int N=image.cols;

	int newM=(int)(M*ratio+0.5);
	int newN=(int)(N*ratio+0.5);

	Mat ret(newM,newN,CV_8U);

	for(int i=0;i<newM;i++)
	{
		for(int j=0;j<newN;j++)
		{
#if 0
		    int x=(int)(i/ratio);
			int y=(int)(j/ratio);

			if(x>=0&&x<M&&y>=0&&y<N)
			{
				ret.ptr<uchar>(i)[j]=image.ptr<uchar>(x)[y]; //找最临近点 最邻近插值
			}
#else
			float x=i/ratio;
			float y=j/ratio;
			if(x>=0&&x<M-1&&y>=0&&y<N-1)
			{
				//双线性插值
				int x1=(int)floor(x),x2=x1+1;
				int y1=(int)floor(y),y2=y1+1;

				int g=(image.ptr<uchar>(x1)[y2]-image.ptr<uchar>(x1)[y1])*(x-x1)+image.ptr<uchar>(x1)[y1];
				int h=(image.ptr<uchar>(x2)[y2]-image.ptr<uchar>(x2)[y1])*(x-x1)+image.ptr<uchar>(x2)[y1];

				ret.ptr<uchar>(i)[j]=(uchar)((h-g)*(y-y1)+g);
			}
#endif
		}
	}

	return ret;
}

int main()
{
	//读取图像
	Mat image;
	image=imread("a.jpg",CV_LOAD_IMAGE_GRAYSCALE);

	int M=image.rows;
	int N=image.cols;

	//几何变换

	Mat newImage=Zoom(image,4);
	
	cvNamedWindow("test",CV_WINDOW_AUTOSIZE);
	imshow("test",newImage);

	waitKey(0);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值