参考文章:
创建和使用动态链接库(C++): https://msdn.microsoft.com/zh-cn/library/ms235636(v=vs.120).aspx
dll生成与使用: http://blog.csdn.net/elaine_bao/article/details/51784864
C++编译提示error LNK2005/1169 找到一个或多个重定义的符号: http://ask.csdn.net/questions/353139
1. 新建程序,命名
选择dll,导出符号
2. 本人要使用opencv函数调用相机,并在MFC中显示视频,在.h头文件中添加命名空间和类,dll编写完毕,生成解决方案
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 OPENCVDLL_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// OPENCVDLL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef OPENCVDLL_EXPORTS
#define OPENCVDLL_API __declspec(dllexport)
#else
#define OPENCVDLL_API __declspec(dllimport)
#endif
#include
#include
#include
#include
#include
using namespace cv;
// 此类是从 opencvdll.dll 导出的
class OPENCVDLL_API Copencvdll {
public:
Copencvdll(void);
// TODO: 在此添加您的方法。
};
extern OPENCVDLL_API int nopencvdll;
OPENCVDLL_API int fnopencvdll(void);
namespace camera //命名空间
{
class OPENCVDLL_API mycamera
{
public:
//添加一些自己功能函数
};
}
选择基于对话框,点击完成
4. 添加Picture Control空间,ID为IDC_STATIC,添加按钮,ID为IDC_Start
启动调试
5.将cameradll的debug中的dll和lib拷到Videoshow的debug中
将camera.h复制到VideoShow的工程目录下(包含.cpp的文件内)
6. 配置VIdeoShow项目属性
7. 在头文件中添加代码,加载库文件,并声明类,定义Mat对象
// VideoShowDlg.h : 头文件
//
#pragma once
#pragma comment(lib,"camerall.lib")
#include "cameradll.h"
// CVideoShowDlg 对话框
class CVideoShowDlg : public CDialogEx
{
// 构造
public:
CVideoShowDlg(CWnd* pParent = NULL); // 标准构造函数
VideoCapture capture;
camera::mycamera cameras; //声明类
Mat img,midImage;
在对话框初始化添加代码,通过设定父窗口将OpenCV创建的Window与PicControl控件绑定
// CVideoShowDlg 消息处理程序
BOOL CVideoShowDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
//通过设定父窗口将OpenCV创建的Window与PicControl控件绑定
namedWindow(windows_name,WINDOW_AUTOSIZE);
//window_name.c_str();//string.c_str()
HWND hWnd = (HWND) cvGetWindowHandle(windows_name.c_str()); //获得创建的窗口句柄
HWND hParent = ::GetParent(hWnd); //获得其父句柄
::SetParent(hWnd, GetDlgItem(IDC_STATIC)->m_hWnd); //设置创建窗口的父窗口为Picture control控件
::ShowWindow(hParent, SW_HIDE); //将父窗口及其子窗口进行隐藏
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
对话框界面右击,选择类向导,选择消息,WM_TIMER,添加处理程序
定时器添加代码
void CVideoShowDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(1==nIDEvent)
{
if (camera::capture.isOpened())
{
capture>>img;
//以下操作获取图形控件尺寸并以此改变图片尺寸
CRect rect;
GetDlgItem(IDC_STATIC)->GetClientRect(&rect);//获取Picture Control控件的大小
Rect dst(rect.left,rect.top,rect.right,rect.bottom);
resize(img,midImage,cv::Size(rect.Width(),rect.Height()));
imshow(windows_name,midImage);
}
}
CDialogEx::OnTimer(nIDEvent);
}
void CVideoShowDlg::OnBnClickedStart()
{
// TODO: 在此添加控件通知处理程序代码
static int sw=0;
if(sw==0) //打开摄像头
{
GetDlgItem(IDC_Start)->SetWindowText("关闭相机");
capture.open(1);
/* capture.set(CV_CAP_PROP_FRAME_WIDTH, width); //可以设置视频大小
capture.set(CV_CAP_PROP_FRAME_HEIGHT, height);*/
if (!capture.isOpened())
{
AfxMessageBox("请打开相机");
}
// rate=capture.get(CV_CAP_PROP_FPS); //获取视频本身的播放速度
// delay=1000*1.0/rate; //每一帧的延迟和帧率相对应
SetTimer(1,100,NULL); //定时器
}
else //关闭摄像头
{
GetDlgItem(IDC_Start)->SetWindowText("打开视频");
KillTimer(1);
capture.release(); //关闭摄像头
}
sw++;
sw %=2;
}
如果直接把程序在没有opencv或者没有装vs的电脑中运行,会缺少dll库文件,这时需要把相应缺少的拷贝进exe程序所在的文件夹即可
VS2010的MFC的一些库在这个文件下D:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC100.DebugMFC
VS2010的一些动态链接库D:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\redist\Debug_NonRedist\ia64\Microsoft.VC100.DebugCRT
OPENCV的一些库文件D:\Program Files\opencv\build\x86\vc10\bin