opencv裁剪旋转矩阵区域
0.引言
纯代码.
- 主要参考博客
1.透视变换
- 1.计算旋转矩形。
- 2.基于矩形的四个顶点和想要抠出的正矩形的四个顶点得到一个变换矩阵。
- 3.通过透视变换,将四个点组成的平面转换成另四个点组成的一个平面,以此抠出正矩形。
#include
#include
#include using namespace cv;
using namespace std;int main() {Mat img = imread("../test.png");// 定义旋转矩形区域的中心点、宽度、高度和旋转角度Point2f center(150, 215);float width = 190;float height = 150;float angle = 30;// 计算旋转矩形的四个顶点坐标float radians = angle * CV_PI / 180.0;float cos_angle = cos(radians);float sin_angle = sin(radians);vector<Point2f> src_pts;src_pts.push_back(Point2f(-width / 2, -height / 2));src_pts.push_back(Point2f(width / 2, -height / 2));src_pts.push_back(Point2f(width / 2, height / 2));src_pts.push_back(Point2f(-width / 2, height / 2));for (int i = 0; i < 4; i++) {float x = src_pts[i].x * cos_angle - src_pts[i].y * sin_angle + center.x;float y = src_pts[i].x * sin_angle + src_pts[i].y * cos_angle + center.y;if (x < 0 || y < 0 || x >= img.cols || y >= img.rows) {std::cout << "vertex point out of range.";return;}src_pts[i] = Point2f(x, y);}// 定义裁剪后输出的图像大小int output_width = 200;int output_height = 150;// 定义目标图像的四个点vector<Point2f> dst_pts;dst_pts.push_back(Point2f(0, 0));dst_pts.push_back(Point2f(output_width - 1, 0));dst_pts.push_back(Point2f(output_width - 1, output_height - 1));dst_pts.push_back(Point2f(0, output_height - 1));// 计算透视变换矩阵Mat M = getPerspectiveTransform(src_pts, dst_pts);// 应用透视变换Mat output_img;warpPerspective(img, output_img, M, Size(output_width, output_height));// 显示结果imshow("Original Image", img);imshow("Output Image", output_img);waitKey(0);return 0;
}


- 图自
2.仿射变换
- 1.计算旋转矩形。
- 2.基于旋转矩形的中心和角度计算得到一个变换矩阵。
- 3.以旋转矩形的中心为基准点,对整张图进行旋转,这里旋转的实现是基于仿射变换实现的。
由于旋转之后矩形的中点坐标是不变的,以中心为基础,通过width和height抠出正矩形。
#include
#include using namespace cv;
using namespace std;int main()
{// 读取输入图像Mat img = imread("../test.png");// 定义旋转矩形区域RotatedRect rect(Point2f(300, 300), Size2f(200, 100), 45);// 计算旋转矩形的仿射变换矩阵Mat M = getRotationMatrix2D(rect.center, rect.angle, 1.0);// 旋转图像Mat rotated;warpAffine(img, rotated, M, img.size(), INTER_CUBIC);// 裁剪旋转矩形区域Mat cropped;getRectSubPix(rotated, rect.size, rect.center, cropped);// 显示结果imshow("Input", img);imshow("Cropped and Rotated", cropped);waitKey(0);return 0;
}


- 图自
3.总结
- 仿射变换方法需要预先对整张图进行旋转,通过观察旋转后的图像可以发现,有一部分图像被旋转出了图像边界,如果你要抠取的目标正好在图像边缘附近,那么很容易出界导致图像抠取的缺失。同时需要对宽、高和角度做出动态的调整;
- 透视变换的方法直接对抠取区域进行了映射,这种方法可以省略旋转的步骤,并且不会出现抠取内容的缺失。同时只需要对4个顶点之间的映射关系做好定义即可,不需要考虑角度的问题。
- 相对的,透视变换相对于仿射变换计算量更大一些,不过这在c++的底层实现上带来的时延差距小于ms。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
