Opencv2实现平移、旋转、双线性差值放缩变换

本文介绍了几种基本的图像几何变换方法,包括图像平移、旋转和双线性差值缩放,并提供了详细的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 概述

在本文中记录集中简单的几何变换的Opencv实现,对于不是依赖Opencv实现的也可以按照类似的写法完成移植,这些函数经过测试都是可以正常使用的。

2. 实现

图像的平移变换:
//************************************************************************
// 函数名称:    	ImgMove
// 访问权限:    	public 
// 创建日期:		2016/12/05
// 创 建 人:		
// 函数说明:		图像平移操作
// 函数参数: 	cv::Mat & input_img		输入图像
// 函数参数: 	cv::Mat & output_img	输出图像
// 函数参数: 	const int x_diff		图像X轴上的平移距离
// 函数参数: 	const int y_diff		图像Y轴上的平移距离
// 返 回 值:   	bool
//************************************************************************
bool CCalcMutualInfo::ImgMove(cv::Mat& input_img, cv::Mat& output_img, const int x_diff, const int y_diff)
{
	if (!input_img.data)
	{
		cout << "asad" << endl;
		return false;
	}
	int Nrows(input_img.rows);
	int Ncols(input_img.cols);
	unsigned char *data1=nullptr, *data2=nullptr;

	cv::Mat img_temp(Nrows, Ncols, CV_8UC1, cv::Scalar::all(0));
	for (int i = 0; i < Nrows; i++)
	{
		data2 = img_temp.ptr<uchar>(i);
		for (int j = 0; j < Ncols; j++)
		{
			if ((i >= x_diff) && (j >= y_diff) && (i-x_diff<Nrows) && (j-y_diff<Ncols))
			{
				data1 = input_img.ptr<uchar>(i - x_diff);
				data2[j] = data1[j - y_diff];
			}
			else
			{
				data2[j] = 0;
			}
		}
	}

	img_temp.copyTo(output_img);

	return true;
}
旋转变换:
//************************************************************************
// 函数名称:    	ImgRotate
// 访问权限:    	public 
// 创建日期:		2016/12/06
// 创 建 人:		
// 函数说明:		图像旋转
// 函数参数: 	cv::Mat & input_img		输入图像
// 函数参数: 	cv::Mat & output_img	输出图像
// 函数参数: 	const double angle		图像的旋转角度
// 返 回 值:   	bool
//************************************************************************
bool CCalcMutualInfo::ImgRotate(cv::Mat& input_img, cv::Mat& output_img, const double angle)
{
	if (!input_img.data)
	{
		cout << "asad" << endl;
		return false;
	}

	double image_high  = input_img.rows;		//the width of image
	double image_width = input_img.cols * input_img.channels();	//the high of image
	int Nrows = input_img.rows;					//the row number of image
	int Ncols = input_img.cols * input_img.channels();			//the column number of image
	int i=0, j=0;								//loop counting 

	uchar *data1;	//the image matrix data pointer
	uchar *data2;

	cv::Mat Dst_img(input_img.rows, input_img.cols, input_img.type(), cv::Scalar::all(0));	//the destination image matrix that store new image

	double Xvar = -0.5*image_high*std::cos(angle) + 0.5*image_width*std::sin(angle) + 0.5*image_high;	//the constant of X axis
	double Yvar = -0.5*image_high*std::sin(angle) - 0.5*image_width*std::cos(angle)	+ 0.5*image_width;	//the constant of Y axis

	for (i=0; i<Nrows; i++)
	{
		data1 = input_img.ptr<uchar>(i);
		data2 = Dst_img.ptr<uchar>(i);
		for (j=0; j<Ncols; j++)
		{
			int X1 = static_cast<int>((double)i*std::cos(angle) - (double)j*std::sin(angle) + Xvar + 0.5);
			int Y1 = static_cast<int>((double)i*std::sin(angle) + (double)j*std::cos(angle) + Yvar + 0.5);
			if ((X1>=0) && (X1<Nrows) && (Y1>=0) && (Y1<Ncols))
			{
				data2 = Dst_img.ptr<uchar>(X1);
				data2[Y1] = data1[j];
			}	
		}		
	}
	Dst_img.copyTo(output_img);

	return true;
}

双线性差值缩放:
//************************************************************************
// 函数名称:    	StretchImg
// 访问权限:    	public 
// 创建日期:		2016/12/07
// 创 建 人:		
// 函数说明:		双线性差值缩放图像
// 函数参数: 	cv::Mat & input_img	输入图像
// 函数参数: 	cv::Mat & out_img	输出图像
// 函数参数: 	double x_rate		x轴放缩比例
// 函数参数: 	double y_rate		Y轴放缩比例
// 函数参数: 	int center_x		图像X轴的重心	图像配准使用
// 函数参数: 	int center_y		图像Y轴的重心	图像配准使用
// 返 回 值:   	bool
//************************************************************************
bool CCalcMutualInfo::StretchImg(cv::Mat& input_img, cv::Mat& out_img, double x_rate, double y_rate, int center_x, int center_y)
{
	if (!input_img.data)
	{
		cout << "no input img" << endl;
		return false;
	}
	if (0>=x_rate || 0>=y_rate)
	{
		cout << "rate error" << endl;
		return false;
	}

	//截取重心的512*512的图像,配准用(放缩排除这几行代码)
	int center_x1 = (int)((double)center_x*x_rate+0.5);
	int center_y2 = (int)((double)center_y*y_rate+0.5);

	double dst_rows = input_img.rows * x_rate;			//放缩之后目标图像的高度					
	double dst_cols = input_img.cols * input_img.channels() * y_rate;	//放缩之后目标图像的宽度
	int Nrows = input_img.rows;							//原始图像的高度
	int Ncols = input_img.cols * input_img.channels();	//原始图像的宽度
	double orig_x = 0, orig_y = 0;						//输出图像上换算过去对应原图的点
	uchar *data1;	//定义三个像素指针
	uchar *data2;
	uchar *data3;

	cv::Mat Dst_img((int)dst_rows, (int)dst_cols / input_img.channels(), input_img.type());	//create a destination image
	int i = 0, j = 0;	//循环变量

	for (i = 0; i < (int)dst_rows; i++)
	{
		data2 = Dst_img.ptr<uchar>(i);
		orig_x = static_cast<double>((double)i * (Nrows - 1) / (dst_rows - 1) + 0.5);		//原图中的X坐标值
		for (j = 0; j < (int)dst_cols; j++)
		{
			orig_y = static_cast<double>((double)j * (Ncols - 1) / (dst_cols - 1) + 0.5);	//源图像的Y轴坐标

			double bx1 = orig_x - (int)orig_x;	//计算距离系数,之后按照这个进行加权
			double bx2 = 1.0 - bx1;
			double by1 = orig_y - (int)orig_y;
			double by2 = 1.0 - by1;

			if ((orig_x >= 0) && (orig_x < Nrows) && (orig_y >= 0) && (orig_y < Ncols))
			{
				if ((orig_x < Nrows - 1) && (orig_y < Ncols - 1))
				{

					data1 = input_img.ptr<uchar>((int)orig_x);
					data3 = input_img.ptr<uchar>((int)orig_x + 1);
					data2[j] = data1[(int)orig_y] * bx2 * by2 + data1[(int)orig_y + 1] * bx2 * by1 +
						data3[(int)orig_y] * bx1 * by2 + data3[(int)orig_y + 1] * bx1 * by1;	//计算加权之后的目标像素
				}
			}
		}
	}

	//截取重心的512*512的图像,配准用(放缩排除这几行代码)
	if (dst_rows > Nrows && dst_cols>Ncols)
	{
		Dst_img = Dst_img(cv::Rect((center_x1-center_x), (center_y-center_y), 512, 512));
	}
	Dst_img.copyTo(out_img);

	return true;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值