一、鼠标截图

其中用到的方法有

imread("arnold_schwarzenegger.jpg")  //读取图片的函数,用法参考imread六种姿势

setMouseCallback("inWindows", onMouse, 0);

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:传给回调函数的参数

 

onMouse(int event, int x, int y, int flag, void *param)

void on_Mouse(int event, int x, int y, int flags, void* param);
event是 CV_EVENT_*变量之一
x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系) 
flags是CV_EVENT_FLAG的组合, param是用户定义的传递到setMouseCallback函数调用的参数。

cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
                  int thickness=1, int line_type=8, int shift=0 );
img:图像.pt1:矩形的一个顶点。pt2:矩形对角线上的另一个顶点

color:线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image)
thickness:组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形
line_type :线条的类型。见cvLine的描述   shift :坐标点的小数点位数
具体代码如下,修改了ROI = inImage(Rect(pt.x, pt.y, x - pt.x, y - pt.y));这里

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

Mat inImage = imread("arnold_schwarzenegger.jpg");//施瓦辛格,放在项目同一文件夹里
Mat outImage = inImage.clone();
bool flag = false;
Point pt;
Mat ROI;

void onMouse(int event, int x, int y, int flag, void *param)
{
	switch (event)
	{
	case CV_EVENT_LBUTTONDOWN:	//鼠标左键按下
		printf("鼠标左键按下\n");
		flag = true;
		pt.x = x;
		pt.y = y;
		break;

	case CV_EVENT_MOUSEMOVE:
		printf("鼠标移动\n");

		if (flag)
		{
			inImage.copyTo(outImage); //将原图像赋值给temp,以便永远只有一个矩形(否则许多矩形会重叠在一起)
			rectangle(outImage, pt, Point(x, y), Scalar(0, 255, 0), 2, 8);
			//这里的Scalar是控制矩形颜色的,分别是R,G,B三色道,(0,255,0)是绿色,(255,0,0)是红色,(0,0,255)是蓝色
		}
		break;

	case CV_EVENT_LBUTTONUP:
		printf("鼠标左键抬起\n");

		flag = false;
		//ROI = outImage(Rect(pt.x, pt.y, x - pt.x, y - pt.y));	//确定ROI区域,有矩形边框
		//ROI = inImage(Rect(pt.x, pt.y, x - pt.x, y - pt.y));//无矩形边框,这样写只能鼠标右下复制,其他方式会出现error
		//做一个简单的数学变换
		ROI = inImage(Rect(min(pt.x,x),min(pt.y,y),abs(x-pt.x),abs(y-pt.y)));//使用min函数可以省去不必要的判断
		imshow("Out", ROI);
		imwrite("ROI.jpg", ROI);
		break;

	default:
		break;
	}
}

int main()
{
	namedWindow("inWindows", CV_WINDOW_AUTOSIZE);

	setMouseCallback("inWindows", onMouse, 0);//我理解是开了线程,检测“inWindows”里面的鼠标动作

	while (1)//不加while(1),闪一下就没了
	{
		imshow("inWindows", outImage);//窗口显示outImage,施瓦辛格图片
		if (27 == waitKey(30))  //按esc键退出循环
		{
			break;
		}
	}

	destroyAllWindows();
	return 0;
}

二、滑动条播放视频

createTrackbar(const string& trackbarname, const string& winname, int* value, int count, TrackbarCallback onChange=0, void*userdata=0)

Parameters:

  • trackbarname:创建的滑动条名。
  • winname:滑动条的父窗体名。
  • value:滑动条当前值。
  • count:允许的最大值,最小值为0。
  • onChange:回调函数,当滑动条位置发生变化时,调用此函数。函数形如void Foo(int,void*);,第一个是位置值,第二个是userdata
  • userdata:可以被传递给回调函数,可以在没有全局位置变量时起作用。
     
void setTrackbarPos(const String& trackbarname, const String& winname, int pos)

Parameters:

  • trackbarname:滑动条名称。
  • winname:窗口名称。
  • pos:新位置。
/*
	滑动条视频播放
*/
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;


int value;

void onChange(int pos, void *param)//进度条拖动要做的事情
{
	VideoCapture cap = *(VideoCapture *)param;
	cap.set(CV_CAP_PROP_POS_FRAMES, value);	//设置视频帧位置
}

int main()
{
	Mat frame;
	VideoCapture capture;

	capture.open("test.MP4");
	if (!capture.isOpened())
	{
		printf("can't open video file\n");
		return -1;
	}

	int fps = (int)capture.get(CV_CAP_PROP_FPS);	//获取视频帧率
	int frameCount = (int)capture.get(CV_CAP_PROP_FRAME_COUNT);	//获取视频总帧数

	namedWindow("video", CV_WINDOW_AUTOSIZE);

	createTrackbar("frame", "video", &value, frameCount, onChange, (void *)&capture);

	while (true)
	{
		int framePos = (int)capture.get(CV_CAP_PROP_POS_FRAMES);
		setTrackbarPos("frame", "video", framePos);
		capture.read(frame);
		if(!frame.empty())  //添加这一句之后不会出现error
		imshow("video", frame);
		if (27 == waitKey(1000 / fps))
		{
			break;
		}
	}

	capture.release();
	destroyAllWindows();

	return 0;
}