- void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);
- /*******************************************************************
- * winname: 监听窗口名称
- * onMouse: 鼠标事件回调函数
- * userdata: 递给回调函数的可选参数
- *********************************************************************/
- typedef void (*MouseCallback)(int event, int x, int y, int flags, void* userdata);
- //MouseCallback onMouse
- void onMouse(int event,int x,int y,int flag,void *param)
- /*******************************************************************
- * event: 事件类型
- * x: 鼠标所在图像的坐标
- * y:
- * flags: 代表拖拽事件
- * param: 自己定义的onMouse事件的ID
- *********************************************************************/
- enum MouseEventTypes {
- EVENT_MOUSEMOVE = 0, //鼠标移动
- EVENT_LBUTTONDOWN = 1, //鼠标左键按下
- EVENT_RBUTTONDOWN = 2, //鼠标右键按下
- EVENT_MBUTTONDOWN = 3, //鼠标中键按下
- EVENT_LBUTTONUP = 4, //鼠标左键弹起
- EVENT_RBUTTONUP = 5, //鼠标右键弹起
- EVENT_MBUTTONUP = 6, //鼠标中键弹起
- EVENT_LBUTTONDBLCLK = 7, //鼠标左键双击
- EVENT_RBUTTONDBLCLK = 8, //鼠标右键双击
- EVENT_MBUTTONDBLCLK = 9, //鼠标中间双击
- EVENT_MOUSEWHEEL = 10, //鼠标滚轮 正数和负数分别表示向前和向后滚动
- EVENT_MOUSEHWHEEL = 11 //鼠标滚轮 正数和负数分别表示向右和向左滚动
- };
- enum MouseEventFlags {
- EVENT_FLAG_LBUTTON = 1, //左键拖动
- EVENT_FLAG_RBUTTON = 2, //右键拖动
- EVENT_FLAG_MBUTTON = 4, //中键拖动
- EVENT_FLAG_CTRLKEY = 8, //ctr拖动
- EVENT_FLAG_SHIFTKEY = 16, //shift拖动
- EVENT_FLAG_ALTKEY = 32 //alt拖动
- };
注意点:
①将onMouse函数(回调函数)设置为类中的静态函数--->不用创建对象直接调用。
②onMouse(回调函数)的参数是固定的,最后一个参数是void* param,此处是通过DrawShape这个类生成的对象来进行绘制操作的,所以param传入的是其生成的对象。最后在onMouse函数中第一步,就必须得强制类型转换才行。
③namedWindow函数是用来生成一个窗口的,参数对应setMouseCallback函数的第一个参数const String& winname(窗口的名称)
④无需写鼠标事件响应函数的函数体(直接调用),setMouseCallback,直接传参即可,注意第二个参数就是回调函数,第三个参数是param
⑤Rect类实例化后是一个存储矩形基本信息的对象。x,y,width,height
- //Opencv鼠标左键画圆,右键画方
- #include
- #include
- using namespace std;
- using namespace cv;
- class DrawShape
- {
- public:
- DrawShape() :mat(imread("mm.jpg")) {}
- void Show(string wName = "drawShape")
- {
- imshow(wName, mat);
- }
- void DrawCircle(int x = 300, int y = 300, int r = 10)
- {
- circle(mat, Point(x, y), r, Scalar(0, 255, 0));
- }
- void DrawRecagnle(int x = 200, int y = 200, int w = 40, int h = 40)
- {
- rectangle(mat, Rect(x, y, w, h), Scalar(255, 0, 0));
- }
- static void OnMouse(int event, int x, int y, int flag, void* param);
- protected:
- Mat mat;
- };
- void DrawShape::OnMouse(int event, int x, int y, int flag, void* param)
- {
- DrawShape* pshape = (DrawShape*)param;
- switch(event)
- {
- case EVENT_LBUTTONDOWN:
- cout << "左键按下......." << endl;
- pshape->DrawCircle(x,y,10);
- break;
- case EVENT_RBUTTONDOWN:
- cout << "右键按下......." << endl;
- pshape->DrawRecagnle(x-5,y-5,10,10);
- break;
- }
- }
- int main()
- {
- DrawShape* pshape = new DrawShape;
- namedWindow("drawShape");
- setMouseCallback("drawShape", &DrawShape::OnMouse, pshape);
- //主循环
- while (1)
- {
- pshape->Show();
- if (waitKey(10) == 27)
- {
- break;
- }
- }
- delete pshape;
- pshape = nullptr;
- return 0;
- }
opencv里对视频的编码解码等支持并不是很良好,所以不要希望用opencv 做多媒体开发,opencv是一个强大的计算机视觉库,而不是视频流编码器或者解码器。希望大家不要走入这个误区,可以把这部分简单单独看待。而且生成的视频文件不能大于2GB,而且不能添加音频。如果想搞音视频处理可以使用FFmpeg库。
opencv中通过VideoCaptrue类对视频进行读取操作以及调用摄像头,类如下
- class VideoCapture
- {
- public:
- VideoCapture();
- explicit VideoCapture(const String& filename, int apiPreference = CAP_ANY);
- explicit VideoCapture(const String& filename, int apiPreference, const std::vector<int>& params);
- explicit VideoCapture(int index, int apiPreference = CAP_ANY);
- explicit VideoCapture(int index, int apiPreference, const std::vector<int>& params);
- virtual ~VideoCapture();
- virtual bool open(const String& filename, int apiPreference = CAP_ANY);
- virtual bool open(const String& filename, int apiPreference, const std::vector<int>& params);
- virtual bool open(int index, int apiPreference = CAP_ANY);
- virtual bool open(int index, int apiPreference, const std::vector<int>& params);
- virtual bool isOpened() const;
- virtual void release();
- virtual bool grab();
- virtual bool retrieve(OutputArray image, int flag = 0);
- virtual VideoCapture& operator >> (CV_OUT Mat& image);
- virtual VideoCapture& operator >> (CV_OUT UMat& image);
- virtual bool read(OutputArray image);
- virtual bool set(int propId, double value);
- virtual double get(int propId) const;
- String getBackendName() const;
- void setExceptionMode(bool enable) { throwOnFail = enable; }
- bool getExceptionMode() { return throwOnFail; }
- bool waitAny(const std::vector
& streams,CV_OUT std::vector<int>& readyIndex,int64 timeoutNs = 0) ; - protected:
- Ptr
cap; - Ptr
icap; - bool throwOnFail;
- friend class internal::VideoCapturePrivateAccessor;
- };
①创建对象除了下面代码创建的方式(构造函数)以外,还可以使用内部的成员函数open函数。
②参数是一个路径--->对应视频 参数若是0--->对应摄像头
- #include
- #include
- using namespace std;
- using namespace cv;
-
- int main()
- {
- VideoCapture cap = VideoCapture("test.mp4");
- if(!cap.isOpened())
- {
- cout << "打开失败!" << endl;
- return 0;
- }
- VideoCapture camera = VideoCapture(0);
- if (!camera.isOpened())
- {
- cout << "摄像头打开失败!" << endl;
- return 0;
- }
- return 0;
- }
获得视频有诸多属性,比如:帧率、总帧数、尺寸、格式等
- #include
- #include
- using namespace std;
- using namespace cv;
-
- int main()
- {
- VideoCapture cap = VideoCapture("test.mp4");
- if(!cap.isOpened())
- {
- cout << "打开失败!" << endl;
- return 0;
- }
- cout << "宽度:" << cap.get(CAP_PROP_FRAME_WIDTH) << endl;
- cout << "高度:" << cap.get(CAP_PROP_FRAME_HEIGHT) << endl;
- cout << "帧数:" << cap.get(CAP_PROP_FRAME_COUNT) << endl;
- cout << "帧率:" << cap.get(CAP_PROP_FPS) << endl;
-
- //VideoCapture camera = VideoCapture(0);
- //if (!camera.isOpened())
- //{
- // cout << "摄像头打开失败!" << endl;
- // return 0;
- //}
- return 0;
- }
其他属性获取
- enum VideoCaptureProperties {
- CAP_PROP_POS_MSEC =0, //视频文件的当前位置,单位为毫秒
- CAP_PROP_POS_FRAMES =1, //解码/捕获的帧的基于0的索引
- CAP_PROP_POS_AVI_RATIO =2, //视频文件的相对位置:0=影片开始,1=影片结束
- CAP_PROP_FRAME_WIDTH =3, //视频宽度
- CAP_PROP_FRAME_HEIGHT =4, //视频高度
- CAP_PROP_FPS =5, //帧率
- CAP_PROP_FOURCC =6, //4个字符的编解码器代码
- CAP_PROP_FRAME_COUNT =7, //视频文件中的帧数
- CAP_PROP_FORMAT =8, //视频格式
-
- CAP_PROP_MODE =9,
- CAP_PROP_BRIGHTNESS =10, //图像亮度(摄像模式)
- CAP_PROP_CONTRAST =11, //图像对比度(摄像模式)
- CAP_PROP_SATURATION =12, //图像饱和度(摄像模式)
- CAP_PROP_HUE =13, //图像的色调(摄像模式)
- CAP_PROP_GAIN =14, //图像增益(摄像模式)
- CAP_PROP_EXPOSURE =15, //曝光(摄像模式)
- CAP_PROP_CONVERT_RGB =16, //图像是否应该转换为RGB的布尔标记
-
- CAP_PROP_WHITE_BALANCE_BLUE_U =17,
- CAP_PROP_RECTIFICATION =18,
- CAP_PROP_MONOCHROME =19,
- CAP_PROP_SHARPNESS =20,
- CAP_PROP_AUTO_EXPOSURE =21,
- CAP_PROP_GAMMA =22,
- CAP_PROP_TEMPERATURE =23,
- CAP_PROP_TRIGGER =24,
- CAP_PROP_TRIGGER_DELAY =25,
- CAP_PROP_WHITE_BALANCE_RED_V =26,
- CAP_PROP_ZOOM =27,
- CAP_PROP_FOCUS =28,
- CAP_PROP_GUID =29,
- CAP_PROP_ISO_SPEED =30,
- CAP_PROP_BACKLIGHT =32,
- CAP_PROP_PAN =33,
- CAP_PROP_TILT =34,
- CAP_PROP_ROLL =35,
- CAP_PROP_IRIS =36,
- CAP_PROP_SETTINGS =37,
- CAP_PROP_BUFFERSIZE =38,
- CAP_PROP_AUTOFOCUS =39,
- CAP_PROP_SAR_NUM =40,
- CAP_PROP_SAR_DEN =41,
- CAP_PROP_BACKEND =42,
- CAP_PROP_CHANNEL =43,
- CAP_PROP_AUTO_WB =44,
- CAP_PROP_WB_TEMPERATURE=45,
- CAP_PROP_CODEC_PIXEL_FORMAT =46,
- CAP_PROP_BITRATE =47,
- CAP_PROP_ORIENTATION_META=48,
- CAP_PROP_ORIENTATION_AUTO=49,
- CAP_PROP_HW_ACCELERATION=50,
- CAP_PROP_HW_DEVICE =51,
- CAP_PROP_HW_ACCELERATION_USE_OPENCL=52,
- CAP_PROP_OPEN_TIMEOUT_MSEC=53,
- CAP_PROP_READ_TIMEOUT_MSEC=54,
- CAP_PROP_STREAM_OPEN_TIME_USEC =55,
- CAP_PROP_VIDEO_TOTAL_CHANNELS = 56,
- CAP_PROP_VIDEO_STREAM = 57,
- CAP_PROP_AUDIO_STREAM = 58,
- CAP_PROP_AUDIO_POS = 59,
- CAP_PROP_AUDIO_SHIFT_NSEC = 60,
- CAP_PROP_AUDIO_DATA_DEPTH = 61,
- CAP_PROP_AUDIO_SAMPLES_PER_SECOND = 62,
- CAP_PROP_AUDIO_BASE_INDEX = 63,
- CAP_PROP_AUDIO_TOTAL_CHANNELS = 64,
- CAP_PROP_AUDIO_TOTAL_STREAMS = 65,
- CAP_PROP_AUDIO_SYNCHRONIZE = 66,
- CAP_PROP_LRF_HAS_KEY_FRAME = 67,
- CAP_PROP_CODEC_EXTRADATA_INDEX = 68,
- #ifndef CV_DOXYGEN
- CV__CAP_PROP_LATEST
- #endif
- };
视频转图像显示
方法:一帧一帧的流操作(已重载)即可。
(注意:流操作结束之后,原对象的相关信息都会丢失,若还要继续使用,需要重新获取。)
- #include
- #include
- using namespace std;
- using namespace cv;
-
-
- int main()
- {
- VideoCapture cap = VideoCapture("test.mp4");
- if(!cap.isOpened())
- {
- cout << "打开失败!" << endl;
- return 0;
- }
- Mat img;
- while (true)
- {
- cap >> img; //flip
- if (img.empty())
- {
- break;
- }
- imshow("图像", img);
- waitKey(30);
- }
- cap.release();
- return 0;
- }
视频转图像保存(每一帧图像的保存)
- #include
- #include
- using namespace std;
- using namespace cv;
-
-
- int main()
- {
- VideoCapture cap = VideoCapture("test.mp4");
- if(!cap.isOpened())
- {
- cout << "打开失败!" << endl;
- return 0;
- }
- Mat img;
- int index = 1;
- while (true)
- {
- cap >> img; //flip
- if (img.empty())
- {
- break;
- }
- //imshow("图像", img);
- string name = "mm/img" + to_string(index++) + ".jpg";
- imwrite(name, img);
- waitKey(30);
- }
- cap.release();
- return 0;
- }
- #include
- #include
- using namespace std;
- using namespace cv;
- int main()
- {
- VideoCapture cap = VideoCapture(0);
- if(!cap.isOpened())
- {
- cout << "打开失败!" << endl;
- return 0;
- }
- Mat img;
- int index = 1;
- while (true)
- {
- cap >> img;
- if (img.empty())
- {
- break;
- }
- imshow("图像", img);
- waitKey(30);
- }
- cap.release();
- return 0;
- }
opencv中通过VideoWriter类对视频进行读取操作以及调用摄像头,该类的API与VideoCapture类似,该类的主要API除了构造函数外,提供了open、isOpened、release、write和重载操作符<<
- class CV_EXPORTS_W VideoWriter
- {
- public:
- CV_WRAP VideoWriter();
- CV_WRAP VideoWriter(const String& filename, int fourcc, double fps,
- Size frameSize, bool isColor = true);
- CV_WRAP VideoWriter(const String& filename, int apiPreference, int fourcc, double fps,
- Size frameSize, bool isColor = true);
- CV_WRAP VideoWriter(const String& filename, int fourcc, double fps, const Size& frameSize,
- const std::vector<int>& params);
- CV_WRAP VideoWriter(const String& filename, int apiPreference, int fourcc, double fps,
- const Size& frameSize, const std::vector<int>& params);
- virtual ~VideoWriter();
- CV_WRAP virtual bool open(const String& filename, int fourcc, double fps,
- Size frameSize, bool isColor = true);
- CV_WRAP bool open(const String& filename, int apiPreference, int fourcc, double fps,
- Size frameSize, bool isColor = true);
- CV_WRAP bool open(const String& filename, int fourcc, double fps, const Size& frameSize,
- const std::vector<int>& params);
- CV_WRAP bool open(const String& filename, int apiPreference, int fourcc, double fps,
- const Size& frameSize, const std::vector<int>& params);
- CV_WRAP virtual bool isOpened() const;
- CV_WRAP virtual void release();
- virtual VideoWriter& operator << (const Mat& image);
- virtual VideoWriter& operator << (const UMat& image);
- CV_WRAP virtual void write(InputArray image);
- CV_WRAP virtual bool set(int propId, double value);
- CV_WRAP virtual double get(int propId) const;
- CV_WRAP static int fourcc(char c1, char c2, char c3, char c4);
- CV_WRAP String getBackendName() const;
- protected:
- Ptr
writer; - Ptr
iwriter; -
- static Ptr
create(const String& filename, int fourcc, double fps, - Size frameSize, bool isColor = true);
- };
针对静态函数 fourcc函数,四个参数如何传入,见下面的网站,挑一个格式,分解成四个字符传入即可。--->常作为open的第二个参数。
视频其他格式
http://mp4ra.org/#/codecs
摄像头转视频保存.
①VideoWriter的open需要四个参数:
1)保存的路径名
2)int fourcc--->解编码格式
3)fps帧率
4)Size对象(宽度和高度来构造)--->常通过get方法来获取。
②将在cap中 流出每一帧的图片img
再流入save对象即可实现。
- #include
- #include
- using namespace std;
- using namespace cv;
- int main()
- {
- VideoCapture cap = VideoCapture(0);
- if(!cap.isOpened())
- {
- cout << "打开失败!" << endl;
- return 0;
- }
- int width = cap.get(CAP_PROP_FRAME_WIDTH);
- int height = cap.get(CAP_PROP_FRAME_HEIGHT);
- VideoWriter save;
- save.open("save.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), 30, Size(width, height), true);
- Mat img;
- while (true)
- {
- cap >> img;
- imshow("摄像头", img);
- save << img;
- //按ESC退出
- if (waitKey(10) == 27)
- {
- break;
- }
- }
- cap.release();
- save.release();
- return 0;
- }
- #include
- #include
- using namespace cv;
- using namespace std;
- class Video
- {
- public:
- Video();
- ~Video();
- void GetVideo(string fileName = "test.mp4");//初始化cap
- void SaveToVideo(string fileName = "out.avi");
- void SaveToImg(string preName = "mm/img");
- void Camera(string fileName = "录像.avi");
-
-
- protected:
- VideoCapture cap;
- VideoWriter save;
- };
- Video::Video()
- {
-
- }
- Video::~Video()
- {
- cap.release();
- save.release();
- }
- void Video::GetVideo(string fileName)
- {
- cap = VideoCapture(fileName);
- if (!cap.isOpened())
- {
- cout << "视频获取失败!" << endl;
- }
- }
-
- void Video::SaveToVideo(string fileName)
- {
- int w = cap.get(CAP_PROP_FRAME_WIDTH);
- int h = cap.get(CAP_PROP_FRAME_HEIGHT);
- int fps = cap.get(CAP_PROP_FPS);
- save.open(fileName, VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, Size(w, h), true);
- Mat img;
- while (true)
- {
- cap >> img;
- if (img.empty())
- break;
- save << img;
- }
- }
-
- void Video::SaveToImg(string preName)
- {
- Mat img;
- int index = 0;
- string name;
- while (true)
- {
- cap >> img;
- if (img.empty())
- {
- break;
- }
- name = preName + to_string(index++) + ".jpg";
- imwrite(name, img);
- }
- }
-
- void Video::Camera(string fileName)
- {
- cap = VideoCapture(0);
- if (!cap.isOpened())
- {
- cout << "摄像头打开失败!" << endl;
- return;
- }
- int w = cap.get(CAP_PROP_FRAME_WIDTH);
- int h = cap.get(CAP_PROP_FRAME_HEIGHT);
- save.open(fileName, VideoWriter::fourcc('M', 'J', 'P', 'G'), 30, Size(w, h), true);
- Mat img;
- while (true)
- {
- cap >> img;
- imshow("摄像头", img);
- save << img;
- if (waitKey(10) == 27)
- {
- break;
- }
- }
- }
-
-
- int main()
- {
- Video* pvideo = new Video;
- pvideo->GetVideo();
- pvideo->SaveToImg();
- //刚才读到的video已经全部流出去了。
- pvideo->GetVideo();
- pvideo->SaveToVideo();
-
- pvideo->Camera();
- delete pvideo;
- return 0;
- }
滑动条(Trackbar)是opencv动态调节参数特别好用的一种工具,虽然看起来着实有点丑
- int createTrackbar(const String& trackbarname, const String& winname,int* value, int count,TrackbarCallback onChange = 0,void* userdata = 0);
- /*******************************************************************
- * trackbarname: 滑动条名字
- * winname: 依附窗口名
- * value: 滑块位置
- * count: 滑块最大值(最小值是0)
- * onChange: 滑块回调函数
- * userdata: 用户回传给回调函数的数据
- *********************************************************************/
- typedef void (*TrackbarCallback)(int pos, void* userdata);
- void On_Trackbar(int pos, void* userdata);
- /*******************************************************************
- * pos: 位置
- * userdata: 用户回传给回调函数的数据
- *********************************************************************/
① 主要实现滑动条回调函数,然后直接调用createTrackerbar函数即可。
②下面主要实现,亮度条的调节滑动条---->本质上通过at函数提高每个像素点的像素值即可.
- //滑块 去操作一张图片的像素点,改变图片的连读即可
- #include
- #include
- #include
- using namespace std;
- using namespace cv;
- class TrackBar
- {
- public:
- TrackBar() :img(imread("mm.jpg")), curBright(6), maxBright(30)
- {
- }
- void Show(string wName = "trackBar")
- {
- imshow(wName, img);
- }
- int* GetData()
- {
- return &curBright;
- }
- int GetMaxBright()
- {
- return maxBright;
- }
- static void On_Trackbar(int pos, void* userdata);
- private:
- Mat img;
- int curBright;
- int maxBright;
- };
- void TrackBar::On_Trackbar(int pos, void* userdata)
- {
- TrackBar* pBar = (TrackBar*)userdata;
- if (!pBar->img.data)
- {
- return;
- }
- int rows = pBar->img.rows;
- int cols = pBar->img.cols;
- int dims = pBar->img.channels();
- cout << dims << endl;
- Mat mat = Mat::zeros(pBar->img.size(), pBar->img.type());
- float beta = 30;
- float alpha = 0.1f + (float)pBar->curBright / 10.0;
- for (int i = 0; i < rows; i++)
- {
- for (int j = 0; j < cols; j++)
- {
- if (dims == 1)
- {
- float bgr = pBar->img.at
(i, j); - mat.at
(i, j) = saturate_cast(bgr * alpha + beta); - }
- else if (dims == 3)
- {
- float g = pBar->img.at
(i, j)[0]; - float b = pBar->img.at
(i, j)[1]; - float r = pBar->img.at
(i, j)[2]; - mat.at
(i, j)[0] = saturate_cast(g * alpha + beta); - mat.at
(i, j)[1] = saturate_cast(b * alpha + beta); - mat.at
(i, j)[2] = saturate_cast(r * alpha + beta); - }
- else
- return;
- }
- }
- imshow("trackBar", mat);
- }
- int main()
- {
- TrackBar* pBar = new TrackBar;
- namedWindow("trackBar");
- createTrackbar("亮度调整", "trackBar", pBar->GetData(), pBar->GetMaxBright(), &TrackBar::On_Trackbar, pBar);
- waitKey(0);
- return 0;
- }