天天看點

25、opencv的仿射變換

基本思想:opencv仿射變換不是太準,存在于嵌套仿射的情況,存在這樣的問題,在角點的四個外圍坐标仿射為正向坐标之後,通過仿射矩陣M去計算内部存在的嵌套矩形框,計算存在偏差,同時以截圖為遮擋,仿射的外圍四個角點還是存在誤差的,需要添加平移參數調整

情況一:

測試圖檔

25、opencv的仿射變換

測試代碼

#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;
}      

測試結果

25、opencv的仿射變換
25、opencv的仿射變換

情況二:測試圖檔

25、opencv的仿射變換

 測試代碼

#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;
}      

測試結果

原圖

繼續閱讀