图像放大 缩小 旋转 亚像素处理

/*图像旋转(以图像中心为旋转中心)*/
void CImageProcessDlg::affine_trans_rotate(cv::Mat& src, cv::Mat& dst, double Angle)
{
	double angle = Angle * CV_PI / 180.0;
	// 构造输出图像
	int dst_rows = round(fabs(src.rows * cos(angle)) + fabs(src.cols * sin(angle)));	// 图像 高度
	int dst_cols = round(fabs(src.cols * cos(angle)) + fabs(src.rows * sin(angle)));	// 图像 宽度
	if (src.channels() == 1)	// 灰度图
	{
		dst = Mat::zeros(dst_rows, dst_cols, CV_8UC1);	// 灰度图初始
	}
	else
	{
		dst = Mat::zeros(dst_rows, dst_cols, CV_8UC3);	// RGB图初始化
	}
	// 平移转换矩阵 将原图像坐标映射到数学笛卡尔坐标
	cv::Mat T1 = (cv::Mat_<double>(3, 3) << 1.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.5 *src.cols, 0.5*src.rows, 1.0);	
	// 旋转 矩阵 //数学笛卡尔坐标下顺时针旋转的变换矩阵
	cv::Mat T2 = (cv::Mat_<double>(3, 3) << cos(angle), -sin(angle), 0.0, sin(angle), cos(angle), 0.0, 0.0, 0.0, 1.0);
	// 将数学笛卡尔坐标映射到旋转后的图像坐标
	double t3[3][3] = { {1.0, 0.0,0.0},{0.0, -1.0, 0.0}, {0.5*dst.cols, 0.5*dst.rows, 1.0} };
	cv::Mat T3 = cv::Mat(3.0, 3.0, CV_64FC1, t3);
	cv::Mat T = T1 * T2 * T3;
	// 求逆矩阵
	cv::Mat T_inv = T.inv();
 #pragma omp parallel for 
	for (int i = 0; i < dst.rows; i++)
	{
		for (int j = 0; j < dst.cols; j++)
		{
			cv::Mat dst_coordinate = (cv::Mat_<double>(1, 3) << j, i, 1.0);
			cv::Mat src_coordinate = dst_coordinate * T_inv;
			double v = src_coordinate.at<double>(0, 0);// 原图像的横坐标,列,宽
			double w = src_coordinate.at<double>(0, 1);// 原图像的纵坐标,行,高

			// 双线性插值
			// 判断是否越界  //必须要加上,否则会出现边界问题
			if (int(angle) % 90 == 0)
			{
				if (v < 0) v = 0;
				if (v > src.cols - 1) v = src.cols - 1;
				if (w < 0) w = 0;
				if (w > src.rows - 1) w = src.rows - 1;
			}
			if (v >= 0 && w >= 0 && v <= src.cols-1 && w <= src.rows - 1)
			{
				int top = floor(w), bottom = ceil(w), left = floor(v), right = ceil(v);//与映射到原图坐标相邻的四个像素点的坐标
				double pw = w - top; //pw为坐标 行 的小数部分(坐标偏差)
				double pv = v - left; //pv为坐标 列 的小数部分(坐标偏差)
				if (src.channels() == 1)
				{
					// 灰度图像
					dst.at<uchar>(i, j) = (1 - pw)*(1 - pv)*src.at<uchar>(top, left) + (1 - pw)*pv*src.at<uchar>(top, right) + pw * (1 - pv)*src.at<uchar>(bottom, left) + pw * pv*src.at<uchar>(bottom, right);
				}
				else
				{
					//彩色图像
					dst.at<cv::Vec3b>(i, j)[0] = (1 - pw)*(1 - pv)*src.at<cv::Vec3b>(top, left)[0] + (1 - pw)*pv*src.at<cv::Vec3b>(top, right)[0] + pw * (1 - pv)*src.at<cv::Vec3b>(bottom, left)[0] + pw * pv*src.at<cv::Vec3b>(bottom, right)[0];
					dst.at<cv::Vec3b>(i, j)[1] = (1 - pw)*(1 - pv)*src.at<cv::Vec3b>(top, left)[1] + (1 - pw)*pv*src.at<cv::Vec3b>(top, right)[1] + pw * (1 - pv)*src.at<cv::Vec3b>(bottom, left)[1] + pw * pv*src.at<cv::Vec3b>(bottom, right)[1];
					dst.at<cv::Vec3b>(i, j)[2] = (1 - pw)*(1 - pv)*src.at<cv::Vec3b>(top, left)[2] + (1 - pw)*pv*src.at<cv::Vec3b>(top, right)[2] + pw * (1 - pv)*src.at<cv::Vec3b>(bottom, left)[2] + pw * pv*src.at<cv::Vec3b>(bottom, right)[2];
				}
			}
		}
	}
}

/*平移变换*(以图像左顶点为原点)/
/****************************************
tx: 水平平移距离 正数向右移动 负数向左移动
ty: 垂直平移距离 正数向下移动 负数向上移动
*****************************************/
void CImageProcessDlg::affine_trans_translation(cv::Mat& src, cv::Mat& dst, double tx, double ty)
{
	// 输出构造函数
	int dst_rows = src.rows /*+ tx*/;
	int dst_cols = src.cols /*+ ty*/;
	if (src.channels() == 1)
	{
		dst = cv::Mat::zeros(dst_rows, dst_cols, CV_8UC1);
	}
	else
		dst = cv::Mat::z
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值