Артефакты вращения OpenCV и переназначение точек

Я пытаюсь достичь следующей цели:

1) Определить характерные точки на изображении и сохранить их в массив

2) Скопируйте и поверните оригинальное изображение

3) Определить точки на повернутом изображении

4) «Повернуть» (преобразовать) исходное изображение обнаруженных точек под тем же углом (матрицей), что и исходное изображение

5) Изучите надежность методов, используя вращение (проверьте, сколько признаков повернутого изображения соответствуют преобразованным признакам исходного изображения)

На самом деле мои проблемы начинаются с шага 2: когда я пытаюсь повернуть четное квадратное изображение на угол -90 (кстати, мне нужно 45 для моей задачи), я получаю несколько черных / блеклых границ, и получается изображение размером 202×203, в то время как оригинал 201×201:
-90 повернутое изображение артефактов

Код, который я использую для поворота Mat:

- (Mat)rotateImage:(Mat)imageMat angle:(double)angle {

// get rotation matrix for rotating the image around its center
cv::Point2f center(imageMat.cols/2.0, imageMat.rows/2.0);
cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0);

// determine bounding rectangle
cv::Rect bbox = cv::RotatedRect(center,imageMat.size(), angle).boundingRect();

// adjust transformation matrix
rot.at<double>(0,2) += bbox.width/2.0 - center.x;
rot.at<double>(1,2) += bbox.height/2.0 - center.y;

cv::Mat dst;
cv::warpAffine(imageMat, dst, rot, bbox.size());
return dst;
}

от https://stackoverflow.com/a/24352524/1286212

Также я попробовал это с тем же результатом: https://stackoverflow.com/a/29945433/1286212

И следующая проблема с вращением точек, я использую этот код для преобразования исходных объектов на тот же угол (-90):

- (std::vector<cv::Point>)transformPoints:(std::vector<cv::Point>)featurePoints fromMat:(Mat)imageMat angle:(double)angle {
cv::Point2f center(imageMat.cols/2.0, imageMat.rows/2.0);
cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0);
std::vector<cv::Point> dst;
cv::transform(featurePoints, dst, rot);
return dst;
}

И я не могу определить, работает ли он так, как я ожидаю, из-за неправильно повернутого изображения, я сделал пример, чтобы показать, о чем я говорю:

    cv::Mat testMat(3, 3, CV_8UC3, cv::Scalar(255,0,0));
testMat.at<Vec3b>(cv::Point(0,1)) = Vec3b(0, 255, 0);

for(int i = 0; i < testMat.rows; i++) {
for(int j = 0; j < testMat.cols; j++) {
Vec3b color = testMat.at<Vec3b>(cv::Point(i,j));
NSLog(@"Pixel (%d, %d) color = (%d, %d, %d)", i, j, color[0], color[1], color[2]);
}
}

std::vector<cv::Point> featurePoints1;
std::vector<cv::Point> featureRot;
cv::Point featurePoint = cv::Point( 0, 1 );
featurePoints1.push_back(featurePoint);
cv::Mat rotated = [self rotateImage:testMat angle:-90];
featureRot = [self transformPoints:featurePoints1 fromMat:testMat angle:90];for(int i = 0; i < rotated.rows; i++) {
for(int j = 0; j < rotated.cols; j++) {
Vec3b color = rotated.at<Vec3b>(cv::Point(i,j));
NSLog(@"Pixel (%d, %d) color = (%d, %d, %d)", i, j, color[0], color[1], color[2]);
}
}

Оба мата (testMat и повернутый) должны быть 3х3, а второй 4х5. И этот зеленый пиксель должен быть переведен из (0, 1) в (1, 2) с поворотом на -90. Но на самом деле с помощью transformPoints:fromMat:angle: Метод это (1, 3) (из-за неправильных размеров в повернутом изображении, я думаю). Вот журналы для оригинального изображения:

Pixel (0, 0) color = (255, 0, 0)
Pixel (0, 1) color = (0, 255, 0)
Pixel (0, 2) color = (255, 0, 0)
Pixel (1, 0) color = (255, 0, 0)
Pixel (1, 1) color = (255, 0, 0)
Pixel (1, 2) color = (255, 0, 0)
Pixel (2, 0) color = (255, 0, 0)
Pixel (2, 1) color = (255, 0, 0)
Pixel (2, 2) color = (255, 0, 0)

И для повернутого:

Pixel (0, 0) color = (0, 0, 0)
Pixel (0, 1) color = (0, 0, 0)
Pixel (0, 2) color = (0, 0, 0)
Pixel (0, 3) color = (0, 0, 0)
Pixel (0, 4) color = (255, 127, 0)
Pixel (1, 0) color = (0, 0, 0)
Pixel (1, 1) color = (0, 0, 0)
Pixel (1, 2) color = (0, 0, 0)
Pixel (1, 3) color = (0, 0, 0)
Pixel (1, 4) color = (0, 71, 16)
Pixel (2, 0) color = (128, 0, 0)
Pixel (2, 1) color = (255, 0, 0)
Pixel (2, 2) color = (255, 0, 0)
Pixel (2, 3) color = (128, 0, 0)
Pixel (2, 4) color = (91, 16, 0)
Pixel (3, 0) color = (0, 128, 0)
Pixel (3, 1) color = (128, 128, 0)
Pixel (3, 2) color = (255, 0, 0)
Pixel (3, 3) color = (128, 0, 0)
Pixel (3, 4) color = (0, 0, 176)

Как видите, цвета пикселей тоже искажены. Что я делаю неправильно или недоразумение?

UPD решено:

1) Вы должны использовать boundingRect2f() вместо boundingRect() не потерять точность с плавающей точкой и получить правильную ограничивающую рамку

2) Вы должны получить свой центр как cv::Point2f center(imageMat.cols/2.0f - 0.5f, imageMat.rows/2.0 - 0.5f) получить актуальный индексированный по пикселям центр (понятия не имею, почему каждый ответ на SO имеет неверный центр реализации)

1

Решение

использование boundingRect2f вместо boundingRect , boundingRect2f использует целочисленные значения. Это теряет точность.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector