zoukankan      html  css  js  c++  java
  • 透视校正--鼠标沿着物体画4条线

    .pro

    QT -= gui
    
    CONFIG += c++11 console
    CONFIG -= app_bundle
    
    # The following define makes your compiler emit warnings if you use
    # any feature of Qt which as been marked deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    
    # You can also make your code fail to compile if you use deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    SOURCES += main.cpp 
        function.cpp
    
    
    OPENCV_ROOT_PATH = /home/yhl/software_install/opencv3.2
    
    
    INCLUDEPATH += $${OPENCV_ROOT_PATH}/include 
                   $${OPENCV_ROOT_PATH}/include/opencv 
                   $${OPENCV_ROOT_PATH}/include/opencv2
    
    
    
    LIBS += -L$${OPENCV_ROOT_PATH}/lib
    
    
    LIBS += -lopencv_core 
            -lopencv_highgui 
            -lopencv_imgproc 
            -lopencv_imgcodecs
    
    HEADERS += 
        function.h
    
    

    function.h

    #ifndef FUNCTION_H
    #define FUNCTION_H
    
    #include <iostream>
    #include "opencv2/opencv.hpp"
    #include "math.h"
    using namespace std;
    using namespace cv;
    
    
    double get_point_angle(CvPoint pointO,CvPoint pointA);
    
    double dis_pt(Point &pt1, Point &pt2);
    
    double get_ang(vector<Point> &v_pt);
    
    cv::Mat rotateImg(cv::Mat & img, double degree,cv::Mat &map_matrix);
    
    vector<Point> rot_pt(vector<Point> &v_pt,const cv::Mat &map_matrix);
    
    bool correct_(const vector<Point> &v_pt,cv::Mat &SrcImg,cv::Mat &m_MingP,bool b_debug);
    
    #endif // FUNCTION_H
    
    

    function.cpp

    #include "function.h"
    
    
    /************************************************************************
    *函数名:        get_point_angle
    *
    *函数作用:      已知2个坐标点,求从 0------->x 逆时针需旋转多少角度到该位置
    *
    *                   |
    *                   |
    *                   |
    *                   |
    *------------------------------------> x
    *                   | 0
    *                   |
    *                   |
    *                   |
    *                   v
    *                   y
    *
    *函数参数:
    *CvPoint2D32f pointO  - 起点
    *CvPoint2D32f pointA  - 终点
    *
    *函数返回值:
    *double         向量OA,从 0------->x 逆时针需旋转多少角度到该位置
    **************************************************************************/
    double get_point_angle(CvPoint pointO,CvPoint pointA)
    {
        double angle = 0;
        CvPoint point;
        double temp;
    
        point = cvPoint((pointA.x - pointO.x), (pointA.y - pointO.y));
    
        if ((0==point.x) && (0==point.y))
        {
            return 0;
        }
    
        if (0==point.x)
        {
            angle = 90;
            return angle;
        }
    
        if (0==point.y)
        {
            angle = 0;
            return angle;
        }
    
        temp = fabsf(float(point.y)/float(point.x));
        temp = atan(temp);
        temp = temp*180/CV_PI ;
    
        if ((0<point.x)&&(0<point.y))
        {
            angle = 360 - temp;
            return angle;
        }
    
        if ((0>point.x)&&(0<point.y))
        {
            angle = 360 - (180 - temp);
            return angle;
        }
    
        if ((0<point.x)&&(0>point.y))
        {
            angle = temp;
            return angle;
        }
    
        if ((0>point.x)&&(0>point.y))
        {
            angle = 180 - temp;
            return angle;
        }
    
        printf("sceneDrawing :: getAngle error!");
        return -1;
    }
    
    double dis_pt(Point &pt1, Point &pt2)
    {
        return (sqrt(pow(pt1.x-pt2.x,2) + pow(pt1.y-pt2.y,2)));
    }
    
    double get_ang(vector<Point> &v_pt)
    {
        if(v_pt.size()<1) { return 0;}
        double len_1 = dis_pt(v_pt[0],v_pt[1]);
        double len_2 = dis_pt(v_pt[2],v_pt[1]);
        double ang = 0.0;
        if(len_1 > len_2)
        {
            ang = get_point_angle(v_pt[0],v_pt[1]);
        }else
        {
            ang = get_point_angle(v_pt[2],v_pt[1]);
        }
        return ang;
    }
    
    cv::Mat rotateImg(cv::Mat & img, double degree,cv::Mat &map_matrix_1)
    {
        if (degree == 0)
        {
            cv::Mat m = img.clone();
            return m;
        }
    
        degree = -degree;
        double angle = degree  * 1.0 * CV_PI / 180.;
        double a = sin(angle), b = cos(angle);
        int width = img.cols;
        int height = img.rows;
        int width_rotate = int(height * fabs(a) + width * fabs(b));
        int height_rotate = int(width * fabs(a) + height * fabs(b));
    
        // [ m0  m1  m2 ] ===>  [ A11  A12   b1 ]
        // [ m3  m4  m5 ] ===>  [ A21  A22   b2 ]
        float map[6];
        //    cv::Mat map_matrix = cv::Mat(2, 3, CV_32F, map);
        Mat map_matrix = cv::Mat(2, 3, CV_32F, map);
    
        CvPoint2D32f center = cvPoint2D32f(width / 2, height / 2);
        CvMat map_matrix2 = map_matrix;
        cv2DRotationMatrix(center, degree, 1.0, &map_matrix2);
        map[2] += (width_rotate - width) / 2;
        map[5] += (height_rotate - height) / 2;
        cv::Mat img_rotate;
    
        warpAffine(img, img_rotate, map_matrix, cv::Size(width_rotate, height_rotate), 1, 0, 0);
        map_matrix_1 = map_matrix.clone();
        return img_rotate;
    }
    
    vector<Point> rot_pt(vector<Point> &v_pt,const cv::Mat &map_matrix)
    {
        std::cout<<"map_matrix="<<map_matrix<<std::endl;
        float *map = (float *)map_matrix.ptr<float>();
    
        vector<Point> v_pt2src;
        for(int i=0;i<v_pt.size();i++)
        {
            std::cout<<"src_pt="<<v_pt[i]<<std::endl;
            int x_t = v_pt[i].x;
            int y_t = v_pt[i].y;
            int x =  map[0]* x_t + map[1] * y_t + map[2];
            int y = map[3] * x_t + map[4] * y_t + map[5];
            v_pt2src.push_back(Point(x,y));
        }
        return v_pt2src;
    }
    
    //对矩形区域进行修正,防止图片越界
    void RoiCorrect(cv::Rect  &r, const cv::Mat &m)
    {
        if (r.x < 0) r.x = 0;
        if (r.y < 0) r.y = 0;
    
        if(r.x >= m.cols-1) r.x=0;
        if(r.y >= m.rows-1) r.y=0;
    
        if(r.width <= 0) r.width = 1;
        if(r.height <= 0) r.height = 1;
    
        if(r.x + r.width > m.cols - 1) r.width = m.cols - 1 - r.x;
        if(r.y + r.height > m.rows - 1) r.height = m.rows - 1 - r.y;
    }
    
    bool correct_(const vector<Point> &v_pt,cv::Mat &SrcImg,cv::Mat &m_out,bool b_debug)
    {
        //   0   2
        //   1   3
        cv::Point pt_tl,pt_bl,pt_tr, pt_br;
        pt_tl = v_pt[3];
        pt_bl = v_pt[2];
        pt_tr = v_pt[0];
        pt_br = v_pt[1];
    
        Mat m_src_correct;
        cv::Point2f src_pt[4];
        cv::Point2f dst_pt[4];
        src_pt[0] = pt_tl;
        src_pt[1] = pt_bl;
        src_pt[2] = pt_tr;
        src_pt[3] = pt_br;
        //    int height = DisPt2Pt(pt_tl,pt_bl);
        //    int width = DisPt2Pt(pt_tl,pt_tr);
        int T_1 = 0;
        int T_2 = 0;
        dst_pt[0] = cv::Point(MIN(src_pt[0].x,src_pt[1].x) - T_1,MIN(src_pt[0].y,src_pt[2].y));
        dst_pt[1] = cv::Point(MIN(src_pt[0].x,src_pt[1].x) -T_1,MAX(src_pt[1].y,src_pt[3].y));
        dst_pt[2] = cv::Point(MAX(src_pt[2].x,src_pt[3].x) + T_2,MIN(src_pt[0].y,src_pt[2].y));
        dst_pt[3] = cv::Point(MAX(src_pt[2].x,src_pt[3].x) + T_2,MAX(src_pt[1].y,src_pt[3].y));
    
        //    int T_1 = 0;
        //    int T_2 = 0;
        //    dst_pt[0] = cv::Point(MIN(src_pt[0].x,src_pt[1].x)-T_1,MIN(src_pt[0].y,src_pt[2].y));
        //    dst_pt[1] = cv::Point(dst_pt[0].x-T_1,dst_pt[0].y + height);
        //    dst_pt[2] = cv::Point(dst_pt[0].x+width+T_2,dst_pt[0].y);
        //    dst_pt[3] = cv::Point(dst_pt[0].x+width+T_2,dst_pt[0].y + height);
        int offset_x = (dst_pt[2].x - dst_pt[0].x) * 0.0;//0.05;
        int offset_y = (dst_pt[3].y - dst_pt[2].y) * 0;//0.05;
        Point ptout_tl(dst_pt[0].x-offset_x,dst_pt[0].y-offset_y);
        Point ptout_br(dst_pt[3].x+offset_x,dst_pt[3].y+offset_y);
        Rect roi_mingp = Rect(ptout_tl,ptout_br);
    
        cv::Mat warpMatrix = cv::getPerspectiveTransform(src_pt, dst_pt);
        cv::warpPerspective(SrcImg, m_src_correct, warpMatrix, SrcImg.size(), cv::INTER_NEAREST, cv::BORDER_CONSTANT);
        RoiCorrect(roi_mingp,m_src_correct);
        Mat m_MingP = m_src_correct(roi_mingp).clone();
        m_out = m_src_correct.clone();
        if(b_debug)
        {
            Mat m_show = m_src_correct.clone();
            rectangle(m_show,roi_mingp,Scalar(0,255,255),3);
            cv::namedWindow("correctSrcImg",cv::WINDOW_NORMAL);
            cv::imshow("correctSrcImg",SrcImg);
            cv::namedWindow("correctPic",cv::WINDOW_NORMAL);
            cv::imshow("correctPic",m_show);
            cv::namedWindow("correctRoi",cv::WINDOW_NORMAL);
            cv::imshow("correctRoi",m_MingP);
            waitKey(0);
        }
        return true;
    }
    

    main.cpp

    #include "function.h"
    
    void on_MouseHandle(int event, int x, int y, int flag, void* param);
    void DrawRectangle(Mat& img, Rect box);
    
    int cnt = 1;
    vector<Point> v_pt;
    Mat m_src_cp;
    /*****************鼠标操作*****************/
    Rect g_rect;
    bool g_DrawFlag = false;
    RNG g_rng(12345);
    Point pt_start,pt_end;
    void MouseEvent( Mat &srcImage )
    {
        //准备参数
        g_rect = Rect(-1, -1, 0, 0);
        //Mat srcImage(600, 600, CV_8UC3), tempImage;
        m_src_cp = srcImage.clone();
        Mat tempImage;
        srcImage.copyTo(tempImage);
        g_rect = Rect(-1, -1, 0, 0);
        //srcImage = Scalar::all(0);
    
        //设置鼠标操作回调函数
        namedWindow("Win");
        setMouseCallback("Win", on_MouseHandle, (void*)&srcImage);
    
        //绘画
        while (1)
        {
            srcImage.copyTo(tempImage);
            if (g_DrawFlag && 2 != cnt) {
                //DrawRectangle(tempImage, g_rect);
                line(tempImage,pt_start,pt_end,Scalar(g_rng.uniform(0, 255),
                                                      g_rng.uniform(0, 255), g_rng.uniform(0, 255)),2);
            }
    
            imshow("Win", tempImage);//imshow("Win", srcImage);//        imshow("Win", tempImage);
    
            //std::cout<<"v_pt_size="<<v_pt.size()<<std::endl;
    
            if (waitKey(10) == 27) break;//ESC 退出
        }
    }
    //鼠标回调事件
    void on_MouseHandle(int event, int x, int y, int flag, void* param)
    {
        Mat& image = *(Mat*)param;
        switch (event)
        {
        case EVENT_MOUSEMOVE://移动
            if (g_DrawFlag) {
                pt_end = Point(x,y);
                cnt += 1;
            }
            break;
        case EVENT_LBUTTONDOWN://左键按下
            g_DrawFlag = true;
            //设置g_rect的初始值在同一个点
            //g_rect = Rect(x, y, 0, 0);
    
            if(1 == cnt)
            {
                pt_start = Point(x,y);
            }else
            {
                pt_start = pt_end;
            }
            cnt += 1;
            break;
        case EVENT_LBUTTONUP://左键抬起
            g_DrawFlag = false;
            v_pt.push_back(pt_end);
            line(image,pt_start,pt_end,Scalar(g_rng.uniform(0, 255),
                                              g_rng.uniform(0, 255), g_rng.uniform(0, 255)),2);
            break;
        }
    }
    //矩形绘制函数
    void DrawRectangle(Mat& img, Rect box)
    {
        //rectangle画矩形
        //tl左上角的点,br右下角的点
        //Scalar设置颜色,设置为3通道
        //g_rng.uniform(0, 255)随机颜色
        rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0, 255),
                                                  g_rng.uniform(0, 255), g_rng.uniform(0, 255)));
    }
    
    
    int main(int argc, char *argv[])
    {
        Mat srcImage = imread("/home/yhl/下载/1113_1.jpg");
        MouseEvent(srcImage);
    
        double ang = get_ang(v_pt);
        Mat map_matrix = cv::Mat(2, 3, CV_32F);
        Mat m_rot = rotateImg(m_src_cp,ang,map_matrix);
        vector<Point> v_pt_rot = rot_pt(v_pt,map_matrix);
        cv::Mat m_out;
        bool b_debug = false;
        correct_(v_pt_rot,m_rot,m_out,b_debug);
    
        namedWindow("perspective",0);
        imshow("perspective",m_out);
        waitKey(0);
        return 0;
    }
    
  • 相关阅读:
    WPF:简洁为美
    WPF工作笔记:本地化支持、主进程通知、两种最常用异步编程方式
    WPF:将HTML RGB颜色值转化为Color对象的两种方式
    WPF:定制Checkbox样式,让“正确”绿得好看,让“错误”红的显眼
    Is C# a clone of a Microsoft replacement for Java?
    原创的基于HTML/CSS/JavaScript的层级目录树
    Android笔记——BaseAdapter的使用
    C#开源持久层框架
    经典.net面试题目
    C#:实体框架EF(entity framework)
  • 原文地址:https://www.cnblogs.com/yanghailin/p/11855614.html
Copyright © 2011-2022 走看看