海康相机驱动(C++)

目录

1.海康相机开发流程

1.1设备连接接口流程(海康相机V3.5.0)

1.2主动取流流程(海康相机V3.5.0)

1.3回调取流流程(海康相机V3.5.0)

2.步骤示例

2.1枚举设备

2.2 创建设备句柄

2.3 打开设备

2.4 开始抓图(开始取流)

2.5 获取一帧并保存图像(此项有点混乱 有待修正)

2.5.1 方式一:

2.5.1方式二:

2.6 停止抓图(停止取流)

2.7 关闭相机设备

2.8 销毁句柄

3.实验源码

hikvision SDK使用(转)-腾讯云开发者社区-腾讯云

4.运行结果


1.海康相机开发流程

使用工业相机采集图像,首先需要对相机的相关参数进行设置。现在项目需要使用SDK进行二次开发。依照以下步骤进行:

1.枚举设备 -> 2.创建句柄 -> 3.打开设备 -> 4.开始抓图 -> 5.获取一帧并保存图像 -> 6.停止抓图 -> 7.关闭设备 -> 8.销毁句柄

1.1 设备连接接口流程(海康相机V3.5.0)

详细步骤

  1. (可选)调用 MV_CC_EnumDevices() 枚举子网内指定传输协议对应的所有设备。 可通过nTLayerType在结构 MV_CC_DEVICE_INFO() 中获取设备信息。
  2. (可选)在打开指定设备前,调用 MV_CC_IsDeviceAccessible() 检查指定设备是否可访问。
  3. 调用 MV_CC_CreateHandle() 创建设备句柄。
  4. 调用 MV_CC_OpenDevice() 打开设备。
  5. (可选)调用 MV_CC_GetAllMatchInfo()以获取设备信息。
  6. 调用 MV_CC_CloseDevice() 关闭设备。
  7. 调用 MV_CC_DestroyHandle() 销毁句柄并释放资源。

1.2 主动取流流程(海康相机V3.5.0)

SDK提供主动获取图像的接口,用户可以在开启取流后直接调用此接口获取图像,也可以使用异步方式(线程、定时器等)获取图像。

 • 主动获取图像有两种方式(两种方式不能同时使用):

    方式一:调用 MV_CC_StartGrabbing() 开始采集,需要自己开启一个buffer,然后在应用层循环调用 MV_CC_GetOneFrameTimeout() 获取指定像素格式的帧数据,获取帧数据时上层应用程序需要根据帧率控制好调用该接口的频率。

    方式二:调用 MV_CC_StartGrabbing() 开始采集,然后在应用层调用 MV_CC_GetImageBuffer() 获取指定像素格式的帧数据,然后调用 MV_CC_FreeImageBuffer() 释放buffer,获取帧数据时上层应用程序需要根据帧率控制好调用该接口的频率。

 • 主动取图方式使用的场景:

主动取图方式需要先调用 MV_CC_StartGrabbing() 启动图像采集。上层应用程序需要根据帧率,控制好调用主动取图接口的频率。两种主动取图方式都支持设置超时时间,SDK内部等待直到有数据时返回,可以增加取流平稳性,适合用于对平稳性要求较高的场合。

 • 两种主动取图方式的区别:

    a、 MV_CC_GetImageBuffer() 需要与 MV_CC_FreeImageBuffer() 配套使用,当处理完取到的数据后,需要用 MV_CC_FreeImageBuffer() 接口将pstFrame内的数据指针权限进行释放。

    b、 MV_CC_GetImageBuffer() 与 MV_CC_GetOneFrameTimeout() 相比,有着更高的效率。且其取流缓存的分配是由sdk内部自动分配的,而 MV_CC_GetOneFrameTimeout() 接口是需要客户自行分配。

 • 注意事项:

    a、两种主动取图方式不能同时使用,且不能与后面的回调取图方式同时使用,三种取图方式只能使用其中一种。

    b、pData返回的是一个地址指针,建议将pData里面的数据copy出来另建线程使用。

详细步骤

  1. (可选)调用 MV_CC_EnumDevices() 枚举子网内指定传输协议对应的所有设备。 可通过nTLayerType在结构 MV_CC_DEVICE_INFO() 中获取设备信息。
  2. (可选)打开指定设备前,调用 MV_CC_IsDeviceAccessible() 检查指定设备是否可访问。
  3. 调用 MV_CC_CreateHandle() 创建设备句柄。
  4. 调用 MV_CC_OpenDevice() 打开设备。
  5. (可选)执行以下一个或多个操作以获取/设置相机不同类型的参数。

     • 获取/设置Int类型节点值   调用 MV_CC_GetIntValue() / MV_CC_SetIntValue()

     • 获取/设置Float类型节点值   调用 MV_CC_GetFloatValue() / MV_CC_SetFloatValue()

     • 获取/设置Enum类型节点值   调用 MV_CC_GetEnumValue() / MV_CC_SetEnumValue()

     • 获取/设置Bool类型节点值   调用 MV_CC_GetBoolValue() / MV_CC_SetBoolValue()

     • 获取/设置String类型节点值   调用 MV_CC_GetStringValue() / MV_CC_SetStringValue()

     • 设置Command类型节点值   调用 MV_CC_SetCommandValue()

  6. 图像采集:

     • (可选)调用 MV_CC_SetImageNodeNum() 设置图像缓存节点个数。当获取的图像数超过这个设定值,最早的图像数据会被自动丢弃。

     • 调用 MV_CC_StartGrabbing() 开始取流。

     • 对于原始图像数据,可调用 MV_CC_ConvertPixelType() 转换图像的像素格式,也可调用 MV_CC_SaveImage() 转换成JPEG或BMP格式的图片,并保存成图片文件。

     • 在应用程序层中重复调用 MV_CC_GetOneFrameTimeout() 来获取图片数据。

  7. 调用 MV_CC_StopGrabbing() 停止采集。
  8. 调用 MV_CC_CloseDevice() 关闭设备。
  9. 调用 MV_CC_DestroyHandle() 销毁句柄并释放资源。

1.3 回调取流流程(海康相机V3.5.0)

SDK提供注册回调函数的接口,用户可以将自己定义的回调函数注册在SDK内部,SDK获取到相机图像会主动回调到应用程序供用户处理,此方式可以简化用户程序逻辑。

 • 回调取图方式使用场景:

    可以使用 MV_CC_RegisterImageCallBackEx() 接口注册回调函数。回调函数可以自定义,用于自动回调获取的图像。此方法可以简化应用程序逻辑。如果你想设置获取RGB24或BGR24格式的图像数据,也可以使用 MV_CC_RegisterImageCallBackForRGB() 或 MV_CC_RegisterImageCallBackForBGR() 来注册回调函数。

 • 注意事项:

    a、回调函数中不建议有耗时操作、线程锁等,容易造成回调阻塞。

    b、pData返回的是一个地址指针,建议将pData里面的数据copy出来另建线程使用。

详细步骤

  1. (可选)调用 MV_CC_EnumDevices() 枚举子网内指定传输协议对应的所有设备。 可通过nTLayerType在结构 MV_CC_DEVICE_INFO() 中获取设备的信息。
  2. (可选)打开指定设备前,调用 MV_CC_IsDeviceAccessible() 检查指定设备是否可访问。
  3. 调用 MV_CC_CreateHandle() 创建设备句柄。
  4. 调用 MV_CC_OpenDevice() 打开设备。
  5. (可选)执行以下一个或多个操作以获取/设置相机不同类型的参数。

     • 获取/设置Int类型节点值   调用 MV_CC_GetIntValue() / MV_CC_SetIntValue()

     • 获取/设置Float类型节点值   调用 MV_CC_GetFloatValue() / MV_CC_SetFloatValue()

     • 获取/设置Enum类型节点值   调用 MV_CC_GetEnumValue() / MV_CC_SetEnumValue()

     • 获取/设置Bool类型节点值   调用 MV_CC_GetBoolValue() / MV_CC_SetBoolValue()

     • 获取/设置String类型节点值   调用 MV_CC_GetStringValue() / MV_CC_SetStringValue()

     • 设置Command类型节点值   调用 MV_CC_SetCommandValue()

  6. 图像采集:

     • (可选)调用 MV_CC_SetImageNodeNum() 设置图像缓存节点个数。当获取的图像数超过这个设定值,最早的图像数据会被自动丢弃。

     • 调用 MV_CC_RegisterImageCallBack() 来设置数据回调函数。

     • 调用 MV_CC_StartGrabbing() 开始采集。

     • 对于原始图像数据,可调用 MV_CC_ConvertPixelType() 转换图像的像素格式,也可以调用 MV_CC_SaveImage() 转换为JPEG或BMP格式图片,并保存成图片文件。

  7. 调用 MV_CC_StopGrabbing() 停止采集。
  8. 调用 MV_CC_CloseDevice() 关闭设备。
  9. 调用 MV_CC_DestroyHandle() 销毁句柄并释放资源。

2.步骤示例

1.枚举设备 -> 2.创建设备句柄 -> 3.打开相机设备 -> 4.开始抓图 -> 5.获取一帧并保存图像 -> 6.停止抓图 -> 7.关闭相机设备 -> 8.销毁句柄

2.1 枚举设备

调用 MV_CC_EnumDevices() 枚举子网内指定传输协议对应的所有设备。

int MV_CC_EnumDevices  ( IN unsigned int  nTLayerType,  
  IN OUT MV_CC_DEVICE_INFO_LIST *  pstDevList ) 
枚举设备 

参数
nTLayerType [IN] 枚举传输层 
按位表示,支持复选,可选协议类型如下所示:
例如:nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE,表示查找GigE和USB3.0设备  

pstDevList [OUT] 设备列表 
 
返回  
成功,返回MV_OK;失败,返回错误码。

#include<iostream>
#include<MvCameraControl.h>
#include "windows.h"


using namespace std;

int main()
{
	//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)
	{
		cout<<"Enum Devices fail! nRet [0x%x]\n"<< nRet<<endl;
		return 0;
	}
	else//找到相机
	{
		//枚举到相机后,就可以获取到相机的一些设备信息
		//打印设备的SN码、设备名称、制造商
		//获取枚举到的相机数量
		int cam_num = cam_List.nDeviceNum;
		cout << "相机数量:" << cam_num << endl;
		//留给后边研究,没有运行成功
		MV_CC_DEVICE_INFO* p_cam_Info = cam_List.pDeviceInfo[0];//相机数量可能有多个,此处只对第一个进行参数访问等
		cout << "相机序列号: " << p_cam_Info->SpecialInfo.stGigEInfo.chSerialNumber << endl;//此处默认为网口相机
		int MV_A = MV_CC_IsDeviceAccessible(p_cam_Info, MV_ACCESS_Control);
		if (!MV_A)
		{
			cout << "设备不允许被访问!" << endl;
		}
		cout << "设备运行被访问" << endl;
	}
}

2.2 创建设备句柄

调用 MV_CC_CreateHandle() 创建设备句柄。

int  MV_CC_CreateHandle  ( OUT void **  handle,IN const MV_CC_DEVICE_INFO *  pstDevInfo) 

创建设备句柄 

参数
handle [OUT] 设备句柄  
pstDevInfo [IN] 设备信息结构体  

返回
成功,返回MV_OK;
失败,返回错误码 。
#include<iostream>
#include<MvCameraControl.h>
#include "windows.h"


using namespace std;



int main()
{
	//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)
	{
		cout<<"Enum Devices fail! nRet [0x%x]\n"<< nRet<<endl;
		return 0;
	}
	else//找到相机
	{
		//枚举到相机后,就可以获取到相机的一些设备信息
		//打印设备的SN码、设备名称、制造商
		//获取枚举到的相机数量
		int cam_num = cam_List.nDeviceNum;
		cout << "相机数量:" << cam_num << endl;
		//留给后边研究,没有运行成功
		MV_CC_DEVICE_INFO* p_cam_Info = cam_List.pDeviceInfo[0];
	
		//相机相关参数输出

		//检查指定设备是否可访问
		int MV_A = MV_CC_IsDeviceAccessible(p_cam_Info, MV_ACCESS_Control);
		if (!MV_A)
		{
			cout << "设备不允许被访问!" << endl;
		}
		cout << "设备运行被访问" << endl;
	}
	//创建相机句柄
	int nRet2 = MV_OK;
	void* handle = NULL;
	nRet2 = MV_CC_CreateHandle(&handle, cam_List.pDeviceInfo[0]);//枚举相机列表中的第一个相机
	if (MV_OK != nRet2)
	{
		cout << "创建句柄失败!nRet2 :" << nRet2 << endl;
		system("pause");
		return 0;
	}
	//打开相机
	//开始取流

	//使用内部缓存获取一帧图片
	//其余操作

	//停止采集
	//关闭相机
	//销毁句柄
	if (handle != NULL)
	{
		MV_CC_DestroyHandle(handle);
		handle = NULL;
	}

	system("pause");
	return 0;
}

2.3 打开设备

调用 MV_CC_OpenDevice() 打开设备。

int  MV_CC_OpenDevice  ( IN void *  handle,  
  IN unsigned int  nAccessMode,  
  IN unsigned short  nSwitchoverKey)  
打开设备 

参数
handle [IN] 设备句柄  
nAccessMode [IN] 访问权限,具体可见下列表格
nSwitchoverKey [IN] 切换访问权限时的密钥  

返回
成功,返回MV_OK;
失败,返回错误码 。 

//打开相机
	int nRet3 = MV_OK;
	nRet3 = MV_CC_OpenDevice(handle);//此处handle参数为MV_CC_CreateHandle创建的相机句柄
	if (MV_OK != nRet3)
	{
		cout << "打开相机失败!nRet3 :" << nRet3 << endl;
		system("pause");
		return 0;
	}

2.4 开始抓图(开始取流)

调用 MV_CC_StartGrabbing() 开始取流。

int MV_CC_StartGrabbing  ( IN void *  handle )  

开始取流 

参数
handle [IN] 设备句柄
  
返回
成功,返回MV_OK;
失败,返回错误码 

备注
该接口不支持CameraLink设备。 
//开始取流
	// Start grab image
	nRet = MV_CC_StartGrabbing(handle);
	if (MV_OK != nRet)
	{
		cout << "取流失败!nRet :" << nRet << endl;
		system("pause");
		return 0;
	}

2.5 获取一帧并保存图像(此项有点混乱 有待修正)

2.5.1 方式一:

调用 MV_CC_StartGrabbing() 开始采集,需要自己开启一个buffer,然后在应用层循环调用 MV_CC_GetOneFrameTimeout() 获取指定像素格式的帧数据,获取帧数据时上层应用程序需要根据帧率控制好调用该接口的频率。

int MV_CC_GetOneFrameTimeout  ( IN void *  handle,  
  IN OUT unsigned char *  pData,  
  IN unsigned int  nDataSize,  
  IN OUT MV_FRAME_OUT_INFO_EX *  pstFrameInfo,  
  unsigned int  nMsec) 
采用超时机制获取一帧图片,SDK内部等待直到有数据时返回
参数

handle [IN] 设备句柄  
pData [OUT] 图像数据接收指针  
nDataSize [IN] 接收缓存大小  
pstFrameInfo [OUT] 图像信息结构体  
nMsec [IN] 等待超时时间 
 
返回
成功,返回MV_OK;
失败,返回错误码 

备注 
• 调用该接口获取图像数据帧之前需要先调用 MV_CC_StartGrabbing() 启动图像采集。该接口为主动式获取帧数据,上层应用程序需要根据帧率,控制好调用该接口的频率。该接口支持设置超时时间,SDK内部等待直到有数据时返回,可以增加取流平稳性,适合用于对平稳性要求较高的场合。
• 该接口对于U3V、GIGE设备均可支持。
• 该接口不支持CameraLink设备。

2.5.1方式二:

调用 MV_CC_StartGrabbing() 开始采集,然后在应用层调用 MV_CC_GetImageBuffer() 获取指定像素格式的帧数据,然后调用 MV_CC_FreeImageBuffer() 释放buffer,获取帧数据时上层应用程序需要根据帧率控制好调用该接口的频率。

应用层调用 MV_CC_GetImageBuffer() 获取指定像素格式的帧数据

int MV_CC_GetImageBuffer  ( IN void *  handle,  
  OUT MV_FRAME_OUT *  pstFrame,  
  IN unsigned int  nMsec)   

使用内部缓存获取一帧图片(与 MV_CC_Display() 不能同时使用) 

参数
handle [IN] 设备句柄  
pstFrame [OUT] 图像数据和图像信息  
nMsec [IN] 等待超时时间,输入INFINITE时表示无限等待,直到收到一帧数据或者停止取流  

返回
成功,返回MV_OK;
失败,返回错误码 

用 MV_CC_FreeImageBuffer() 接口将pstFrame内的数据指针权限进行释放

int  MV_CC_FreeImageBuffer  ( IN void *  handle,  
  IN MV_FRAME_OUT *  pstFrame)   

释放图像缓存(此接口用于释放不再使用的图像缓存,与 MV_CC_GetImageBuffer() 配套使用) 

参数
handle [IN] 设备句柄  
pstFrame [IN] 图像数据和图像数据
  
返回
成功,返回MV_OK;
失败,返回错误码 

备注 
• 该接口与 MV_CC_GetImageBuffer() 配套使用,使用 MV_CC_GetImageBuffer() 接口取到的图像数据pstFrame,需要用 MV_CC_FreeImageBuffer() 接口进行权限释放。 
 
• 该接口对于取流效率高于GetOneFrameTimeout接口,且GetImageBuffer在不进行Free的情况下,最大支持输出的节点数与SetImageNode接口所设置的节点数相等,默认节点数是1。
 
• 该接口对于U3V、GIGE设备均可支持。 
 
• 该接口不支持CameraLink设备。

​​​​​​​​​​​​​​

对于原始图像数据,可调用 MV_CC_ConvertPixelType() 转换图像的像素格式

int  MV_CC_ConvertPixelType  ( IN void *  handle,  
  IN OUT MV_CC_PIXEL_CONVERT_PARAM *  pstCvtParam)   
像素格式转换 

参数
handle [IN] 设备句柄  
pstCvtParam [IN][OUT] 像素格式转换参数结构体
  
返回
成功,返回MV_OK ;
失败,返回错误码 

备注
通过将接口可以将从设备采集到的原始图像数据转换成用户所需的像素格式并存放在指定内存中。该接口调用无接口顺序要求,有图像源数据就可以进行转换,可以先调用 MV_CC_GetOneFrameTimeout() 或者 MV_CC_RegisterImageCallBackEx() 设置回调函数,获取一帧图像数据,然后再通过该接口转换格式。如果设备当前采集图像是JPEG压缩的格式,则不支持调用该接口进行转换。 

​​​​​​​

#include<iostream>
#include<MvCameraControl.h>
#include "windows.h"


using namespace std;


void PrintDeviceInfo(MV_CC_DEVICE_INFO* pstMVDevInfo)
{
	if (NULL == pstMVDevInfo)
	{
		printf("The Pointer of pstMVDevInfo is NULL!\n");
		return;
	}
	if (pstMVDevInfo->nTLayerType == MV_GIGE_DEVICE)
	{
		int nIp1 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24);
		int nIp2 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16);
		int nIp3 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8);
		int nIp4 = (pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);

		// en:print current ip and user defined name
		printf("CurrentIp: %d.%d.%d.%d\n", nIp1, nIp2, nIp3, nIp4);
		cout << "用户自定义名称: " << pstMVDevInfo->SpecialInfo.stGigEInfo.chUserDefinedName << endl;
		cout << "相机序列号: " << pstMVDevInfo->SpecialInfo.stGigEInfo.chSerialNumber << endl;
	}
	else if (pstMVDevInfo->nTLayerType == MV_USB_DEVICE)
	{
		printf("UserDefinedName: %s\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName);
		printf("Serial Number: %s\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chSerialNumber);
		printf("Device Number: %d\n\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.nDeviceNumber);
	}
	else
	{
		printf("Not support.\n");
	}

}

bool IsColor(MvGvspPixelType enType)
{
	switch (enType)
	{
	case PixelType_Gvsp_BGR8_Packed:
	case PixelType_Gvsp_YUV422_Packed:
	case PixelType_Gvsp_YUV422_YUYV_Packed:
	case PixelType_Gvsp_BayerGR8:
	case PixelType_Gvsp_BayerRG8:
	case PixelType_Gvsp_BayerGB8:
	case PixelType_Gvsp_BayerBG8:
	case PixelType_Gvsp_BayerGB10:
	case PixelType_Gvsp_BayerGB10_Packed:
	case PixelType_Gvsp_BayerBG10:
	case PixelType_Gvsp_BayerBG10_Packed:
	case PixelType_Gvsp_BayerRG10:
	case PixelType_Gvsp_BayerRG10_Packed:
	case PixelType_Gvsp_BayerGR10:
	case PixelType_Gvsp_BayerGR10_Packed:
	case PixelType_Gvsp_BayerGB12:
	case PixelType_Gvsp_BayerGB12_Packed:
	case PixelType_Gvsp_BayerBG12:
	case PixelType_Gvsp_BayerBG12_Packed:
	case PixelType_Gvsp_BayerRG12:
	case PixelType_Gvsp_BayerRG12_Packed:
	case PixelType_Gvsp_BayerGR12:
	case PixelType_Gvsp_BayerGR12_Packed:
		return true;
	default:
		return false;
	}
}

bool IsMono(MvGvspPixelType enType)
{
	switch (enType)
	{
	case PixelType_Gvsp_Mono10:
	case PixelType_Gvsp_Mono10_Packed:
	case PixelType_Gvsp_Mono12:
	case PixelType_Gvsp_Mono12_Packed:
		return true;
	default:
		return false;
	}
}





int main()
{
	//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)
	{
		cout<<"Enum Devices fail! nRet [0x%x]\n"<< nRet<<endl;
		return 0;
	}
	else//找到相机
	{
		//枚举到相机后,就可以获取到相机的一些设备信息
		//打印设备的SN码、设备名称、制造商
		//获取枚举到的相机数量
		int cam_num = cam_List.nDeviceNum;
		cout << "相机数量:" << cam_num << endl;
		//留给后边研究,没有运行成功
		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)
		{
			cout << "设备不允许被访问!" << endl;
		}
		cout << "设备运行被访问" << endl;
	}
	//创建相机句柄
	int nRet2 = MV_OK;
	void* handle = NULL;
	nRet2 = MV_CC_CreateHandle(&handle, cam_List.pDeviceInfo[0]);//枚举相机列表中的第一个相机
	if (MV_OK != nRet2)
	{
		cout << "创建句柄失败!nRet2 :" << nRet2 << endl;
		system("pause");
		return 0;
	}
	//打开相机
	int nRet3 = MV_OK;
	nRet3 = MV_CC_OpenDevice(handle);
	if (MV_OK != nRet3)
	{
		cout << "打开相机失败!nRet3 :" << nRet3 << endl;
		system("pause");
		return 0;
	}


	//开始取流
	// Start grab image
	nRet = MV_CC_StartGrabbing(handle);
	if (MV_OK != nRet)
	{
		cout << "取流失败!nRet :" << nRet << endl;
		system("pause");
		return 0;
	}
	创建结构体
	//MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 };
	//nRet = MV_CC_ConvertPixelType(handle, &stConvertParam);
	//if (MV_OK != nRet)
	//{
	//	cout << "图像创建失败!nRet :" << nRet << endl;
	//	system("pause");
	//	return 0;
	//}



	///**************************************/
	使用内部缓存获取一帧图片 
	ConvertPixelType.cpp
	例子来自 ConnectSpecCamera.cpp

	//MV_FRAME_OUT stImageInfo = { 0 };
	//nRet = MV_CC_GetImageBuffer(handle, &stImageInfo, 1000);
	//if (nRet == MV_OK)
	//{
	//	cout << "相机采集图像的宽度:" << stImageInfo.stFrameInfo.nWidth << endl;
	//	cout << "相机采集图像的高度:" << stImageInfo.stFrameInfo.nHeight << endl;
	//	cout << "相机采集图像的帧号:" << stImageInfo.stFrameInfo.nFrameNum << endl;
	//	
	//	//ConvertPixelType.cpp
	//	MV_DISPLAY_FRAME_INFO stDisplayInfo = { 0 };

	//	//HWND g_hWnd = AfxGetMainWnd()->m_hWnd;
	//		//if (g_hwnd)
	//		{
	//		cout << "正在输出" << endl;
	//		//stDisplayInfo.hWnd = GetDesktopWindow();
	//		//GetDesktopWindow该函数返回桌面窗口的句柄;
	//		stDisplayInfo.hWnd = GetForegroundWindow();
	//		//是获取当前系统中被激活的窗口
	//			stDisplayInfo.pData = stImageInfo.pBufAddr;
	//			stDisplayInfo.nDataLen = stImageInfo.stFrameInfo.nFrameLen;
	//			stDisplayInfo.nWidth = stImageInfo.stFrameInfo.nWidth;
	//			stDisplayInfo.nHeight = stImageInfo.stFrameInfo.nHeight;
	//			stDisplayInfo.enPixelType = stImageInfo.stFrameInfo.enPixelType;

	//			MV_CC_DisplayOneFrame(handle, &stDisplayInfo);
	//			//system("pause");
	//		}

	//	//释放指针 MV_CC_GetImageBuffer---&stImageInfo
	//	nRet = MV_CC_FreeImageBuffer(handle, &stImageInfo);
	//	if (nRet != MV_OK)
	//	{
	//		cout << "Free Image Buffer fail! nRet=" << nRet << endl;
	//	}
	//}
	//else
	//{
	//	cout << "No data! nRet=" << nRet << endl;
	//}
	///**************************************/
	unsigned char *pConvertData = NULL;
	unsigned int nConvertDataSize = 0;

	MV_FRAME_OUT stImageInfo = { 0 };

	nRet = MV_CC_GetImageBuffer(handle, &stImageInfo, 1000);
	if (nRet == MV_OK)
	{
		printf("Get One Frame: Width[%d], Height[%d], nFrameNum[%d]\n",
			stImageInfo.stFrameInfo.nWidth, stImageInfo.stFrameInfo.nHeight, stImageInfo.stFrameInfo.nFrameNum);

		MvGvspPixelType enDstPixelType = PixelType_Gvsp_Undefined;
		unsigned int nChannelNum = 0;
		char chFileName[MAX_PATH] = { 0 };
		//If it is color, converted to RGB8 
		if (IsColor(stImageInfo.stFrameInfo.enPixelType))
		{
			nChannelNum = 3;
			enDstPixelType = PixelType_Gvsp_RGB8_Packed;
			sprintf(chFileName, "AfterConvert.rgb");
		}
		//If it's Mono, converted to Mono8 
		else if (IsMono(stImageInfo.stFrameInfo.enPixelType))
		{
			nChannelNum = 1;
			enDstPixelType = PixelType_Gvsp_Mono8;
			sprintf(chFileName, "AfterConvert.gray");
		}
		else
		{
			printf("Don't need to convert!\n");
		}

		if (enDstPixelType != PixelType_Gvsp_Undefined)
		{
			pConvertData = (unsigned char*)malloc(stImageInfo.stFrameInfo.nWidth * stImageInfo.stFrameInfo.nHeight * nChannelNum);
			if (NULL == pConvertData)
			{
				printf("malloc pConvertData fail!\n");
				nRet = MV_E_RESOURCE;
				return;
			}
			nConvertDataSize = stImageInfo.stFrameInfo.nWidth * stImageInfo.stFrameInfo.nHeight * nChannelNum;

			// Convert pixel format 
			MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 };

			stConvertParam.nWidth = stImageInfo.stFrameInfo.nWidth;                 // image width
			stConvertParam.nHeight = stImageInfo.stFrameInfo.nHeight;               // image height
			stConvertParam.pSrcData = stImageInfo.pBufAddr;                         // input data buffer
			stConvertParam.nSrcDataLen = stImageInfo.stFrameInfo.nFrameLen;         // input data size
			stConvertParam.enSrcPixelType = stImageInfo.stFrameInfo.enPixelType;    // input pixel format
			stConvertParam.enDstPixelType = enDstPixelType;                         // output pixel format
			stConvertParam.pDstBuffer = pConvertData;                               // output data buffer
			stConvertParam.nDstBufferSize = nConvertDataSize;                       // output buffer size
			nRet = MV_CC_ConvertPixelType(handle, &stConvertParam);
			if (MV_OK != nRet)
			{
				printf("Convert Pixel Type fail! nRet [0x%x]\n", nRet);
				return;
			}

			FILE* fp = NULL;
			errno_t err = fopen_s(&fp, chFileName, "wb");
			if (0 != err || NULL == fp)
			{
				printf("Open file failed\n");
				nRet = MV_E_RESOURCE;
				return;
			}
			fwrite(stConvertParam.pDstBuffer, 1, stConvertParam.nDstLen, fp);
			fclose(fp);
			printf("Convert pixeltype succeed\n");
		}
		MV_CC_FreeImageBuffer(handle, &stImageInfo);
	}
	else
	{
		printf("No data[0x%x]\n", nRet);
	}








	//
	//停止采集
	// Stop grab image
	nRet = MV_CC_StopGrabbing(handle);
	if (MV_OK != nRet)
	{
		cout << "停止采集失败!nRet :" << nRet << endl;
		system("pause");
		return 0;
	}

	//关闭相机
	int nRet4 = MV_OK;
	nRet4=MV_CC_CloseDevice(handle);
	if (MV_OK != nRet4)
	{
		cout << "关闭相机失败!nRet4 :" << nRet4 << endl;
		return 0;
	}
	//销毁句柄
	if (handle != NULL)
	{
		MV_CC_DestroyHandle(handle);
		handle = NULL;
	}

	cout << "Hello!" << endl;
	system("pause");
	return 0;
}

2.6 停止抓图(停止取流)

调用 MV_CC_StopGrabbing() 停止采集。

int  MV_CC_StopGrabbing  ( IN void *  handle )  

停止取流 

参数
handle [IN] 设备句柄  

返回
成功,返回MV_OK;
失败,返回错误码 

备注
该接口不支持CameraLink设备。 

2.7 关闭相机设备

调用 MV_CC_CloseDevice() 关闭设备。

int  MV_CC_CloseDevice  ( IN void *  handle ) 
关闭设备 

参数
handle [IN] 设备句柄 
 
返回
成功,返回MV_OK;
失败,返回错误码 

备注
通过 MV_CC_OpenDevice() 连接设备后,可以通过该接口断开设备连接,释放资源 
//关闭相机
	int nRet4 = MV_OK;
	nRet4=MV_CC_CloseDevice(handle);//此处handle参数为MV_CC_CreateHandle创建的相机句柄
	if (MV_OK != nRet4)
	{
		cout << "关闭相机失败!nRet4 :" << nRet4 << endl;
		return 0;
	}

2.8 销毁句柄

调用 MV_CC_DestroyHandle() 销毁句柄并释放资源。

int  MV_CC_DestroyHandle  ( IN void *  handle )  

销毁设备句柄 

参数
handle [IN] 设备句柄  

返回
成功,返回MV_OK;
失败,返回错误码 。 
//销毁句柄
	if (handle != NULL)
	{
		MV_CC_DestroyHandle(handle);//此处handle参数为MV_CC_CreateHandle创建的相机句柄
		handle = NULL;
	}

3.实验源码

#include<iostream>
#include<MvCameraControl.h>
#include "windows.h"


using namespace std;


void PrintDeviceInfo(MV_CC_DEVICE_INFO* pstMVDevInfo)
{
	if (NULL == pstMVDevInfo)
	{
		printf("The Pointer of pstMVDevInfo is NULL!\n");
		return;
	}
	if (pstMVDevInfo->nTLayerType == MV_GIGE_DEVICE)
	{
		int nIp1 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24);
		int nIp2 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16);
		int nIp3 = ((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8);
		int nIp4 = (pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);

		// en:print current ip and user defined name
		printf("CurrentIp: %d.%d.%d.%d\n", nIp1, nIp2, nIp3, nIp4);
		cout << "用户自定义名称: " << pstMVDevInfo->SpecialInfo.stGigEInfo.chUserDefinedName << endl;
		cout << "相机序列号: " << pstMVDevInfo->SpecialInfo.stGigEInfo.chSerialNumber << endl;
	}
	else if (pstMVDevInfo->nTLayerType == MV_USB_DEVICE)
	{
		printf("UserDefinedName: %s\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName);
		printf("Serial Number: %s\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chSerialNumber);
		printf("Device Number: %d\n\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.nDeviceNumber);
	}
	else
	{
		printf("Not support.\n");
	}

}



int main()
{
	//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)
	{
		cout<<"Enum Devices fail! nRet [0x%x]\n"<< nRet<<endl;
		return 0;
	}
	else//找到相机
	{
		//枚举到相机后,就可以获取到相机的一些设备信息
		//打印设备的SN码、设备名称、制造商
		//获取枚举到的相机数量
		int cam_num = cam_List.nDeviceNum;
		cout << "相机数量:" << cam_num << endl;
		//留给后边研究,没有运行成功
		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)
		{
			cout << "设备不允许被访问!" << endl;
		}
		cout << "设备运行被访问" << endl;
	}
	//创建相机句柄
	int nRet2 = MV_OK;
	void* handle = NULL;
	nRet2 = MV_CC_CreateHandle(&handle, cam_List.pDeviceInfo[0]);//枚举相机列表中的第一个相机
	if (MV_OK != nRet2)
	{
		cout << "创建句柄失败!nRet2 :" << nRet2 << endl;
		system("pause");
		return 0;
	}
	//打开相机
	int nRet3 = MV_OK;
	nRet3 = MV_CC_OpenDevice(handle);
	if (MV_OK != nRet3)
	{
		cout << "打开相机失败!nRet3 :" << nRet3 << endl;
		system("pause");
		return 0;
	}


	//开始取流
	// Start grab image
	nRet = MV_CC_StartGrabbing(handle);
	if (MV_OK != nRet)
	{
		cout << "取流失败!nRet :" << nRet << endl;
		system("pause");
		return 0;
	}
	创建结构体
	//MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 };
	//nRet = MV_CC_ConvertPixelType(handle, &stConvertParam);
	//if (MV_OK != nRet)
	//{
	//	cout << "图像创建失败!nRet :" << nRet << endl;
	//	system("pause");
	//	return 0;
	//}

	//使用内部缓存获取一帧图片 
	//例子来自 ConnectSpecCamera.cpp
	MV_FRAME_OUT stImageInfo = { 0 };

	nRet = MV_CC_GetImageBuffer(handle, &stImageInfo, 1000);
	if (nRet == MV_OK)
	{
		cout << "相机采集图像的宽度:" << stImageInfo.stFrameInfo.nWidth << endl;
		cout << "相机采集图像的高度:" << stImageInfo.stFrameInfo.nHeight << endl;
		cout << "相机采集图像的帧号:" << stImageInfo.stFrameInfo.nFrameNum << endl;
		
		//ConvertPixelType.cpp
		MV_DISPLAY_FRAME_INFO stDisplayInfo = { 0 };

		//HWND g_hWnd = AfxGetMainWnd()->m_hWnd;
			//if (g_hwnd)
			{
			cout << "正在输出" << endl;
			//stDisplayInfo.hWnd = GetDesktopWindow();
			//GetDesktopWindow该函数返回桌面窗口的句柄;
			stDisplayInfo.hWnd = GetForegroundWindow();
			//是获取当前系统中被激活的窗口
				stDisplayInfo.pData = stImageInfo.pBufAddr;
				stDisplayInfo.nDataLen = stImageInfo.stFrameInfo.nFrameLen;
				stDisplayInfo.nWidth = stImageInfo.stFrameInfo.nWidth;
				stDisplayInfo.nHeight = stImageInfo.stFrameInfo.nHeight;
				stDisplayInfo.enPixelType = stImageInfo.stFrameInfo.enPixelType;

				MV_CC_DisplayOneFrame(handle, &stDisplayInfo);
				//system("pause");
			}



		//释放指针 MV_CC_GetImageBuffer---&stImageInfo
		nRet = MV_CC_FreeImageBuffer(handle, &stImageInfo);
		if (nRet != MV_OK)
		{
			cout << "Free Image Buffer fail! nRet=" << nRet << endl;
		}
	}
	else
	{
		cout << "No data! nRet=" << nRet << endl;
	}


	//
	//停止采集
	// Stop grab image
	nRet = MV_CC_StopGrabbing(handle);
	if (MV_OK != nRet)
	{
		cout << "停止采集失败!nRet :" << nRet << endl;
		system("pause");
		return 0;
	}

	//关闭相机
	int nRet4 = MV_OK;
	nRet4=MV_CC_CloseDevice(handle);
	if (MV_OK != nRet4)
	{
		cout << "关闭相机失败!nRet4 :" << nRet4 << endl;
		return 0;
	}
	//销毁句柄
	if (handle != NULL)
	{
		MV_CC_DestroyHandle(handle);
		handle = NULL;
	}

	cout << "Hello!" << endl;
	system("pause");
	return 0;
}

hikvision SDK使用(转)-腾讯云开发者社区-腾讯云

4.运行结果

相关推荐

  1. 115.工业相机SDK开发指南(阅读)

    2024-04-09 09:32:01       20 阅读
  2. QT c++ 红外热像仪

    2024-04-09 09:32:01       15 阅读
  3. 怎样使用Halcon控制相机实时读取图像

    2024-04-09 09:32:01       37 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-09 09:32:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-09 09:32:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-09 09:32:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-09 09:32:01       18 阅读

热门阅读

  1. 学习Python第十七天:用python构建一个SSH僵尸网络

    2024-04-09 09:32:01       10 阅读
  2. 【Rust】——编写自动化测试

    2024-04-09 09:32:01       14 阅读
  3. 自然语言处理应用实例

    2024-04-09 09:32:01       15 阅读
  4. AI技术创业机会之智慧城市与智慧交通

    2024-04-09 09:32:01       10 阅读
  5. Python 中的离线语音转文本

    2024-04-09 09:32:01       12 阅读
  6. curaengine编译源码之libarcus编译记录

    2024-04-09 09:32:01       14 阅读
  7. 如何创建Windows下google Chrome便携版?

    2024-04-09 09:32:01       11 阅读
  8. Golang 中 在gmp下,mutex 是如何并发的

    2024-04-09 09:32:01       14 阅读
  9. tab切换 vue

    2024-04-09 09:32:01       13 阅读