编辑器:Visual Studio2022
OpenCV版本:4.5.4
点击完成后,项目创建完成。界面如下:
点击"本地Windows调试器",即可运行,运行结果如下:
下载地址:https://opencv.org/releases/
安装:无脑下一步(记住opencv的安装路径)
安装完成后,opencv目录下有build和sources两个文件夹,build是我们需要使用的,build文件夹内容见下图
右击项目,选择"在文件资源管理器中打开文件夹"
将opencv/build/include目录复制到项目的目录下
将opencv/build/x64/vc15/lib目录复制到项目的目录下
复制完后的目录如下:
回到项目,点击重新生成,打开生成exe所在的目录
将opencv\build\x64\vc15\bin目录下的opencv_videoio_ffmpeg454_64.dll
,opencv_world454d.dll
文件都拷贝到exe所在目录。
拷贝好的项目目录如下:
库目录:
选择刚才拷贝的lib文件,确定
回到上一层,点击应用。
头文件:
同理添加头文件。
链接器:
在链接器中添加opencv_world454d.lib
(直接粘贴即可)
点击应用确定。至此Opencv开发环境配置完成。
回到项目主界面,双击确定,进入代码
编辑确定按钮的代码,代码内容如下
void CopencvDemoDlg::OnBnClickedOk()
{
//1.从摄像头读入视频
VideoCapture cap(0);
//2.循环显示每一帧
while (1)
{
Mat cam;
cap >> cam;//获取当前帧图像
imshow("相机", cam);//显示当前帧图像
waitKey(30);//延时30秒
}
}
拉到项目最上方,添加头文件
#include
#include
using namespace std;
using namespace cv;
从左侧的工具栏中选择Picture Control,拖动到窗口中,调整大小,移动到合适位置,效果如下图
点击完成后,双击页面的确定,重新编写代码,代码如下
void CopencvDemoDlg::OnBnClickedOk()
{
//将opencv的窗体嵌入到页面中
cv::namedWindow("picView", cv::WINDOW_AUTOSIZE);
HWND hWnd = (HWND)cvGetWindowHandle("picView");
HWND hParent = ::GetParent(hWnd);
::SetParent(hWnd, GetDlgItem(IDC_PIC)->m_hWnd);
::ShowWindow(hParent, SW_HIDE);
//1.从摄像头读入视频
VideoCapture cap(0);
//2.循环显示每一帧
while (1)
{
Mat cam;
cap >> cam;//获取当前帧图像
imshow("picView", cam);//显示当前帧图像
waitKey(30);//延时30秒
}
}
将鼠标移动至对话框右下角,左击(不松开)鼠标,往右下角拖动,放大窗口,放大后的效果如下图
左击(不松开)工具箱的Button控件,拖动到右侧的对话框后,松开鼠标左键
同理再添加4个按钮,效果如图
参照3.6.5 章节,修改按钮的显示名称。
名称 | 显示文字 | 变量 |
---|---|---|
按钮1 | 关闭监控 | |
按钮2 | 录像 | |
按钮3 | 录像结束 | |
按钮4 | 播放视频 | |
按钮5 | 打开照片所在目录 |
打开项目对话框的头文件
(opencvDemoDlg.h),在头文件中定义静态变量
static bool closeFlag;//关闭监控标志
static bool takePhotoFlag;//拍照标志
static bool recordFlag;//录像标志
打开项目对话框的cpp文件
(opencvDemoDlg.cpp),在cpp文件中声明变量。
下图中的folderPath为全局变量,closeFlag、takePhotoFlag 、recordFlag三个变量为静态变量(静态变量的定义为类名::变量名
)
//关闭监控标志
bool CopencvDemoDlg::closeFlag = false;
//拍照标志
bool CopencvDemoDlg::takePhotoFlag = false;
//录像标志
bool CopencvDemoDlg::recordFlag = false;
//图片、视频默认存储位置
CString folerPath = L"c:/record/";
回到资源视图,打开主对话框,双击关闭监控
按钮,添加如下代码
void CopencvDemoDlg::OnBnClickedButton1()
{
// closeFlag置为true,关闭实时监控
CopencvDemoDlg::closeFlag = true;
}
同理,双击实时监控
,添加如下代码
//当用户点机实时监控,将closeFlag置为false
CopencvDemoDlg::closeFlag = false;
//此处代码省略
//如果CloseFlag为true,跳出循环,结束监控
if (CopencvDemoDlg::closeFlag) break;
至此已经实现监控、关闭监控功能,至此点击运行项目,测试开启和关闭功能。
尝试发现,当第一次关闭再打开后,只有摄像头再亮,视频不显示。原因是我们创建的picView窗体已被销毁。解决方案只需要确保我们每次打开的窗体名称不同即可,此时可以使用时间来命名窗口。
void CopencvDemoDlg::OnBnClickedOk()
{
//获取当前时间日期
CTime m_time;
m_time = CTime::GetCurrentTime();
//通过格式化日期,构建View名称
CString viewTime = m_time.Format(_T("%Y%m%d%H%M%Sview"));
//将CString转换为string类型
string viewTitleString = CT2A(viewTime.GetBuffer());
//将string类型转为char*
char* viewName = (char*)viewTitleString.data();
//当用户点机实时监控,将closeFlag置为false
CopencvDemoDlg::closeFlag = false;
//将opencv的窗体嵌入到页面中
cv::namedWindow(viewName, cv::WINDOW_AUTOSIZE);
HWND hWnd = (HWND)cvGetWindowHandle(viewName);
HWND hParent = ::GetParent(hWnd);
::SetParent(hWnd, GetDlgItem(IDC_PIC)->m_hWnd);
::ShowWindow(hParent, SW_HIDE);
//1.从摄像头读入视频
VideoCapture cap(0);
//2.循环显示每一帧
while (1)
{
Mat cam;
cap >> cam;//获取当前帧图像
imshow(viewName, cam);//显示当前帧图像
//如果CloseFlag为true,跳出循环,结束监控
if (CopencvDemoDlg::closeFlag) break;
waitKey(30);//延时30秒
}
}
回到资源视图,打开主对话框,双击拍照
按钮,添加如下代码
void CopencvDemoDlg::OnBnClickedPhoto()
{
// TODO: 在此添加控件通知处理程序代码
takePhotoFlag = true;
}
//拍照
if (takePhotoFlag)
{
//拍照状态重置
takePhotoFlag = false;
//生成并转换照片名称
m_time = CTime::GetCurrentTime();
CString m_strDateTime = folerPath + m_time.Format(_T("%Y%m%d%H%M%S.jpg"));
string name = CT2A(m_strDateTime.GetBuffer());
//将Mat数据写入文件
bool res = imwrite(name, cam);
}
拍照功能至此完成,运行项目,点击实时监控
后,点击拍照
即可实现拍照。拍摄的照片可在C:\record
目录下查看。
回到资源视图,打开主对话框,双击打开照片所在位置
按钮,添加如下代码
CreateDirectory(folerPath, NULL);
ShellExecute(NULL, NULL, folerPath, NULL, NULL, SW_SHOW);
回到资源视图,打开主对话框,双击录像
按钮,添加如下代码
//开启摄像头
VideoCapture capture(0);
// 获取视频参数
int width = capture.get(CAP_PROP_FRAME_WIDTH);
int height = capture.get(CAP_PROP_FRAME_HEIGHT);
int count = capture.get(CAP_PROP_FRAME_COUNT);
double fps = capture.get(CAP_PROP_FPS);
//生成录制文件名
CTime m_time;
m_time = CTime::GetCurrentTime();
CString videoNameCString = folerPath + m_time.Format(_T("%Y%m%d%H%M%S.avi")); //格式化日期时间
string videoName = CT2A(videoNameCString.GetBuffer());
//实例化VideoWriter对象
VideoWriter writer(videoName, VideoWriter::fourcc('D', 'I', 'V', 'X'), 30, Size(width, height), true);
//生成实时监控名
Mat frame;
CString viewNameCString = folerPath + m_time.Format(_T("%Y%m%d%H%M%SView"));
string viewNameString = CT2A(viewNameCString.GetBuffer());
//opencv嵌入到mfc中
char* viewName = (char*)viewNameString.data();
cv::namedWindow(viewName, cv::WINDOW_AUTOSIZE);
HWND hWnd = (HWND)cvGetWindowHandle(viewName);
HWND hParent = ::GetParent(hWnd);
::SetParent(hWnd, GetDlgItem(IDC_PIC)->m_hWnd);
::ShowWindow(hParent, SW_HIDE);
//循环播放并录制
while (true) {
//读帧数据,显示数据
capture.read(frame);
flip(frame, frame, 1);
if (frame.empty()) break;
imshow(viewName, frame);
//帧写入视频文件
writer.write(frame);
waitKey(30);
if (recordFlag) break;
}
//重置录制状态
recordFlag = false;
//释放写视频对象
writer.release();
回到资源视图,打开主对话框,双击录像结束
按钮,添加如下代码
recordFlag = true;
录像功能至此结束,运行项目,点击录像
,等待一段时间,点击结束录像
,录像完成。
回到资源视图,打开主对话框,双击播放视频
按钮,添加如下代码
// 公共对话框结构。
OPENFILENAME ofn;
// 保存获取文件名称的缓冲区。
TCHAR szFile[MAX_PATH];
// 初始化选择文件对话框。
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"All(*.*)\0*.*\0Text(*.txt)\0*.AVI\0\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
//ofn.lpTemplateName = MAKEINTRESOURCE(ID_TEMP_DIALOG);
// 显示打开选择文件对话框。
if (GetOpenFileName(&ofn))
{
//显示选择的文件。
OutputDebugString(szFile);
playAVI(szFile);
}
在函数外,添加PlayAVI的实现
void CopencvDemoDlg::playAVI(CString cfileName)
{
CTime m_time;
m_time = CTime::GetCurrentTime(); //获取当前时间日期
CString viewTime = m_time.Format(_T("%Y%m%d%H%M%Sview"));
string viewNameString = CT2A(viewTime.GetBuffer());
char* viewName = (char*)viewNameString.data();
cv::namedWindow(viewName, cv::WINDOW_AUTOSIZE);
HWND hWnd = (HWND)cvGetWindowHandle(viewName);
HWND hParent = ::GetParent(hWnd);
::SetParent(hWnd, GetDlgItem(IDC_PIC)->m_hWnd);
::ShowWindow(hParent, SW_HIDE);
string fileName = CT2A(cfileName.GetBuffer());
VideoCapture capture(fileName);
while (true) {
Mat frame;
Mat edge;
capture >> frame;
if (frame.empty())
break;
cvtColor(frame, edge, COLOR_BGR2GRAY);
imshow(viewName, frame);
//等待50ms,如果从键盘输入的是q、Q、或者是Esc键,则退出
int key = waitKey(50);
if (key == 'q' || key == 'Q' || key == 27)
break;
}
}
打开项目的头文件(opencvDemoDlg.h),添加PlayAVI的声明
void playAVI(CString cfileName);//播放avi视频