我想在 JavaCV/OpenCV 中以可变角度(如 22°)旋转一些图像。目前我使用 cvWarpAffine()
.
我的问题是,旋转后我失去了图像的边缘,所以我必须使 dst.image 更大并移动中心点。在这个页面上,我找到了一些 AS-Code 来计算图像的新尺寸。但我不知道如何用 JavaCV/OpenCV 实现它
及时我有以下代码:
public CvMat rotateImage(int angle) {
CvPoint2D32f center = new CvPoint2D32f(input.cols() / 2.0F,
input.rows() / 2.0F);
CvMat rotMat = cvCreateMat(2, 3, CV_32F);
cv2DRotationMatrix(center, angle, 1, rotMat);
CvMat dst = cvCreateMat(input.rows(), input.cols(), input.type());
cvWarpAffine(input, dst, rotMat);
return dst;
}
有人有想法吗?
问候
//更新
不知道……有事。如果我计算旋转图像,我的结果具有正确的尺寸,但它主要是黑色(0 和 360° 有效)......这是代码:
public CvMat rotateImage(float angle) {
CvPoint2D32f center = new CvPoint2D32f(input.cols() / 2.0F,
input.rows() / 2.0F);
CvBox2D box = new CvBox2D(center, cvSize2D32f(input.cols() - 1,
input.rows() - 1), angle);
CvPoint2D32f points = new CvPoint2D32f(4);
cvBoxPoints(box, points);
CvMat pointMat = cvCreateMat(1, 4, CV_32FC2);
pointMat.put(0, 0, 0, points.position(0).x());
pointMat.put(0, 0, 1, points.position(0).y());
pointMat.put(0, 1, 0, points.position(1).x());
pointMat.put(0, 1, 1, points.position(1).y());
pointMat.put(0, 2, 0, points.position(2).x());
pointMat.put(0, 2, 1, points.position(2).y());
pointMat.put(0, 3, 0, points.position(3).x());
pointMat.put(0, 3, 1, points.position(3).y());
CvRect boundingRect = cvBoundingRect(pointMat, 0);
CvMat dst = cvCreateMat(boundingRect.height(), boundingRect.width(),
input.type());
CvPoint2D32f centerDst = new CvPoint2D32f(center.x()
+ (dst.cols() / 2.0F), center.y() + (dst.rows() / 2.0F));
CvMat rotMat = cvCreateMat(2, 3, CV_32F);
cv2DRotationMatrix(centerDst, angle, 1, rotMat);
CvMat trans = cvCreateMat(3, 3, CV_32F);
cvZero(trans);
trans.put(0, 2, dst.cols() / 2.0F);
trans.put(1, 2, dst.rows() / 2.0F);
trans.put(0, 0, 1);
trans.put(1, 1, 1);
trans.put(2, 2, 1);
CvMat newRot = cvCreateMat(3, 3, CV_32F);
cvZero(newRot);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
newRot.put(i, j, rotMat.get(i, j));
}
}
newRot.put(2, 2, 1);
cvMul(trans, newRot, newRot, 1);
cvWarpPerspective(input, dst, newRot);
// cvWarpAffine(input, dst, dstRotMat);
return dst;
}
rotMat
看起来像:
[ 0.9396926, 0.34202015, -311.1334
-0.34202015, 0.9396926, 601.47485 ]
(trans
组织图片的大小为 1428x928px):
[ 1.0, 0.0, 836.0
0.0, 1.0, 699.0
0.0, 0.0, 1.0 ]
和newRot
[ 0.9396926, 0.0, -260107.52
-0.0, 0.9396926, 420430.94
0.0, 0.0, 1.0 ]
我找不到错误
//更新2
public CvMat rotateImage(float angle) {
CvPoint2D32f center = new CvPoint2D32f(input.cols() / 2.0F,
input.rows() / 2.0F);
CvBox2D box = new CvBox2D(center, cvSize2D32f(input.cols() - 1,
input.rows() - 1), angle);
CvPoint2D32f points = new CvPoint2D32f(4);
cvBoxPoints(box, points);
CvMat pointMat = cvCreateMat(1, 4, CV_32FC2);
pointMat.put(0, 0, 0, points.position(0).x());
pointMat.put(0, 0, 1, points.position(0).y());
pointMat.put(0, 1, 0, points.position(1).x());
pointMat.put(0, 1, 1, points.position(1).y());
pointMat.put(0, 2, 0, points.position(2).x());
pointMat.put(0, 2, 1, points.position(2).y());
pointMat.put(0, 3, 0, points.position(3).x());
pointMat.put(0, 3, 1, points.position(3).y());
CvRect boundingRect = cvBoundingRect(pointMat, 0);
CvMat dst = cvCreateMat(boundingRect.height(), boundingRect.width(),
input.type());
// CvPoint2D32f centerDst = new CvPoint2D32f(((dst.cols()-input.cols()
// )/ 2.0F),(( dst.rows()-input.rows()) / 2.0F));
CvMat rotMat = cvCreateMat(2, 3, CV_32F);
cv2DRotationMatrix(center, angle, 1, rotMat);
CvMat trans = cvCreateMat(3, 3, CV_32F);
cvZero(trans);
trans.put(0, 2, (dst.cols() - input.cols()) / 2.0F);
trans.put(1, 2, (dst.rows() - input.rows()) / 2.0F);
trans.put(0, 0, 1);
trans.put(1, 1, 1);
trans.put(2, 2, 1);
CvMat newRot = cvCreateMat(3, 3, CV_32F);
cvZero(newRot);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
newRot.put(i, j, rotMat.get(i, j));
}
}
newRot.put(2, 2, 1);
cvMul(trans, newRot, newRot, 1);
cvWarpPerspective(input, dst, newRot);
// cvWarpAffine(input, dst, rotMat);
System.out.println(rotMat);
System.out.println(trans);
System.out.println(newRot);
return dst;
在 1 度时,矩阵看起来像:
rotMat
:
[ 0.9998477, 0.017452406, -8.338219
-0.017452406, 0.9998477, 12.534734 ]
trans
[ 1.0, 0.0, -8.0
0.0, 1.0, -12.0
0.0, 0.0, 1.0 ]
newRot
[ 0.9998477, 0.0, 66.70575
-0.0, 0.9998477, -150.41681
0.0, 0.0, 1.0 ]
最终的
Hammer 指令的工作 JavaCode:
public CvMat rotateImage(float angle) {
CvPoint2D32f center = new CvPoint2D32f(input.cols() / 2.0F,
input.rows() / 2.0F);
CvBox2D box = new CvBox2D(center, cvSize2D32f(input.cols() - 1,
input.rows() - 1), angle);
CvPoint2D32f points = new CvPoint2D32f(4);
cvBoxPoints(box, points);
CvMat pointMat = cvCreateMat(1, 4, CV_32FC2);
pointMat.put(0, 0, 0, points.position(0).x());
pointMat.put(0, 0, 1, points.position(0).y());
pointMat.put(0, 1, 0, points.position(1).x());
pointMat.put(0, 1, 1, points.position(1).y());
pointMat.put(0, 2, 0, points.position(2).x());
pointMat.put(0, 2, 1, points.position(2).y());
pointMat.put(0, 3, 0, points.position(3).x());
pointMat.put(0, 3, 1, points.position(3).y());
CvRect boundingRect = cvBoundingRect(pointMat, 0);
CvMat dst = cvCreateMat(boundingRect.height(), boundingRect.width(),
input.type());
CvMat rotMat = cvCreateMat(2, 3, CV_32FC1);
cv2DRotationMatrix(center, angle, 1, rotMat);
double y_1 = ((boundingRect.width() - input.cols()) / 2.0F)
+ rotMat.get(0, 2);
double y_2 = ((boundingRect.height() - input.rows()) / 2.0F + rotMat
.get(1, 2));
rotMat.put(0, 2, y_1);
rotMat.put(1, 2, y_2);
cvWarpAffine(input, dst, rotMat);
return dst;
}