北京时间:2019年5月8日  15时33分

因毕设要求,实现一个视频跟踪算法,算法实现了,现在实现界面化,用opencv2.4.9+MFC实现。

一、创建一个简单的MFC界面

添加控件,一个PICTURE CONTROL 和两个 BUTTON。

二、添加CvvImage.h和CvvImage.cpp

CvvImage.h和CvvImage.cpp的定义参见附录。

三、在头文件添加定义

包含头文件:

#include "opencv2/highgui/highgui.hpp"
#include "CvvImage.h"
#include "afxcmn.h"
using namespace cv;

定义变量:

private:       CRect rect;CStatic* pStc; //标识图像显示的Picture控件CDC* pDC; //视频显示控件设备上下文HDC hDC; //视频显示控件设备句柄CvCapture* capture; //视频获取结构

如下图。

四、设置回调函数实现播放

1、什么是回调函数?     通俗理解“回调函数”

2、什么是定时器?怎么通过定时器设置回调函数? 怎么使用SetTime( )函数

添加定时器

在类向导中添加定时器。

在OnInitDialog()中添加

pStc=(CStatic *)GetDlgItem(IDC_VIDEO);//IDC_VIDEO为Picture控件ID
pStc->GetClientRect(&rect);//将CWind类客户区的坐标点传给矩形
pDC=pStc->GetDC(); //得到Picture控件设备上下文
hDC=pDC->GetSafeHdc(); //得到控件设备上下文的句柄

onTimer函数如下:

void CplayVideoDlg::OnTimer(UINT_PTR nIDEvent)
{// TODO: 在此添加消息处理程序代码和/或调用默认值IplImage* m_Frame;  m_Frame=cvQueryFrame(capture);  //从视频中取出一幅图像CvvImage m_CvvImage;  m_CvvImage.CopyOf(m_Frame,1);     m_CvvImage.DrawToHDC(hDC, &rect);  //通过句柄hDC,显示CDialogEx::OnTimer(nIDEvent);
}

添加play按钮的函数

void CplayVideoDlg::OnBnClickedButton1()
{capture = cvCaptureFromCAM(0);//打开摄像头//capture = cvCaptureFromFile("D://1.mp4"); //播放本地文件if (!capture){MessageBox(L"无法获得摄像头");fprintf(stderr, "Can not open camera.\n");return;}SetTimer(1,100,NULL);//设置定时器,视频刷新定时器,决定了帧率
}

这样就可以了,也可以把SetTimer(1,100,NULL);改为SetTimer(1,5000,callbackFunction);callbackFunction为自己写的回调函数。

自定义的回调函数如下:

void CALLBACK Func(HDC hDC, CRect rect, CvCapture* capture,bool isplay)
{while(isplay)//isplay 在头文件定义{IplImage* m_Frame;  m_Frame=cvQueryFrame(capture);  //从视频中取出一幅图像CvvImage m_CvvImage;  m_CvvImage.CopyOf(m_Frame,1);     m_CvvImage.DrawToHDC(hDC, &rect);  //通过句柄hDC,显示}
}void CplayVideoDlg::OnBnClickedButton1()
{capture = cvCaptureFromCAM(0);//打开摄像头//capture = cvCaptureFromFile("D://1.mp4"); //播放本地文件if (!capture){MessageBox(L"无法获得摄像头");fprintf(stderr, "Can not open camera.\n");return;}isplay=true;Func(hDC,rect,capture,isplay);//SetTimer(1,100,Func);//设置定时器,视频刷新定时器,决定了帧率
}

附录

//CvvImage.h

#pragma once
#ifndef CVVIMAGE_CLASS_DEF
#define CVVIMAGE_CLASS_DEF
#include "opencv.hpp"
/* CvvImage class definition */
class  CvvImage
{
public:CvvImage();virtual ~CvvImage();/* Create image (BGR or grayscale) */virtual bool  Create( int width, int height, int bits_per_pixel, int image_origin = 0 );/* Load image from specified file */virtual bool  Load( const char* filename, int desired_color = 1 );/* Load rectangle from the file */virtual bool  LoadRect( const char* filename,int desired_color, CvRect r );
#if defined WIN32 || defined _WIN32virtual bool  LoadRect( const char* filename,int desired_color, RECT r ){return LoadRect( filename, desired_color,cvRect( r.left, r.top, r.right - r.left, r.bottom - r.top ));}
#endif/* Save entire image to specified file. */virtual bool  Save( const char* filename );/* Get copy of input image ROI */virtual void  CopyOf( CvvImage& image, int desired_color = -1 );virtual void  CopyOf( IplImage* img, int desired_color = -1 );IplImage* GetImage() { return m_img; };virtual void  Destroy(void);/* width and height of ROI */int Width() { return !m_img ? 0 : !m_img->roi ? m_img->width : m_img->roi->width; };int Height() { return !m_img ? 0 : !m_img->roi ? m_img->height : m_img->roi->height;};int Bpp() { return m_img ? (m_img->depth & 255)*m_img->nChannels : 0; };virtual void  Fill( int color );/* draw to highgui window */virtual void  Show( const char* window );#if defined WIN32 || defined _WIN32/* draw part of image to the specified DC */virtual void  Show( HDC dc, int x, int y, int width, int height,int from_x = 0, int from_y = 0 );/* draw the current image ROI to the specified rectangle of the destination DC */virtual void  DrawToHDC( HDC hDCDst, RECT* pDstRect );
#endif
protected:IplImage*  m_img;
};
typedef CvvImage CImage;
#endif

//CvvImage.cpp

#include "StdAfx.h"
#include "CvvImage.h"
//
// Construction/Destruction
//
CV_INLINE RECT NormalizeRect( RECT r );
CV_INLINE RECT NormalizeRect( RECT r )
{int t;if( r.left > r.right ){t = r.left;r.left = r.right;r.right = t;}if( r.top > r.bottom ){t = r.top;r.top = r.bottom;r.bottom = t;}return r;
}
CV_INLINE CvRect RectToCvRect( RECT sr );
CV_INLINE CvRect RectToCvRect( RECT sr )
{sr = NormalizeRect( sr );return cvRect( sr.left, sr.top, sr.right - sr.left, sr.bottom - sr.top );
}
CV_INLINE RECT CvRectToRect( CvRect sr );
CV_INLINE RECT CvRectToRect( CvRect sr )
{RECT dr;dr.left = sr.x;dr.top = sr.y;dr.right = sr.x + sr.width;dr.bottom = sr.y + sr.height;return dr;
}
CV_INLINE IplROI RectToROI( RECT r );
CV_INLINE IplROI RectToROI( RECT r )
{IplROI roi;r = NormalizeRect( r );roi.xOffset = r.left;roi.yOffset = r.top;roi.width = r.right - r.left;roi.height = r.bottom - r.top;roi.coi = 0;return roi;
}
void  FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin )
{assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);memset( bmih, 0, sizeof(*bmih));bmih->biSize = sizeof(BITMAPINFOHEADER);bmih->biWidth = width;bmih->biHeight = origin ? abs(height) : -abs(height);bmih->biPlanes = 1;bmih->biBitCount = (unsigned short)bpp;bmih->biCompression = BI_RGB;if( bpp == 8 ){RGBQUAD* palette = bmi->bmiColors;int i;for( i = 0; i < 256; i++ ){palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;palette[i].rgbReserved = 0;}}
}
CvvImage::CvvImage()
{m_img = 0;
}
void CvvImage::Destroy()
{cvReleaseImage( &m_img );
}
CvvImage::~CvvImage()
{Destroy();
}
bool  CvvImage::Create( int w, int h, int bpp, int origin )
{const unsigned max_img_size = 10000;if( (bpp != 8 && bpp != 24 && bpp != 32) ||(unsigned)w >=  max_img_size || (unsigned)h >= max_img_size ||(origin != IPL_ORIGIN_TL && origin != IPL_ORIGIN_BL)){assert(0); // most probably, it is a programming errorreturn false;}if( !m_img || Bpp() != bpp || m_img->width != w || m_img->height != h ){if( m_img && m_img->nSize == sizeof(IplImage))Destroy();/* prepare IPL header */m_img = cvCreateImage( cvSize( w, h ), IPL_DEPTH_8U, bpp/8 );}if( m_img )m_img->origin = origin == 0 ? IPL_ORIGIN_TL : IPL_ORIGIN_BL;return m_img != 0;
}
void  CvvImage::CopyOf( CvvImage& image, int desired_color )
{IplImage* img = image.GetImage();if( img ){CopyOf( img, desired_color );}
}
#define HG_IS_IMAGE(img)                                                  \((img) != 0 && ((const IplImage*)(img))->nSize == sizeof(IplImage) && \((IplImage*)img)->imageData != 0)
void  CvvImage::CopyOf( IplImage* img, int desired_color )
{if( HG_IS_IMAGE(img) ){int color = desired_color;CvSize size = cvGetSize( img ); if( color < 0 )color = img->nChannels > 1;if( Create( size.width, size.height,(!color ? 1 : img->nChannels > 1 ? img->nChannels : 3)*8,img->origin )){cvConvertImage( img, m_img, 0 );}}
}
bool  CvvImage::Load( const char* filename, int desired_color )
{IplImage* img = cvLoadImage( filename, desired_color );if( !img )return false;CopyOf( img, desired_color );cvReleaseImage( &img );return true;
}
bool  CvvImage::LoadRect( const char* filename,int desired_color, CvRect r )
{if( r.width < 0 || r.height < 0 ) return false;IplImage* img = cvLoadImage( filename, desired_color );if( !img )return false;if( r.width == 0 || r.height == 0 ){r.width = img->width;r.height = img->height;r.x = r.y = 0;}if( r.x > img->width || r.y > img->height ||r.x + r.width < 0 || r.y + r.height < 0 ){cvReleaseImage( &img );return false;}/* truncate r to source image */if( r.x < 0 ){r.width += r.x;r.x = 0;}if( r.y < 0 ){r.height += r.y;r.y = 0;}if( r.x + r.width > img->width )r.width = img->width - r.x;if( r.y + r.height > img->height )r.height = img->height - r.y;cvSetImageROI( img, r );CopyOf( img, desired_color );cvReleaseImage( &img );return true;
}
bool  CvvImage::Save( const char* filename )
{if( !m_img )return false;cvSaveImage( filename, m_img );return true;
}
void  CvvImage::Show( const char* window )
{if( m_img )cvShowImage( window, m_img );
}
void  CvvImage::Show( HDC dc, int x, int y, int w, int h, int from_x, int from_y )
{if( m_img && m_img->depth == IPL_DEPTH_8U ){uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];BITMAPINFO* bmi = (BITMAPINFO*)buffer;int bmp_w = m_img->width, bmp_h = m_img->height;FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );from_x = MIN( MAX( from_x, 0 ), bmp_w - 1 );from_y = MIN( MAX( from_y, 0 ), bmp_h - 1 );int sw = MAX( MIN( bmp_w - from_x, w ), 0 );int sh = MAX( MIN( bmp_h - from_y, h ), 0 );SetDIBitsToDevice(dc, x, y, sw, sh, from_x, from_y, from_y, sh,m_img->imageData + from_y*m_img->widthStep,bmi, DIB_RGB_COLORS );}
}
void  CvvImage::DrawToHDC( HDC hDCDst, RECT* pDstRect )
{if( pDstRect && m_img && m_img->depth == IPL_DEPTH_8U && m_img->imageData ){uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];BITMAPINFO* bmi = (BITMAPINFO*)buffer;int bmp_w = m_img->width, bmp_h = m_img->height;CvRect roi = cvGetImageROI( m_img );CvRect dst = RectToCvRect( *pDstRect );if( roi.width == dst.width && roi.height == dst.height ){Show( hDCDst, dst.x, dst.y, dst.width, dst.height, roi.x, roi.y );return;}if( roi.width > dst.width ){SetStretchBltMode(hDCDst,           // handle to device contextHALFTONE );}else{SetStretchBltMode(hDCDst,           // handle to device contextCOLORONCOLOR );}FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );::StretchDIBits(hDCDst,dst.x, dst.y, dst.width, dst.height,roi.x, roi.y, roi.width, roi.height,m_img->imageData, bmi, DIB_RGB_COLORS, SRCCOPY );}
}
void  CvvImage::Fill( int color )
{cvSet( m_img, cvScalar(color&255,(color>>8)&255,(color>>16)&255,(color>>24)&255) );
}

参考博客地址:

https://blog.csdn.net/xiabodan/article/details/41355845

https://blog.csdn.net/angciyu/article/details/80794273

https://www.cnblogs.com/lingc/p/3380919.html

MFC 利用opencv实现视频播放相关推荐

  1. 【opencv八】利用opencv加快视频播放速度,并保存avi视频文件

    在许多应用的需求中,希望将输入,或捕获图像记录到输出视频流中,并保存成一个完整的视频,OpenCV提供了一种简单的方法.正如[opencv四]利用opencv读取显示视频和[opencv七]利用ope ...

  2. 利用opencv结合mfc实现识别圆形标记点并计算多个圆形标记点的三维坐标,拟合平面并计算法向量

    利用opencv结合mfc实现识别圆形标记点并计算多个圆形标记点的三维坐标,拟合平面并计算法向量 具体步骤 二.对应代码 1.引入库 2.标定 识别圆形标记点 左右图像中圆形标记点匹配 计算三维坐标 ...

  3. 利用OpenCV实现人脸检测

    如何在一副图片中检测到人脸,这涉及到计算机图形学中一些非常复杂的计算,如果这些计算都靠程序员自己来编程,那么工作量就相当大.OpenCV全称是Open Computer Vision,是指开放的计算机 ...

  4. 【QT课程设计】五:部分内容修正、利用opencv读入视频并进行部分图像处理

    文章目录 前置文章与导航索引 前言 错误修正 伽马变换数值问题 错误描述 错误修改过程 视频部分 布局设计 opencv的使用 opencv的编译&配置 打开视频 Qtimer简介 视频读取 ...

  5. Opencv 简单视频播放器

    最近看了一下[1]_2011_OpenCV 2 Computer Vision Application Programming Cookbook.pdf,写了一个利用Opencv库实现的简单视频播放器 ...

  6. python如何实现找图_利用OpenCV和Python实现查找图片差异

    使用OpenCV和Python查找图片差异 flyfish 方法1 均方误差的算法(Mean Squared Error , MSE) 下面的一些表达与<TensorFlow - 协方差矩阵&g ...

  7. 利用OpenCV、Python和Ubidots构建行人计数器程序(附完整代码)

    作者 | Jose Garcia 译者 | 吴振东 校对 | 张一豪.林亦霖,编辑 | 于腾凯 来源 | 数据派(ID:datapi) 导读:本文将利用OpenCV,Python和Ubidots来编写 ...

  8. 利用OpenCV识别玻璃纤维织物劈缝缺陷

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 玻璃纤维织物是经编多轴向织物,由一层或多层平行的纱线按照尽可能多的 ...

  9. opencv resize_利用OpenCV 识别两张相似的图片

    Background: 在我们项目中,用到U-net,我们对训练样本图片使用labelme进行标定,对标定生成的json文件labelme_json_to_dataset生成标注图像,由于小伙伴将生成 ...

最新文章

  1. 大脑模拟NLP,高德纳奖得主Papadimitriou:神经元集合演算用于句子解析
  2. piblog 0.2
  3. java垃圾回收根对象_Java垃圾回收怎么理解?
  4. C语言试题十六之写删除字符串中指定下标的字符。其中,a指向原字符串,删除后的字符串存放在b所指的数组中,n中存放指定的下标。
  5. 汇编语言(三十)之多模块求和
  6. pythonxml库_对python 生成拼接xml报文的示例详解
  7. --------------比大小---------------大数比大小 这个方法 值得 留念
  8. vue-cli 体验
  9. 【踩坑速记】二次依赖?android studio编译运行各种踩坑解决方案,杜绝弯路,总有你想要的~...
  10. 10.第十一章.风险管理
  11. 全面开创城市数字经济新时代
  12. 关于荣耀che1-cl20手机制作服务器失败的事
  13. 软件开发流程有哪些?完整的软件开发流程
  14. CSAPP实验1:Data Lab笔记
  15. 【2018,中国智能+】新智元10万+热文排行,AI爆发没有看客
  16. Spark hadoop票据过期问题HDFS_DELEGATION_TOKEN
  17. 【搜集】前端面试题总结
  18. 自动驾驶 11-1: 光检测和测距传感器LIDAR Light Detection and Ranging Sensors
  19. 基于机器学习的2022卡塔尔世界杯冠军预测-个人期末项目总结
  20. java 简易购物车

热门文章

  1. PYNQ(ZYNQ)入门资料合集1
  2. 第1-7课:基础开胃菜
  3. PBFT -Golang实现详解
  4. License Code of Jigloo序列号、注册码,可能是通用的呵呵
  5. (附源码)spring boot学生社团管理系统的设计与实现 毕业设计 151109
  6. python基于PHP+MySQL的学生社团管理系统
  7. Windows程序意外挂掉,但显存依然被占用
  8. C#不能直接打开 wod文档,只能保存到本地再打开
  9. Leetcode:剑指 Offer 58 - II. 左旋转字符串(C++)
  10. STM32F103ZE单片机FSMC接口读取NAND Flash芯片K9F1G08U0E的数据时出现数据丢失的解决办法