Opencv暑期历程--Day8 (设计一个标注小工具)

xiaoxiao2021-03-01  24

之前训练识别车牌的程序的时候,本来想要大量车牌的图像,因为之前有做过数据标注的工作,所以很自然的就想到能不能用Opencv也做一个呢,之前公司的人做的标注工具不好用,太多 BUG了。

图像标注工具的原理大概就是:如果有鼠标左键事件,记录这个位置,如果没有松开,就一直记录新的鼠标的位置,然后一直更新终点位置,直到鼠标出校左键松开事件,就为第一个框框,存储到一个矩形容器中。用waitKey(0)函数获取当前按的按键。

 

setMouseCallback()

void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0) winname:窗口的名字 onMouse:鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 这个函数的原型应该为void on_Mouse(int event, int x, int y, int flags, void* param); userdate:传给回调函数的参数

 

void on_Mouse(int event, int x, int y, int flags, void* param); event是 CV_EVENT_*变量之一 x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系) flags是CV_EVENT_FLAG的组合, param是用户定义的传递到setMouseCallback函数调用的参数。 Event: #define CV_EVENT_MOUSEMOVE 0 //滑动 #define CV_EVENT_LBUTTONDOWN 1 //左键点击 #define CV_EVENT_RBUTTONDOWN 2 //右键点击 #define CV_EVENT_MBUTTONDOWN 3 //中键点击 #define CV_EVENT_LBUTTONUP 4 //左键放开 #define CV_EVENT_RBUTTONUP 5 //右键放开 #define CV_EVENT_MBUTTONUP 6 //中键放开 #define CV_EVENT_LBUTTONDBLCLK 7 //左键双击 #define CV_EVENT_RBUTTONDBLCLK 8 //右键双击 #define CV_EVENT_MBUTTONDBLCLK 9 //中键双击 flags: #define CV_EVENT_FLAG_LBUTTON 1 //左鍵拖曳 #define CV_EVENT_FLAG_RBUTTON 2 //右鍵拖曳 #define CV_EVENT_FLAG_MBUTTON 4 //中鍵拖曳 #define CV_EVENT_FLAG_CTRLKEY 8 //(8~15)按Ctrl不放事件 #define CV_EVENT_FLAG_SHIFTKEY 16 //(16~31)按Shift不放事件 #define CV_EVENT_FLAG_ALTKEY 32 //(32~39)按Alt不放事件

 

注意:flags & CV_EVENT_FLAG_LBUTTON 的意思是 提取flags的CV_EVENT_FLAG_LBUTTON 标志位,!()的意思是 标志位无效 。if (flag == CV_EVENT_FLAG_LBUTTON)这句话的意思是如果标志位是CV_EVENT_FLAG_LBUTTON,则...

 

标志工具小例子:

// opencv_day7.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include <iostream> using namespace std; using namespace cv; Point ptL, ptR;鼠标画出矩形框的起点和终点,矩形的左下角和右下角 Mat imageSource, imageSourceCopy; FILE* fp_result;//标签结果 struct UserData { Mat src; vector<Rect> rect; }; void onMouse(int event, int x, int y, int flag, void *dp) { UserData *d = (UserData *)dp; imageSourceCopy = imageSource.clone(); if (event == CV_EVENT_LBUTTONDOWN)//按下鼠标右键,即拖动开始 { ptL = Point(x, y); ptR = Point(x, y);//起点终点都设为当前按下的位置 } if (flag == CV_EVENT_FLAG_LBUTTON) //拖拽鼠标右键,即拖动进行 { ptR = Point(x, y);//获取当前鼠标的位置作为终点 imageSourceCopy = imageSource.clone(); rectangle(imageSourceCopy, ptL, ptR, Scalar(0, 255, 0)); imshow("标注",imageSourceCopy); } if (event == CV_EVENT_LBUTTONUP) { if (ptL != ptR) { rectangle(imageSourceCopy, ptL, ptR, Scalar(0, 255, 0)); imshow("标注", imageSourceCopy); int h = ptR.y - ptL.y;//右下角的y减去左上角的y int w = ptR.x - ptL.x; printf("选择的信息区域是:x:%d y:%d w:%d h:%d\n", ptL.x, ptL.y, w, h); d->rect.push_back(Rect(ptL.x, ptL.y, w, h));//把选中区域存到Rect数组中 } } //点击右键删除一个矩形 if (event == CV_EVENT_RBUTTONDOWN) { if (d->rect.size() > 0) { Rect temp = d->rect.back(); printf("删除的信息区域是:x:%d y:%d w:%d h:%d\n", temp.x, temp.y, temp.width, temp.height); d->rect.pop_back(); for (int i = 0; i < d->rect.size(); i++) { rectangle(imageSourceCopy, d->rect[i], Scalar(0, 255, 0), 1); } } else { printf("已没有框框可以删\n"); } } } void DrawArea(Mat& src, char img_name[], char path_name[]) { Mat img = src.clone(); char c = 'x'; UserData d; d.src = img.clone(); while (c!= 'n')//按'n'下一张图片 { Mat backup = src.clone(); imageSource = img.clone(); cvNamedWindow("标注", WINDOW_AUTOSIZE); imshow("标注", imageSource); setMouseCallback("标注", onMouse, &d);//设置鼠标事件的响应函数 c = waitKey(0); if (c == 'a')//按a键画下一个框 { printf("rect size: %d\n", d.rect.size()); for (int i = 0; i < d.rect.size(); i++) { rectangle(backup, d.rect[i], Scalar(0, 255, 0));//给备份图画框 } img = backup.clone();//本来要用来存放标注完的图像,不过暂时不用 } } //结束当前图像标注时 fprintf(fp_result, "%s\n", path_name); fprintf(fp_result, "%d\n", d.rect.size());//存放图片的名字,大小 for (int i = 0; i < d.rect.size(); i++) { Rect t = d.rect[i]; fprintf(fp_result, "%d %d %d %d\n", t.x, t.y, t.width, t.height);//存放某一张图片中的矩形位置 } // imwrite(path_name, img); } int main() { char filename[10]; fp_result = fopen("record.txt", "a+" );//打开记录文档 for (int i = 0; i < 10; i++) { sprintf(filename, "%d.jpg", i);//格式化输入 Mat src = imread(filename); DrawArea(src, filename, filename); } }

 

 

转载请注明原文地址: https://www.6miu.com/read-4050330.html

最新回复(0)