文中内容大多来自大神浅墨_毛星云 所著【OpenCV3编程入门】,在此基础上加入了自己的理解和补充内容。
#include <opencv2/opencv.hpp>
using namespace cv;
#define WINDOW_NAME "程序窗口"
//全局函数声明
void on_MouseHandle(int event, int x, int y, int flags, void *param);
void drawRectangle(Mat &img, Rect box);
Rect g_rectangle;
bool g_bDrawingBox = false;//是否进行绘制
RNG g_rng(12345);//随机数 参数为随机种子
int main(int argc, char **argv) {
    //准备参数
    g_rectangle = Rect(-1, -1, 0, 0);
    Mat srcImage(600, 800,CV_8UC3);
    Mat tempImage;
    srcImage.copyTo(tempImage);
//    g_rectangle = Rect(-1, -1, 0, 0);
    srcImage = Scalar::all(0);
    //设置鼠标回调函数
    namedWindow(WINDOW_NAME);
    //为指定的窗口设置鼠标回调函数
    setMouseCallback(WINDOW_NAME, on_MouseHandle, (void *) &srcImage);
    //程序主循环 ,当进行绘制的标识符为true时,进行绘制
    while (1) {
        srcImage.copyTo(tempImage);
        if (g_bDrawingBox) {
            drawRectangle(tempImage, g_rectangle);
        }
        imshow(WINDOW_NAME, tempImage);
        //esc退出 esc 的ASCII码为27
        if (waitKey(10) == 27) {
            break;
        }
    }
    return 0;
}
/**
 * 鼠标回调函数,根据不同的鼠标事件进行不同的操作
 @param事件是cv :: MouseEventTypes常量之一。
@param x鼠标事件的x坐标。
@param y鼠标事件的y坐标。
@param标记cv :: MouseEventFlags常量之一。
@param userdata可选参数。
 */
void on_MouseHandle(int event, int x, int y, int flags, void *param) {
    Mat &image = *(Mat *) param;
    switch (event) {
        case EVENT_MOUSEMOVE://鼠标移动
            if (g_bDrawingBox) {
                g_rectangle.width = x - g_rectangle.x;
                g_rectangle.height = y - g_rectangle.y;
            }
            break;
        case EVENT_LBUTTONDOWN: {//鼠标左键按下
            g_bDrawingBox = true;
            g_rectangle = Rect(x, y, 0, 0);//记录起始点
        }
            break;
        case EVENT_LBUTTONUP: {//鼠标释放
            g_bDrawingBox = false;
            //对宽高小于0的处理
            //起点往上往左画 分别对应着height<0 width<0
            if (g_rectangle.width < 0) {
                std::cout<<"width < 0"<<std::endl;
                g_rectangle.x += g_rectangle.width;
                g_rectangle.width *= -1;
            }
            if (g_rectangle.height < 0) {
                std::cout<<"height < 0"<<std::endl;
                g_rectangle.y += g_rectangle.height;
                g_rectangle.height *= -1;
            }
            drawRectangle(image, g_rectangle);
        }
            break;
    }
}
/**
 * 绘制矩形
 * @param img 图像
 * @param box 矩形框 随机颜色
 */
void drawRectangle(Mat &img, Rect box) {
   // img 图像. pt1 矩形的一个顶点。 pt2 矩形对角线上的另一个顶点 color 线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image)。 thickness 组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。 line_type 线条的类型。见cvLine的描述 shift 坐标点的小数点位数。
    rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(
            0, 255
    ),g_rng
    .uniform(0,255),g_rng.uniform(0,255)),1,4,0);
}
运行后鼠标绘图截图:
image.png
补充:
Mat srcImage(600, 800,CV_8UC3); 中的CV_8UC3的含义:
这里的type可以是任何的预定义类型,预定义类型的结构如下所示:
    CV_<bit_depth>(S|U|F)C<number_of_channels>
- bit_depth---比特数---代表8bite,16bites,32bites,64bites---举个例子吧--比如说,如
 
如果你现在创建了一个存储--灰度图片的Mat对象,这个图像的大小为宽100,高100,那么,现在这张
灰度图片中有10000个像素点,它每一个像素点在内存空间所占的空间大小是8bite,8位--所以它对
应的就是CV_8- S|U|F--S--代表---signed int---有符号整形
 
U--代表--unsigned int--无符号整形
F--代表--float---------单精度浮点型- C<number_of_channels>----代表---一张图片的通道数,比如:
 
灰度图片--grayImg---是--单通道图像
RGB彩色图像---------是--3通道图像
带Alph通道的RGB图像--是--4通道图像
所以这里的意思是创建一个高600,宽800的8位无符号3通道的RGB彩色图像容器











网友评论