c++ - 不裁剪的图像旋转
问题描述
亲爱的,使用下面的代码,我旋转了我的 cv::Mat 对象(我没有使用任何 Cv 的功能,除了加载/保存/转换颜色..,因为这是一个学术项目)并且我收到了一个裁剪的图像
旋转功能:
float rads = angle*3.1415926/180.0;
float _cos = cos(-rads);
float _sin = sin(-rads);
float xcenter = (float)(src.cols)/2.0;
float ycenter = (float)(src.rows)/2.0;
for(int i = 0; i < src.rows; i++)
for(int j = 0; j < src.cols; j++){
int x = ycenter + ((float)(i)-ycenter)*_cos - ((float)(j)-xcenter)*_sin;
int y = xcenter + ((float)(i)-ycenter)*_sin + ((float)(j)-xcenter)*_cos;
if (x >= 0 && x < src.rows && y >= 0 && y < src.cols) {
dst.at<cv::Vec4b>(i ,j) = src.at<cv::Vec4b>(x, y);
}
else {
dst.at<cv::Vec4b>(i ,j)[3] = 0;
}
}
我想知道,每次我想旋转它时如何保持我的完整图像。我可能在我的功能中遗漏了一些东西吗?提前致谢
解决方案
旋转后的图像通常必须比旧图像大才能存储所有像素值。
每个点(x,y)
都被翻译成
(x', y') = (x*cos(rads) - y*sin(rads), x*sin(rads) + y*cos(rads))
具有高度h
和宽度的图像w
,中心位于 (0,0),角位于
(h/2, w/2)
(h/2, -w/2)
(-h/2, w/2)
(-h/2, -w/2)
有一个新的高度
h' = 2*y' = 2 * (w/2*sin(rads) + h/2*cos(rads))
和一个新的宽度
w' = 2*x' = 2 * (w/2*cos(rads) + h/2*sin(rads))
为0 <= rads <= pi/4
. 它是x * y <= x' * y'
并且因为rads != k*pi/2
它k = 1, 2, ...
是x * y < x' * y'
在任何情况下,旋转图像的区域都与旧图像的区域大小相同或更大。
如果你使用旧尺寸,你会剪掉角落。
例子:
您的图像有h=1
,w=1
和rads=pi/4
. 您需要一个新图像h'=sqrt(2)=1.41421356237
并w'=sqrt(2)=1.41421356237
存储所有像素值。来自 (1,1) 的像素被转换为 (0, sqrt(2))。
推荐阅读
- ibm-watson - 在 IBM Watson Conversation 中将动态上下文变量与实体进行比较
- java - 使用类作为名称的参数化类的原始使用
- github - Github 拉取请求差异
- c# - 浅拷贝与赋值和深拷贝与原型设计模式中使用新关键字创建新对象之间的区别
- c# - 跨多种类型设计一个属性的最佳方法 (.Net)
- java - 在java中访问对象函数时如何解决错误?
- amazon-web-services - EBS中有哪些好的警报?
- javascript - 在 Javascript 对象中存储图像的最佳方法是什么?
- c# - LINQ to Entities 无法识别方法“<>f__AnonymousType4`1[System.String] get_Item(Int32)”
- sublimetext3 - Sublime Text 3 键绑定优先级