美文网首页OpenCV
OpenCV编写截图程序_&&_鼠标事件

OpenCV编写截图程序_&&_鼠标事件

作者: SIENTIST | 来源:发表于2018-08-19 17:41 被阅读0次

    环境:OpenCV3.2.0,VS2013,Windows7。
    语言:C++
    我需要截取样本作机器学习数据的训练,不但要能方便截图,而且截取的图片必须是固定的尺寸,这样的软件不好找,于是我便打算自己编写一个。
    效果如下:可以看到,图片中所有的矩形框都是1:1的正方形!也就是说,我的截图程序,能把截图时鼠标拖动的矩形自动变为正方形,而且最重要的是,自动变化的矩形框尺寸不会超出图像尺寸。
    这个程序有如下3个难点:鼠标事件的变化; 自动变化的尺寸不超出图像尺寸;需要考虑到鼠标从上往下、从下往上、从左向右、从右向左 等多种拖动方式


    图片.png

    感悟:
    1、程序一定要考虑到图像的尺寸,不能超出图像的尺寸,否则程序就会出错。 尺寸可以把 长(cols)、 宽(rows)分开考虑,这两个值是独立的,如果把他们综合在一起思考容易把自己搞糊涂。

    代码如下:

    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/opencv.hpp>
    #include <iostream>
    #include <string>
    #include <ctime>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include <direct.h>  //windows下C++创建文件夹头文件
    //#include <stdlib.h> //srand()和rand()函数  
    //#include <time.h>
    
    using namespace cv;
    using namespace std;
    
    
    // global variable
    static Mat g_img_src;
    static Mat g_img_dst;
    static Mat g_imgMouseMove;
    static Mat g_img_Cut;
    static bool g_MouseDown_flag = false;
    static Point g_startPoint;
    static string g_window_name = "image";
    
    int P = 0; //图像缩放比例
    
    
    static void onMouse(int event, int x, int y, int, void*)
    {
        if (CV_EVENT_LBUTTONDOWN == event){  //按下鼠标事件
            g_MouseDown_flag = true;  //方框标志位置为真
            g_startPoint = Point(x, y);  //记录下方框的起始位置
        }
        else if (CV_EVENT_MOUSEMOVE == event && g_MouseDown_flag){ //拖动鼠标事件
    
            //  rectangle(Mat& img,   Point pt1,   Point pt2,   const Scalar& color,   int thickness=1,   int lineType=8,   int shift=0)
            //  img 图像;      
            //  pt1 矩形的一个顶点;           
            //  pt2 矩形对角线上的另一个顶点;     
            //  color 线条颜色(RGB) 或亮度(灰度图像 )(grayscale image)。
            //  thickness 组成矩形的线条的粗细程度,取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
            //  line_type 线条的类型,见cvLine的描述;              
            //  shift 坐标点的小数点位数。
    
            x = x <= (g_img_src.cols-1) ? x : (g_img_src.cols-1);
            y = y <= (g_img_src.rows-1) ? y : (g_img_src.rows-1);
            x = x >= 0 ? x : 0;
            y = y >= 0 ? y : 0;
    
            g_img_dst.copyTo(g_imgMouseMove);
    
            rectangle(g_imgMouseMove, g_startPoint, Point(x, y), Scalar_<uchar>::all(20), 3, 8); //在g_imgMouseMove上画鼠标拖动时的矩形
            //rectangle(g_img_src, g_startPoint, Point(x, y), Scalar_<uchar>::all(20), 5, 8);
    
            //  rectangle(g_img_dst, g_startPoint, Point(x, y), Scalar(g_rng.uniform(100, 255), g_rng.uniform(100, 255), g_rng.uniform(100, 255)));
            //  rectangle(g_img_dst, g_startPoint, Point(x, y), Scalar(0, 255, 0));
            imshow(g_window_name, g_imgMouseMove); //把复制的图像显示出来
        }
        else if (CV_EVENT_LBUTTONUP == event /* && g_startPoint != Point(x, y)*/){ //抬起鼠标事件
    
            x = x <= (g_img_src.cols - 1) ? x : (g_img_src.cols - 1);
            y = y <= (g_img_src.rows - 1) ? y : (g_img_src.rows - 1);
            x = x >= 0 ? x : 0;
            y = y >= 0 ? y : 0;
    
            Point centerPoint = Point((x + g_startPoint.x) / 2, (y + g_startPoint.y)/2);
    
            //取边长大值
            int length = abs(x - g_startPoint.x) > abs(y - g_startPoint.y) ? abs(x - g_startPoint.x) : abs(y - g_startPoint.y);
    
            int length_x = (x - g_startPoint.x) / abs(x - g_startPoint.x) * length; //得到各自边长的正负
            int length_y = (y - g_startPoint.y) / abs(y - g_startPoint.y) * length;
    
            g_startPoint.x = centerPoint.x - length_x / 2;
            g_startPoint.y = centerPoint.y - length_y / 2;
    
            if (g_startPoint.x + length_x > g_img_dst.cols){
                g_startPoint.x = g_img_dst.cols - length;// abs(length_x);
            }
            if (g_startPoint.x + length_x < 0){
                g_startPoint.x = length;
            }
    
            if (g_startPoint.y + length_y > g_img_dst.rows){
                g_startPoint.y = g_img_dst.rows - length;// abs(length_y);
            }
            if (g_startPoint.y + length_y < 0){
                g_startPoint.y = length;
            }
    
            x = g_startPoint.x + length_x;
            y = g_startPoint.y + length_y;
    
            cout << length_x << "   " << length_y << endl;
            rectangle(g_img_dst, g_startPoint, Point(x, y), Scalar_<uchar>::all(20), 3, 8); //在img_dst上画矩形框
                            
            Point cutPoint;
    
            g_img_src(Rect(g_startPoint*P, Point(x*P, y*P))).copyTo(g_img_Cut); //保存矩形框中的图片:把起始点和结束点的坐标赋给感兴趣区域,并把感兴趣区域赋给g_img_Cut
        //  imshow("sub image", g_img_Cut);
            
            srand(time(NULL)); //设置随机数种子
            imwrite("截取后的图片\\"+to_string(rand() % 100) + to_string(rand() % 300) + to_string(rand() % 20) + to_string(rand() % 30) + ".jpg", g_img_Cut);
            //
    
            g_MouseDown_flag = false; //清零鼠标按下标志
        }
    }
    
    int main(int argc, char** argv){
    
        if (_mkdir("截取后的图片")==0){
            cout << "保存文件夹创建成功" << endl;
        }
    
        P = 2; //图像尺寸除以4,以减小图片尺寸
    
        g_img_src = imread("1.jpg"); //读取图片
        if (!g_img_src.data){
            cout << "图片读取失败,请检查图片的名称或路径" << endl;
            return 0;
        }
    
        g_img_src.copyTo(g_img_dst);
    
        resize(g_img_dst, g_img_dst, Size(g_img_dst.cols / P, g_img_dst.rows / P));
    
        if (g_img_src.empty()){
            cerr << "读取文件错误" << endl;
            return EXIT_FAILURE; //C语言中执行失败返回的值
        }
    
        namedWindow(g_window_name, 0);//设置窗口属性 //CV_WINDOW_NORMAL  //CV_WINDOW_KEEPRATIO
    
        //                 窗口的名字        鼠标事件发生时的函数指针    默认值为0
        setMouseCallback(g_window_name, onMouse, 0);  //开启鼠标事件
    
        while (true){
            imshow(g_window_name, g_img_dst);
    
            int c = waitKey(0);
            if ((c & 255) == 27){ // 按下Esc键
                destroyAllWindows(); //关闭所有窗口
                cout << "一张图片截图完毕" << endl;
                break;
            }
        }
    
    
        return EXIT_SUCCESS;
    }
    

    相关文章

      网友评论

        本文标题:OpenCV编写截图程序_&&_鼠标事件

        本文链接:https://www.haomeiwen.com/subject/fvnciftx.html