数据标定小工具

为了方便在制作机器学习所需的样本数据,提高工作效率,写了一个简单的矩形框标定并保存标定图像的程序,相关程序可由VS2012+OpenCV2411生成,默认对352*288大小的视频手动进行目标样本截取并保存。

先切换到程序marksave的目录下,需要在目录下分别建立一个叫avi和obj的文件夹,前者放视频,后者存放标定的样本数据,然后在cmd命令行中输入相关参数。

注意输入参数格式依次如下:

第一个输入参数为程序名:marksave.exe

第二个输入参数为视频名:avi/test.avi为视频文件,放置在当前目录下的avi文件夹里;

第三个输入参数控制图像输出格式:1表示会将所截取的图修正为正方形,若取0则不作修正;

第四个输入参数表示起始帧数:10表示从第10帧开始播放;

第五个输入参数表示图片保存格式:0表示存储为*.png1表示存储为*.jpg


程序开始执行后,按键P可以控制视频的暂停/播放;暂停后用鼠标先后点击目标的左上角和有下角确定需要的保存区域,逐个标定完后,再按P继续播放。结果保存在obj文件夹下,第三个输入参数为1时在保存时会对图像比例做修正,使之为正方形。

代码如下,大家可以根据自己的需求做下修改应用到自己的项目上。

// marksave.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <cv.h>
#include <highgui.h>
#include <math.h>
#include <time.h>
#include <iostream>
#include <fstream>
#include <Windows.h>  

#define OBJLEN 10

//视频图像宽高
#define IMGWIDHT 352
#define IMGHEIGHT 288

using namespace cv;  
using namespace std;

int objnum = 0;

bool pause = false;//是否暂停
IplImage *curframe = NULL; 

//复制原图像
IplImage *localframe = cvCreateImage(cvSize(IMGWIDHT,IMGHEIGHT),IPL_DEPTH_8U, 3);

bool lineflag = true;

//ROI区域两端点坐标
	int pointl_x[OBJLEN] = {0};
	int pointl_y[OBJLEN] = {0};
	int pointr_x[OBJLEN] = {0};
	int pointr_y[OBJLEN] = {0};


//鼠标点击获取坐标信息
void on_mouse( int event, int x, int y, int flags, void* ustc)  
{  
    CvFont font;  
    cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);  
          
    if( event == CV_EVENT_LBUTTONDOWN )  
    {  
		if(lineflag)
		{
			pointl_x[objnum] = x;
			pointl_y[objnum] = y;
		}
		else
		{
			pointr_x[objnum] = x;
			pointr_y[objnum] = y;
			objnum++;
		}

        CvPoint pt = cvPoint(x,y);  
#if 0
        char temp[16];  
		if(lineflag)
			sprintf(temp,"L(%d,%d)",pt.x,pt.y);  //显示鼠标点击的左上角坐标
		else
			sprintf(temp,"R(%d,%d)",pt.x,pt.y);  //显示鼠标点击的右上角坐标
        cvPutText(curframe,temp, pt, &font, cvScalar(255, 255, 255));  
#endif
        cvCircle( curframe, pt, 2, cvScalar(255,0,0),CV_FILLED, CV_AA, 0 );  
		cvLine(curframe,cvPoint(pt.x,1),cvPoint(pt.x,IMGHEIGHT-1),Scalar(0,255,0),1);
		cvLine(curframe,cvPoint(1,pt.y),cvPoint(IMGWIDHT-1,pt.y),Scalar(0,255,0),1);
        cvShowImage( "video", curframe );
		if(!lineflag)
			cvCopy(localframe,curframe,NULL);

		lineflag = !lineflag;
    }   
}  


void main(int argc, char* argv[])
{
	int frames = 0;


	int FrameNum = 0;//帧号
	int k = 0;
	int idx;

	int ROIx;
	int ROIy;
	int ROIwidth;
	int ROIheight;

	//CvCapture *capture = cvCreateFileCapture("test.avi");
	CvCapture *capture = cvCreateFileCapture(argv[1]);
	cout<<"视频读取成功!"<<endl;
	
	int rectflag = stoi(argv[2]);
	int startframe = stoi(argv[3]);
	int imgformat = stoi(argv[4]);

	frames = cvGetCaptureProperty(capture,CV_CAP_PROP_FRAME_COUNT);//获取视频帧数
	printf("total frames is %d\n", frames);
	cout<<"按键P可以控制视频的暂停/播放"<<endl;
	cout<<"暂停后用鼠标先后点击目标的左上角和有下角确定需要的保存区域"<<endl;

	uchar key = false;//用来设置暂停

	cvNamedWindow("video",0);
	//滑鼠事件呼叫函式
	cvSetMouseCallback( "video", on_mouse, 0 );

	while (capture)
	{
		curframe = cvQueryFrame(capture); //抓取一帧
		FrameNum++;	
		k++;

		if(FrameNum>startframe)
		{
		cout<<"frame:"<<FrameNum-1<<endl;
		Mat img(curframe,0);//0是不复制影像,也就是iplImg的data共用同个记意位置,header各自有

		cvCopy(curframe,localframe,NULL);

		cvShowImage("video",curframe);//显示当前帧
#if 0
		if(0 == FrameNum%3)//每隔一定帧数暂停一次用鼠标标定ROI区域
		{
				pause = true;
		}
#endif
		//按键P切换暂停和播放
		key = cvWaitKey(1);
		if(key == 'p') pause = true;
		while(pause)
			if(cvWaitKey(0)=='p')
				pause = false;	

		//暂停标定好区域后保存选定区域
		if(1)
		{
			for(idx=0;idx<objnum;idx++)
			{
				char resultImgName[256];
				ROIx = pointl_x[idx];
				ROIy = pointl_y[idx];
				if(rectflag>=1)
				{
					ROIwidth = max(pointr_x[idx]-ROIx+1,pointr_y[idx]-ROIy+1);
					ROIheight = ROIwidth;
				}
				else
				{
					ROIwidth = pointr_x[idx]-ROIx+1;
					ROIheight = pointr_y[idx]-ROIy+1;
				}


				cvSetImageROI(localframe,cvRect(ROIx, ROIy, ROIwidth, ROIheight));//设置源图像ROI
				if(imgformat>0)
					sprintf(resultImgName, "obj/%d_%d.jpg", k,idx);	
				else
					sprintf(resultImgName, "obj/%d_%d.png", k,idx);	
				cvSaveImage( resultImgName, localframe );
				cvResetImageROI(localframe);//源图像用完后,清空ROI

			}

		}
		objnum = 0;

		if(FrameNum == frames-2)//截止帧数
				break;
		}
	}

	cvWaitKey(0);
	cvDestroyWindow("video"); 
	cvReleaseImage(&curframe);
	cvReleaseImage(&localframe);

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值