海康工业相机驱动

1.新建基于对话框的MFC程序,界面布局如下

2.修改控件ID,为控件绑定变量

3.创建全局变量,构造函数中初始化变量,初始化对话框界面,补齐各控件按钮响应函数

全文程序如下:


// MFC_GrabimageDlg.h : 头文件
//

#pragma once
#include"MvCameraControl.h"
#include "afxwin.h"


// CMFC_GrabimageDlg 对话框
class CMFC_GrabimageDlg : public CDialogEx
{
// 构造
public:
	CMFC_GrabimageDlg(CWnd* pParent = NULL);	// 标准构造函数
   ~CMFC_GrabimageDlg();	// 
// 对话框数据
	enum { IDD = IDD_MFC_GRABIMAGE_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()




public:
	void* handle;//用于存放相机句柄
	MV_SAVE_IAMGE_TYPE m_enSaveImageType;//用于存储保存图片的类型
	MV_DISPLAY_FRAME_INFO stDisplayInfo;//原始数据转换
	int m_imagenum;//图像采集的帧号

	afx_msg void OnBnClickedButtonOpen();
	afx_msg void OnBnClickedButtonClose();
	afx_msg void OnBnClickedButtonGrabimage();
	CStatic m_picture;//PictureCtrl控件变量
	afx_msg void OnBnClickedButtonSave();

	afx_msg void OnBnClickedRadioBmp();
	afx_msg void OnBnClickedRadioIpg();
	afx_msg void OnBnClickedRadioPng();
	afx_msg void OnBnClickedRadioTif();
};
// MFC_GrabimageDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "MFC_Grabimage.h"
#include "MFC_GrabimageDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMFC_GrabimageDlg 对话框



CMFC_GrabimageDlg::CMFC_GrabimageDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CMFC_GrabimageDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    handle = NULL;
	m_enSaveImageType = MV_Image_Bmp;//先默认为bmp格式,后续添加单选按钮来获取,保存的图像类型格式
}

void CMFC_GrabimageDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_PICTURE, m_picture);
}

BEGIN_MESSAGE_MAP(CMFC_GrabimageDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_OPEN, &CMFC_GrabimageDlg::OnBnClickedButtonOpen)
	ON_BN_CLICKED(IDC_BUTTON_CLOSE, &CMFC_GrabimageDlg::OnBnClickedButtonClose)
	ON_BN_CLICKED(IDC_BUTTON_GRABIMAGE, &CMFC_GrabimageDlg::OnBnClickedButtonGrabimage)
	ON_BN_CLICKED(IDC_BUTTON_SAVE, &CMFC_GrabimageDlg::OnBnClickedButtonSave)
	ON_BN_CLICKED(IDC_RADIO_BMP, &CMFC_GrabimageDlg::OnBnClickedRadioBmp)
	ON_BN_CLICKED(IDC_RADIO_IPG, &CMFC_GrabimageDlg::OnBnClickedRadioIpg)
	ON_BN_CLICKED(IDC_RADIO_PNG, &CMFC_GrabimageDlg::OnBnClickedRadioPng)
	ON_BN_CLICKED(IDC_RADIO_TIF, &CMFC_GrabimageDlg::OnBnClickedRadioTif)
END_MESSAGE_MAP()


// CMFC_GrabimageDlg 消息处理程序

BOOL CMFC_GrabimageDlg::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:  在此添加额外的初始化代码

	// 默认选中IDC_RADIO_BMP
	CheckRadioButton(IDC_RADIO_BMP, IDC_RADIO_TIF, IDC_RADIO_BMP);//单选按钮设置


	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CMFC_GrabimageDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CMFC_GrabimageDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFC_GrabimageDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void CMFC_GrabimageDlg::OnBnClickedButtonOpen()
{
	// TODO:  在此添加控件通知处理程序代码
	//https://blog.csdn.net/weixin_44840658/article/details/89174782
	//枚举相机
	//先定义一个设备列表,用来存放枚举到的设备
	MV_CC_DEVICE_INFO_LIST cam_List;//列表 用于存放枚举到的相机列表
	//枚举
	int nRet = MV_OK;
	nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE, &cam_List);
	if (MV_OK != nRet)
	{
		MessageBox(_T("枚举相机失败"));
		return ;
	}
	else//找到相机
	{
		//枚举到相机后,就可以获取到相机的一些设备信息
		//打印设备的SN码、设备名称、制造商
		//获取枚举到的相机数量
		int cam_num = cam_List.nDeviceNum;
		CString str;
		str.Format(_T("相机数量:%d"), cam_num);
		MessageBox(str);
		//留给后边研究,没有运行成功
		MV_CC_DEVICE_INFO* p_cam_Info = cam_List.pDeviceInfo[0];

		//相机相关参数输出
		//PrintDeviceInfo(p_cam_Info);

		//检查指定设备是否可访问
		int MV_A = MV_CC_IsDeviceAccessible(p_cam_Info, MV_ACCESS_Control);
		if (!MV_A)
		{
			MessageBox(_T("设备不允许访问!"));
			return;
		}
		else
		{
			MessageBox(_T("设备允许访问!"));
		}
	}
	//创建相机句柄
	int nRet2 = MV_OK;
	nRet2 = MV_CC_CreateHandle(&handle, cam_List.pDeviceInfo[0]);//枚举相机列表中的第一个相机
	if (MV_OK != nRet2)
	{
		MessageBox(_T("创建句柄失败!"));
		return;
	}
	//打开相机
	int nRet3 = MV_OK;
	nRet3 = MV_CC_OpenDevice(handle);
	if (MV_OK != nRet3)
	{
		MessageBox(_T("相机打开失败!"));
		return;
	}
}




void CMFC_GrabimageDlg::OnBnClickedButtonClose()
{
	// TODO:  在此添加控件通知处理程序代码

	//关闭相机
	int nRet4 = MV_OK;
	nRet4 = MV_CC_CloseDevice(handle);
	if (MV_OK != nRet4)
	{
		MessageBox(_T("相机关闭失败!"));
		return;
	}
	else
	{
		MessageBox(_T("相机关闭成功!"));
	}
	//销毁句柄
	if (handle != NULL)
	{
		MV_CC_DestroyHandle(handle);
		handle = NULL;
	}
}


void CMFC_GrabimageDlg::OnBnClickedButtonGrabimage()
{
	// TODO:  在此添加控件通知处理程序代码


	int nRet = MV_OK;
	//开始取流
	// Start grab image
	nRet = MV_CC_StartGrabbing(handle);
	if (MV_OK != nRet)
	{
		MessageBox(_T("取流失败!!"));
		return ;
	}

	MV_FRAME_OUT stImageInfo = { 0 };
	//MV_DISPLAY_FRAME_INFO stDisplayInfo = { 0 };

	stDisplayInfo = { 0 };


	HWND p_hwnd = m_picture.m_hWnd;//获取控件的窗口句柄
	CRect rect;
	m_picture.GetClientRect(&rect);

	int width = rect.Width();   // 控件的宽度
	int height = rect.Height(); // 控件的高度



    nRet = MV_CC_GetImageBuffer(handle, &stImageInfo, 1000);


	if (nRet == MV_OK)
	{
		CString str;
		str.Format(_T("相机采集图像的宽度:%d"), stImageInfo.stFrameInfo.nWidth);
		MessageBox(str);
		str.Format(_T("相机采集图像的高度:%d"), stImageInfo.stFrameInfo.nHeight);
		MessageBox(str);
		m_imagenum = stImageInfo.stFrameInfo.nFrameNum;
		str.Format(_T("相机采集图像的帧号:%d"), m_imagenum);
		MessageBox(str);


		//将图片显示在PictureCtrl控件窗口上
		if (p_hwnd)
		{
			stDisplayInfo.hWnd = p_hwnd;
			stDisplayInfo.pData = stImageInfo.pBufAddr;// 指向图像数据的指针
			stDisplayInfo.nDataLen = stImageInfo.stFrameInfo.nFrameLen;//数据长度 
			stDisplayInfo.nWidth = stImageInfo.stFrameInfo.nWidth;   // 图像的宽度(像素)

			//stDisplayInfo.nWidth = width; // 图像的宽度(像素)用控件的宽度来代替

			stDisplayInfo.nHeight = stImageInfo.stFrameInfo.nHeight; // 图像的高度(像素
			//stDisplayInfo.nHeight = height;// 图像的高度(像素)用控件的高度来代替

			stDisplayInfo.enPixelType = stImageInfo.stFrameInfo.enPixelType;  // 像素类型,如黑白、RGB、Bayer等

			MV_CC_DisplayOneFrame(handle, &stDisplayInfo);//显示图像
		}


		


		MV_CC_FreeImageBuffer(handle, &stImageInfo);
		//需要用 MV_CC_FreeImageBuffer() 接口将pstFrame内的数据指针权限进行释放
	}
	else
	{
		MessageBox(_T("没有数据!"));
	}
	//停止采集
	// Stop grab image
	nRet = MV_CC_StopGrabbing(handle);
	if (MV_OK != nRet)
	{
		MessageBox(_T("停止采集失败!"));
		return ;
	}

}



CMFC_GrabimageDlg::~CMFC_GrabimageDlg()
{
	handle=NULL;
}

void CMFC_GrabimageDlg::OnBnClickedButtonSave()
{
	// TODO:  在此添加控件通知处理程序代码
	MV_SAVE_IMG_TO_FILE_PARAM stSaveFileParam;
	memset(&stSaveFileParam, 0, sizeof(MV_SAVE_IMG_TO_FILE_PARAM));



	stSaveFileParam.enImageType = m_enSaveImageType; // ch:需要保存的图像类型 | en:Image format to save
	stSaveFileParam.enPixelType = stDisplayInfo.enPixelType;  // ch:相机对应的像素格式 | en:Camera pixel type
	stSaveFileParam.nWidth = stDisplayInfo.nWidth;         // ch:相机对应的宽 | en:Width
	stSaveFileParam.nHeight = stDisplayInfo.nHeight;          // ch:相机对应的高 | en:Height
	stSaveFileParam.nDataLen = stDisplayInfo.nDataLen;
	stSaveFileParam.pData = stDisplayInfo.pData;
	stSaveFileParam.iMethodValue = 0;

	// ch:jpg图像质量范围为(50-99], png图像质量范围为[0-9] | en:jpg image nQuality range is (50-99], png image nQuality range is [0-9]
	if (MV_Image_Bmp == stSaveFileParam.enImageType)
	{
		sprintf_s(stSaveFileParam.pImagePath, 256, "Image_w%d_h%d_fn%03d.bmp", stSaveFileParam.nWidth, stSaveFileParam.nHeight, m_imagenum);

		//这段代码使用了 `sprintf_s` 函数来格式化一个字符串,该字符串将用于存储图像文件的路径。`sprintf_s` 是一个安全版本的 `sprintf` 函数,用于格式化输出到一个字符数组中,它可以防止缓冲区溢出。
		//让我们详细分析一下这段代码:
		//sprintf_s(stSaveFileParam.pImagePath, 256, "Image_w%d_h%d_fn%03d.bmp", stSaveFileParam.nWidth, stSaveFileParam.nHeight, m_stImageInfo.nFrameNum);
		// `stSaveFileParam.pImagePath`: 这是指向字符数组的指针,该数组将用来存储生成的文件路径字符串。这个数组应该足够大以容纳生成的字符串。
		//`256`: 这个数字是 `pImagePath` 指向的字符数组的大小,单位是字节。`sprintf_s` 需要知道目标缓冲区的大小,以避免写入超出边界。
		// `"Image_w%d_h%d_fn%03d.bmp"`: 这是格式化字符串,其中包含占位符 `%d` 和 `%03d`。`%d` 用于插入十进制整数,而 `%03d` 表示一个至少三位数的十进制数,不足部分用前导零填充。
		// `stSaveFileParam.nWidth`: 这是一个整数值,表示图像的宽度,它将被插入到第一个 `%d` 占位符的位置。
		// `stSaveFileParam.nHeight`: 这也是一个整数值,表示图像的高度,它将被插入到第二个 `%d` 占位符的位置。
		// `m_stImageInfo.nFrameNum`: 这是帧号,一个整数值,它将被插入到 `%03d` 占位符的位置,表示图像的序号,并确保至少有三位数字,不足则用零填充。
		//整个字符串 `"Image_w%d_h%d_fn%03d.bmp"` 将会被格式化成类似于 `"Image_w640_h480_fn001.bmp"` 的形式,其中 `w640`、`h480` 和 `fn001` 分别代表图像的宽度、高度和帧号。
		//这样做的目的是为了生成一个唯一的文件名,便于在保存图像时区分不同的图像文件,尤其是当有多张图像需要按顺序保存时。这种格式化字符串的方式在处理大量图像文件或需要动态生成文件名时非常常见。

	}
	else if (MV_Image_Jpeg == stSaveFileParam.enImageType)
	{
		stSaveFileParam.nQuality = 80;
		sprintf_s(stSaveFileParam.pImagePath, 256, "Image_w%d_h%d_fn%03d.jpg", stSaveFileParam.nWidth, stSaveFileParam.nHeight, m_imagenum);
	}
	else if (MV_Image_Tif == stSaveFileParam.enImageType)
	{
		sprintf_s(stSaveFileParam.pImagePath, 256, "Image_w%d_h%d_fn%03d.tif", stSaveFileParam.nWidth, stSaveFileParam.nHeight, m_imagenum);
	}
	else if (MV_Image_Png == stSaveFileParam.enImageType)
	{
		stSaveFileParam.nQuality = 8;
		sprintf_s(stSaveFileParam.pImagePath, 256, "Image_w%d_h%d_fn%03d.png", stSaveFileParam.nWidth, stSaveFileParam.nHeight, m_imagenum);
	}
	
	 int nRet = MV_CC_SaveImageToFile(handle, &stSaveFileParam);
	
	if (MV_OK != nRet)
	{
		MessageBox(_T("图像保存失败!"));
		return;
	}
}



void CMFC_GrabimageDlg::OnBnClickedRadioBmp()
{
	// TODO:  在此添加控件通知处理程序代码
	m_enSaveImageType = MV_Image_Bmp;//设置图片为bmp格式
}


void CMFC_GrabimageDlg::OnBnClickedRadioIpg()
{
	// TODO:  在此添加控件通知处理程序代码
	m_enSaveImageType = MV_Image_Jpeg;//设置图片为jpg格式
}


void CMFC_GrabimageDlg::OnBnClickedRadioPng()
{
	// TODO:  在此添加控件通知处理程序代码
	m_enSaveImageType = MV_Image_Png;//设置图片为png格式
}


void CMFC_GrabimageDlg::OnBnClickedRadioTif()
{
	// TODO:  在此添加控件通知处理程序代码
	m_enSaveImageType = MV_Image_Tif;//设置图片为tif格式
}

你好!配置海康工业相机在Visual Studio中可以按照以下步骤进行: 1. 首先,确保你已经安装了海康工业相机驱动程序,并将相机通过USB或其他适配器连接到计算机上。 2. 打开Visual Studio,并创建一个新的项目或打开现有的项目。 3. 在项目中,右键单击解决方案资源管理器中的项目名称,然后选择“属性”选项。 4. 在项目属性对话框的左侧选择“配置属性”,然后选择“C/C++”选项。 5. 在右侧面板中,选择“常规”选项,并将“附加包含目录”设置为海康工业相机驱动程序的安装目录。例如,如果驱动程序安装在"C:\HKCamera"目录下,那么将该值设置为"C:\HKCamera\Include"。 6. 接下来,在右侧面板中选择“链接器”选项,并选择“常规”子选项。 7. 将“附加库目录”设置为海康工业相机驱动程序的库文件所在的目录。例如,如果库文件位于"C:\HKCamera\Lib"目录下,那么将该值设置为"C:\HKCamera\Lib"。 8. 在右侧面板中选择“链接器”选项,并选择“输入”子选项。 9. 在“附加依赖项”中添加海康工业相机的库文件名。例如,如果你使用的是海康工业相机的静态库文件,那么可以添加"HCNetSDK.lib"。 10. 完成上述配置后,点击“应用”按钮,然后点击“确定”按钮。 现在,你的Visual Studio项目已经配置好了海康工业相机。你可以在代码中使用海康工业相机的函数和API来进行开发和集成。请注意,在使用相机功能之前,你可能需要初始化相机并设置相关的参数。具体的操作可以参考海康工业相机的官方文档或示例代码。 希望对你有所帮助!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值