文章目录
前言
在工业领域进行目标检测的时候,可能会需要先对图像进行旋转校正、多幅图像拼接等操作。这就需要我们将检测到的目标坐标映射到处理后的图像上。下面说几种OpenCV下常用的坐标变换计算,旋转、缩放、翻转和仿射变换,完全同步对应OpenCV的图像处理操作。
一、旋转+缩放+翻转
代码展示的是主要逻辑,稍微改一改就可以用到项目里去。m_img是原图,m_src_corners是你需要转换的原图中的坐标集合。
Mat image = m_img;
cv::Point2f center((float(image.cols / resize_scale / 2)), (float)(image.rows / resize_scale / 2));
cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1); //获得图像绕中心点旋转angle角度的旋转矩阵 R2*3
cv::Rect bbox = cv::RotatedRect(center, Size(image.cols / resize_scale, image.rows / resize_scale), angle).boundingRect();//返回包含旋转矩形的最小矩形
rot.at<double>(0, 2) += bbox.width / 2.0 - center.x; //x方向的偏移量Tx
rot.at<double>(1, 2) += bbox.height / 2.0 - center.y; //y方向的偏移量Ty
m_rot_trans = rot;
m_dx = bbox.width / 2 - center.x;
m_dy = bbox.height / 2 - center.y;
for (auto& pt : m_src_corners)
{
Mat p = Mat::ones(3, 1, CV_64F);
p.at<double>(0) = pt.x / resize_scale;
p.at<double>(1) = pt.y / resize_scale;
Mat pp = m_rot_trans * p;
p.at<double>(0) = pp.at<double>(0) - m_dx;
p.at<double>(1) = pp.at<double>(1) - m_dy;
if (flip_code == FLIP_X)
{
p.at<double>(1) = image.rows / resize_scale - p.at<double>(1);
} else if (flip_code == FLIP_Y)
{
p.at<double>(0) = image.cols / resize_scale - p.at<double>(0);
} else if (flip_code == FLIP_BOTH)
{
p.at<double>(0) = image.cols / resize_scale - p.at<double>(0);
p.at<double>(1) = image.rows / resize_scale - p.at<double>(1);
}
Point2f dst_pt;
dst_pt.x = p.at<double>(0);
dst_pt.y = p.at<double>(1);
m_dst_corners.push_back(dst_pt);
}
二、仿射变换
需要注意的是仿射变换需要除以z
Mat p = Mat::ones(3, 1, CV_64F);
p.at<double>(0) = pt.x;
p.at<double>(1) = pt.y;
Mat pp = trans * p;
Point2f result;
result.x = pp.at<double>(0) / pp.at<double>(2);
result.y = pp.at<double>(1) / pp.at<double>(2);