Вращение обратных точек с повернутого изображения в OpenCV

У меня возникают проблемы с вращением. Я хочу сделать следующее:

  • Поворот изображения
  • Обнаружение функций на повернутом изображении (точках)
  • Поверните назад точки, чтобы я мог иметь координаты точек, соответствующие исходному изображению

Я немного застрял на третьем шаге.

Мне удалось повернуть изображение с помощью следующего кода:

cv::Mat M(2, 3, CV_32FC1);
cv::Point2f center((float)dst_img.rows / 2.0f, (float)dst_img.cols / 2.0f);
M = cv::getRotationMatrix2D(center, rotateAngle, 1.0);
cv::warpAffine(dst_img, rotated, M, cv::Size(rotated.cols, rotated.rows));

Я пытаюсь повернуть назад точки с помощью этого кода:

float xp = r.x * std::cos( PI * (-rotateAngle) / 180 ) - r.y * sin(PI * (rotateAngle) / 180);
float yp = r.x * sin(PI * (-rotateAngle) / 180) + r.y * cos(PI * (rotateAngle) / 180);

Это не значит, что вы работаете, но точки не возвращаются на изображение. Существует смещение.

Спасибо за помощь

Ответ 1

Если M - матрица вращения, которую вы получаете от cv::getRotationMatrix2D, чтобы повернуть a cv::Point p с помощью этой матрицы, вы можете сделать это:

cv::Point result;
result.x = M.at<double>(0,0)*p.x + M.at<double>(0,1)*p.y + M.at<double>(0,2);
result.y = M.at<double>(1,0)*p.x + M.at<double>(1,1)*p.y + M.at<double>(1,2);

Если вы хотите повернуть точку назад, сгенерируйте обратную матрицу M или используйте cv::getRotationMatrix2D(center, -rotateAngle, scale) для создания матрицы для обратного вращения.

Ответ 2

Для матрицы вращения ее транспонирование является ее обратной. Таким образом, вы можете просто сделать M.t() * r, чтобы переместить его обратно в исходный кадр, где r - это cv::Mat (вам, возможно, придется преобразовать его в cv::Mat из cv::Point2f или как угодно, или просто записать матричное умножение явно).

Здесь код, чтобы сделать это явно (должен быть правильным, но предупреждение, он полностью не проверен):

cv::Point2f p;
p.x = M.at<float>(0, 0) * r.x + M.at<float>(1, 0) * r.y;
p.y = M.at<float>(0, 1) * r.x + M.at<float>(1, 1) * r.y;
// p contains r rotated back to the original frame.

Ответ 3

У меня была та же проблема.

Для преобразования M и точки pp во вращающемся изображении мы хотим найти точку pp_org в координатах исходного изображения. Используйте следующие строки:

cv::Mat_<double> iM;
cv::invertAffineTransform(M, iM);
cv::Point2f pp_org = iM*pp;

Если оператор * в приведенной выше строке определяется как:

cv::Point2f operator*(cv::Mat_<double> M, const cv::Point2f& p)
{ 
    cv::Mat_<double> src(3/*rows*/,1 /* cols */); 

    src(0,0)=p.x; 
    src(1,0)=p.y; 
    src(2,0)=1.0; 

    cv::Mat_<double> dst = M*src; //USE MATRIX ALGEBRA 
    return cv::Point2f(dst(0,0),dst(1,0)); 
} 

Примечание. M - это матрица вращения, которую вы использовали для перехода от оригинала к повернутому изображению.

Ответ 4

  • Вам нужно повернуть точки, относящиеся к центральной точке вашего изображения.
  • Здесь x и y - ваши точки, которые вы хотите повернуть, imageCenter_x aand _y - это центральная точка вашего изображения.
  • Ниже мой код.

    angle = angle * (M_PI / 180);  
    float axis_x = x - imageCenter_x;  
    float axis_y = y - imageCenter_y;       
    
    x = axis_x * cos(angle) + axis_y * sin(angle);   
    y = (-axis_x) * sin(angle) + axis_y * cos(angle);
    
    x = x + imageCenter_x;  
    y = y + imageCenter_y;