Je veux faire pivoter des images avec un angle variable (comme 22°) dans JavaCV/OpenCV. Pour l'instant, j'utilise cvWarpAffine()
.
Mon problème est que je perds les bords de l'image après la rotation, je dois donc agrandir l'image dst.et déplacer le point central. Sur cette page J'ai trouvé un code AS pour calculer la nouvelle taille de l'image. Mais je ne sais pas comment le réaliser avec JavaCV/OpenCV.
Dans le temps, j'ai le code suivant :
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;
}
Quelqu'un a une idée ?
Salutations
//Mise à jour
Je ne sais pas... quelque chose ne va pas. Si je calcule l'image tournée, mon résultat a la bonne dimension, mais il est surtout noir (0 et 360° fonctionnent)... Voici le code :
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;
}
En rotMat
ressemble :
[ 0.9396926, 0.34202015, -311.1334
-0.34202015, 0.9396926, 601.47485 ]
En trans
(l'image d'org. a une taille de 1428x928px) :
[ 1.0, 0.0, 836.0
0.0, 1.0, 699.0
0.0, 0.0, 1.0 ]
et le newRot
[ 0.9396926, 0.0, -260107.52
-0.0, 0.9396926, 420430.94
0.0, 0.0, 1.0 ]
Je n'arrive pas à trouver l'erreur
//Mise à jour 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;
A 1 degré, la matrice ressemble à :
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 ]
FINAL
JavaCode de travail de l'instruction de Hammer :
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;
}