利用OpenCV旋转图像的摸索(2)

10 篇文章 0 订阅
1 篇文章 0 订阅

http://blog.csdn.net/leaf6094189/article/details/18554549以及http://blog.csdn.net/xiaowei_cqu/article/details/7616044对图像的矩阵变换做了详细的阐述:二维图的变换,如旋转、平移、缩放等,都可以转化为一系列的矩阵操作。这个变换矩阵是是2行3列的cv::Mat。变换矩阵通常的type()是CV_64FC1型,即是说,6个元素的类型都是double。保存在cv::Mat::data为首地址的一段内存里面。由于cv::Mat是行主序排列,所以第一行的3个元素先排,第二行的3个元素后排。

根据 http://blog.csdn.net/xiaowei_cqu/article/details/7616044的说法,这个矩阵的前两列构成一个2x2的矩阵,任何的围绕图像原点(原点即图像左上角)的旋转操作和任何缩放操作都可以用这个2x2矩阵表述。而矩阵的平移则由矩阵的第三列表示。这里要注意,在坐标变换里,少不了规定坐标系。OpenCV规定X正方向是图像的右方,而Y正方向是图像下方。

下图所示的矩阵,表示先将图像绕坐标系原点(即图像左上)逆时针转动角度a,然后沿X方向和Y方向分别平移dX,dY。


接下来验证上面的话。跟利用OpenCV旋转图像的摸索(1)一样,我们利用一张274x300的莱纳图。先产生一个围绕(0,0)旋转的矩阵rotateMat。这样会让图像逆时针转动30度。,如下图:


但是转出去的部分(红线以上)就看不到了。为了让图像完整可见,还要下移图像。于是,接下来把rotateMat.data的第6个元素设置为137.

这是因为图像宽度是274,所以转出部分的高度就是274 * sin(30) = 137. 第六个元素是前面提到的dY,也就是图像下移的像素数。

代码:

int _tmain(int argc, _TCHAR* argv[])
{
	cv::Mat image = cv::imread("E:\\lena.jpg");
	if (image.empty())
	{
		std::cout<<"read image failure"<<std::endl;
		return -1;
	}

	//cv::Point2f center = cv::Point2f(image.cols , image.rows );  // 旋转中心
	cv::Point2f center = cv::Point2f(0 , 0 );
	double angle = 30;  // 旋转角度
	double scale = 1; // 缩放尺度

	cv::Mat rotateMat; 
	rotateMat = cv::getRotationMatrix2D(center, angle, scale);
	/*注意这段代码:*/
	cv::Mat shiftImg = cv::Mat::zeros(image.rows * 2, image.cols * 2, image.type());
	int iType = rotateMat.type();
	//cv::Mat ROI = shiftImg(cv::Rect(image.cols / 2, image.rows/2, image.cols, image.rows));
	cv::Mat ROI = shiftImg(cv::Rect(0, 0, image.cols, image.rows));
	image.copyTo(ROI);
	/***************/
	cv::Mat rotateImg;
	unsigned char * pData = rotateMat.data + sizeof(double) * 5;
	double dY = 137;
	memcpy(pData, &dY, sizeof(double));
	cv::warpAffine(shiftImg, rotateImg, rotateMat, shiftImg.size());
	double arrMat[6];
	memcpy(arrMat, rotateMat.data, sizeof(double) * 6);
	printf("%lf %lf %lf %lf %lf %lf", arrMat[0], arrMat[1], arrMat[2], arrMat[3], arrMat[4], arrMat[5]); 
	cv::imwrite("E:\\rotate.jpg", rotateImg);
	cv::imwrite("E:\\shift.jpg", shiftImg);
	return 0;
}
加断点观察可见,rotateMat.data的内容确实与前面分析的一致:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值