美文网首页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编写截图程序_&&_鼠标事件

    环境:OpenCV3.2.0,VS2013,Windows7。语言:C++我需要截取样本作机器学习数据的训练,不但...

  • opencv 鼠标事件

    目标 学习 opencv的鼠标事件和鼠标事件回调函数cv2.setMouseCallback()的使用。 根据获取...

  • OpenCV鼠标事件

    使用本代码可以打印出鼠标所在的坐标和像素大小(黑白图片)使用函数setMouseCallback,输入参数1是窗口...

  • OpenCV 截图程序

    开发平台 win10 64位、codeblocks 源代码

  • Vue 鼠标事件

    鼠标事件示例:可以实时获得鼠标的x、y轴数据! 编写js文件(事件方法): 在html中引入js文件: 编写css...

  • javascript笔记10

    事件处理程序 焦点事件 鼠标事件-单击与双击 鼠标事件-mouserover/mouserout/mousedow...

  • opencv鼠标事件简易例程

    环境Ubuntu18.04,OpenCv4程序功能是点击鼠标在图上画点

  • 计算机视觉 OpenCV (5)

    我们鼠标或者触控与 opencv 图像进行交互会触发事件,我们输出一下 EVENT 看一看 opencv 为我们提...

  • OpenCV中利用鼠标事件动态绘制图形

    使用鼠标事件动态绘制 对于使用OpenCV绘制图形和文本,我们已经耳熟能详了。在本文中,我们将利用OpenCV中的...

  • Opencv python之图像的载入,显示与保存

    在电脑上安装好Opencv环境之后,就可以开始编写程序啦。Opencv环境安装就不介绍了,之前介绍过了。 首先我们...

网友评论

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

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