基本思想:opencv仿射变换不是太准,存在于嵌套仿射的情况,存在这样的问题,在角点的四个外围坐标仿射为正向坐标之后,通过仿射矩阵M去计算内部存在的嵌套矩形框,计算存在偏差,同时以截图为遮挡,仿射的外围四个角点还是存在误差的,需要添加平移参数调整
代码存在问题,我将大框画在了第一个,需要调整代码,先假设数组的第一个框为大框
情况一:
测试图片
测试代码
- #include<iostream>
- #include<opencv2/opencv.hpp>
-
- using namespace std;
- using namespace cv;
-
- double EuDis(Point pt1, Point pt2) {
- return sqrt((pt2.x - pt1.x) * (pt2.x - pt1.x) + (pt2.y - pt1.y) * (pt2.y - pt1.y));
- }
-
-
- int main() {
-
- Mat src = imread("../demo.jpg");
- Mat src_clone=src.clone();
- vector<vector<Point>> contours;
- std::vector<Point> item;
- item.emplace_back(cv::Point(363, 62));
- item.emplace_back(cv::Point(765, 199));
- item.emplace_back(cv::Point(505, 659));
- item.emplace_back(cv::Point(62, 507));
- contours.emplace_back(item);
- item.clear();
-
- item.emplace_back(cv::Point(378, 290));
- item.emplace_back(cv::Point(456, 252));
- item.emplace_back(cv::Point(491, 295));
- item.emplace_back(cv::Point(417, 332));
- contours.emplace_back(item);
- item.clear();
-
- for(int i=0;i<contours.size();i++){
- for(int j=0;j<contours[i].size();j++){
- circle(src, cv::Point(contours[i][j].x, contours[i][j].y), 10, Scalar(255, 0, 0), -1);
- if(j!=contours[i].size()-1){
- line(src, cv::Point(contours[i][j].x, contours[i][j].y), cv::Point(contours[i][j+1].x, contours[i][j+1].y), Scalar(255, 0, 0),2, LINE_8);
- }else {
- line(src, cv::Point(contours[i][j].x, contours[i][j].y), cv::Point(contours[i][0].x, contours[i][0].y), Scalar(255, 0, 0),2, LINE_8);
-
- }
- }
- }
-
-
- vector<Point> srcPts;
-
-
- double new_area = 0;
- for (int i = 0; i < contours.size(); i++) {
- double area = contourArea(contours[i]);
-
- if (area > new_area) {
- srcPts = {contours[i][0], contours[i][1], contours[i][2], contours[i][3]};
- new_area = area;
- }
- }
-
-
-
- double LeftHeight = EuDis(srcPts[0], srcPts[3]);
- double RightHeight = EuDis(srcPts[1], srcPts[2]);
- double MaxHeight = max(LeftHeight, RightHeight);
-
- double UpWidth = EuDis(srcPts[0], srcPts[1]);
- double DownWidth = EuDis(srcPts[2], srcPts[3]);
- double MaxWidth = max(UpWidth, DownWidth);
-
- Point2f SrcAffinePts[4] = {Point2f(srcPts[0]), Point2f(srcPts[1]), Point2f(srcPts[2]), Point2f(srcPts[3])};
- Point2f DstAffinePts[4] = {Point2f(0, 0), Point2f(MaxWidth, 0), Point2f(MaxWidth, MaxHeight),
- Point2f(0, MaxHeight)};
-
- Mat M = getPerspectiveTransform(SrcAffinePts, DstAffinePts);
-
- Mat DstImg;
-
- warpPerspective(src_clone, DstImg, M, Point(MaxWidth,MaxHeight));
- std::cout << M << std::endl;
- float a00 = M.at<cv::Vec3d>(0, 0)[0];
- float a01 = M.at<cv::Vec3d>(0, 0)[1];
- float a02 = M.at<cv::Vec3d>(0, 0)[2];
- float a10 = M.at<cv::Vec3d>(1, 0)[0];
- float a11 = M.at<cv::Vec3d>(1, 0)[1];
- float a12 = M.at<cv::Vec3d>(1, 0)[2];
- float a20 = M.at<cv::Vec3d>(2, 0)[0];
- float a21 = M.at<cv::Vec3d>(2, 0)[1];
- float a22 = M.at<cv::Vec3d>(2, 0)[2];
- //cosx siny tx a00 a01 a02
- //-sinx cosy ty a10 a11 a12
- //0 0 1 a20 a21 a22
- //矫正畸变不准 需要调整包含物体的坐标
- int cof=5;
- std::vector<std::vector<cv::Point>> new_contours;
- for (int i = 0; i < contours.size(); i++) {
- std::vector<cv::Point> item;
- double new_x=0;
- double new_y=0;
- for (int j = 0; j < contours[i].size(); j++) {
- if(i==0){
- new_x=DstAffinePts[j].x;
- new_y=DstAffinePts[j].y;
-
- }else {
- new_x = contours[i][j].x * a00+ contours[i][j].y * a01 + a02-cof;
- new_y = contours[i][j].x * a10 + contours[i][j].y * a11 + a12-4;
- }
- item.emplace_back(cv::Point(new_x, new_y));
-
-
-
- }
-
- new_contours.emplace_back(item);
- }
-
-
-
-
- for(int i=0;i<new_contours.size();i++){
- for(int j=0;j<new_contours[i].size();j++){
- circle(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), 10, Scalar(0, 0, 255), -1);
- if(j!=new_contours[i].size()-1){
- line(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), cv::Point(new_contours[i][j+1].x, new_contours[i][j+1].y), Scalar(0, 0, 255),2, LINE_8);
- }else {
- line(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), cv::Point(new_contours[i][0].x, new_contours[i][0].y), Scalar(0, 0, 255),2, LINE_8);
-
- }
- }
- }
-
- imshow("Dst", DstImg);
-
-
-
-
-
-
-
-
- imshow("src", src);
- waitKey(0);
- destroyAllWindows();
-
- return 0;
- }
-
测试结果
情况二:测试图片
测试代码
- #include<iostream>
- #include<opencv2/opencv.hpp>
-
- using namespace std;
- using namespace cv;
-
- double EuDis(Point pt1, Point pt2) {
- return sqrt((pt2.x - pt1.x) * (pt2.x - pt1.x) + (pt2.y - pt1.y) * (pt2.y - pt1.y));
- }
-
-
- int main() {
-
- Mat src = imread("../Selection_017.png");
- Mat src_clone=src.clone();
- vector<vector<Point>> contours;
- std::vector<Point> item;
- item.emplace_back(cv::Point(87, 143));
- item.emplace_back(cv::Point(548, 147));
- item.emplace_back(cv::Point(601, 364));
- item.emplace_back(cv::Point(54, 362));
- contours.emplace_back(item);
- item.clear();
-
- item.emplace_back(cv::Point(252, 247));
- item.emplace_back(cv::Point(398, 246));
- item.emplace_back(cv::Point(402, 269));
- item.emplace_back(cv::Point(249, 269));
- contours.emplace_back(item);
- item.clear();
- item.emplace_back(cv::Point(441, 208));
- item.emplace_back(cv::Point(441, 233));
- item.emplace_back(cv::Point(478, 232));
- item.emplace_back(cv::Point(474, 208));
- contours.emplace_back(item);
- item.clear();
-
-
-
- item.emplace_back(cv::Point(155, 223));
- item.emplace_back(cv::Point(155, 246));
- item.emplace_back(cv::Point(192, 245));
- item.emplace_back(cv::Point(193, 222));
- contours.emplace_back(item);
- item.clear();
-
-
- for(int i=0;i<contours.size();i++){
- for(int j=0;j<contours[i].size();j++){
- circle(src, cv::Point(contours[i][j].x, contours[i][j].y), 10, Scalar(255, 0, 0), -1);
- if(j!=contours[i].size()-1){
- line(src, cv::Point(contours[i][j].x, contours[i][j].y), cv::Point(contours[i][j+1].x, contours[i][j+1].y), Scalar(255, 0, 0),2, LINE_8);
- }else {
- line(src, cv::Point(contours[i][j].x, contours[i][j].y), cv::Point(contours[i][0].x, contours[i][0].y), Scalar(255, 0, 0),2, LINE_8);
-
- }
- }
- }
-
-
- vector<Point> srcPts;
-
-
- double new_area = 0;
- for (int i = 0; i < contours.size(); i++) {
- double area = contourArea(contours[i]);
-
- if (area > new_area) {
- srcPts = {contours[i][0], contours[i][1], contours[i][2], contours[i][3]};
- new_area = area;
- }
- }
-
-
-
- double LeftHeight = EuDis(srcPts[0], srcPts[3]);
- double RightHeight = EuDis(srcPts[1], srcPts[2]);
- double MaxHeight = max(LeftHeight, RightHeight);
-
- double UpWidth = EuDis(srcPts[0], srcPts[1]);
- double DownWidth = EuDis(srcPts[2], srcPts[3]);
- double MaxWidth = max(UpWidth, DownWidth);
-
- Point2f SrcAffinePts[4] = {Point2f(srcPts[0]), Point2f(srcPts[1]), Point2f(srcPts[2]), Point2f(srcPts[3])};
- Point2f DstAffinePts[4] = {Point2f(0, 0), Point2f(MaxWidth, 0), Point2f(MaxWidth, MaxHeight),
- Point2f(0, MaxHeight)};
-
- Mat M = getPerspectiveTransform(SrcAffinePts, DstAffinePts);
-
- Mat DstImg;
-
- warpPerspective(src_clone, DstImg, M, Point(MaxWidth,MaxHeight));
- std::cout << M << std::endl;
- float a00 = M.at<cv::Vec3d>(0, 0)[0];
- float a01 = M.at<cv::Vec3d>(0, 0)[1];
- float a02 = M.at<cv::Vec3d>(0, 0)[2];
- float a10 = M.at<cv::Vec3d>(1, 0)[0];
- float a11 = M.at<cv::Vec3d>(1, 0)[1];
- float a12 = M.at<cv::Vec3d>(1, 0)[2];
- float a20 = M.at<cv::Vec3d>(2, 0)[0];
- float a21 = M.at<cv::Vec3d>(2, 0)[1];
- float a22 = M.at<cv::Vec3d>(2, 0)[2];
- //cosx siny tx a00 a01 a02
- //-sinx cosy ty a10 a11 a12
- //0 0 1 a20 a21 a22
- //矫正畸变不准 需要调整包含物体的坐标
- int cof=25;
- std::vector<std::vector<cv::Point>> new_contours;
- for (int i = 0; i < contours.size(); i++) {
- std::vector<cv::Point> item;
- double new_x=0;
- double new_y=0;
- for (int j = 0; j < contours[i].size(); j++) {
- if(i==0){
- new_x=DstAffinePts[j].x;
- new_y=DstAffinePts[j].y;
-
- }else {
- new_x = contours[i][j].x * a00+ contours[i][j].y * a01 + a02-cof;
- new_y = contours[i][j].x * a10 + contours[i][j].y * a11 + a12-cof;
- }
- item.emplace_back(cv::Point(new_x, new_y));
-
-
-
- }
-
- new_contours.emplace_back(item);
- }
-
-
-
-
- for(int i=0;i<new_contours.size();i++){
- for(int j=0;j<new_contours[i].size();j++){
- circle(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), 10, Scalar(0, 0, 255), -1);
- if(j!=new_contours[i].size()-1){
- line(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), cv::Point(new_contours[i][j+1].x, new_contours[i][j+1].y), Scalar(0, 0, 255),2, LINE_8);
- }else {
- line(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), cv::Point(new_contours[i][0].x, new_contours[i][0].y), Scalar(0, 0, 255),2, LINE_8);
-
- }
- }
- }
- cv::imwrite("dst.jpg",DstImg);
- imshow("Dst", DstImg);
-
-
-
-
-
-
- cv::imwrite("src.jpg",src);
-
- imshow("src", src);
- waitKey(0);
- destroyAllWindows();
-
- return 0;
- }
-
测试结果
原图
仿射之后