Get Image in Callback Function

  1. 学习使用在回调函数中获取图像
  2. 示例代码
  3. 控制流程
  4. 函数用法

在回调函数中获取图片

MV_CC_RegisterImageCallBackEx()接口用于注册回调函数,可以自定义回调函数,获取到图片会自动回调。

如果要获取RGB24或BGR24图像,可以调用 MV_CC_RegisterImageCallBackForRGB()或 MV_CC_RegisterImageCallBackForBGR()来注册回调函数。

  1. 在回调函数中不建议使用耗时的操作和线程锁,这可能会导致阻塞;
  2. pData返回地址指针,建议复制pData的数据以创建另一个线程;

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "MvCameraControl.h"

// 等待用户输入enter键来结束取流或结束程序
// wait for user to input enter to stop grabbing or end the sample program
void PressEnterToExit(void)
{
int c;
while ( (c = getchar()) != '\n' && c != EOF );
fprintf( stderr, "\nPress enter to exit.\n");
while( getchar() != '\n');
}

bool PrintDeviceInfo(MV_CC_DEVICE_INFO* pstMVDevInfo)
{
if (NULL == pstMVDevInfo)
{
printf("The Pointer of pstMVDevInfo is NULL!\n");
return false;
}
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);

// ch:打印当前相机ip和用户自定义名字 | en:print current ip and user defined name
printf("Device Model Name: %s\n", pstMVDevInfo->SpecialInfo.stGigEInfo.chModelName);
printf("CurrentIp: %d.%d.%d.%d\n" , nIp1, nIp2, nIp3, nIp4);
printf("UserDefinedName: %s\n\n" , pstMVDevInfo->SpecialInfo.stGigEInfo.chUserDefinedName);
}
else if (pstMVDevInfo->nTLayerType == MV_USB_DEVICE)
{
printf("Device Model Name: %s\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chModelName);
printf("UserDefinedName: %s\n\n", pstMVDevInfo->SpecialInfo.stUsb3VInfo.chUserDefinedName);
}
else if (pstMVDevInfo->nTLayerType == MV_GENTL_GIGE_DEVICE)
{
printf("UserDefinedName: %s\n", pstMVDevInfo->SpecialInfo.stGigEInfo.chUserDefinedName);
printf("Serial Number: %s\n", pstMVDevInfo->SpecialInfo.stGigEInfo.chSerialNumber);
printf("Model Name: %s\n\n", pstMVDevInfo->SpecialInfo.stGigEInfo.chModelName);
}
else if (pstMVDevInfo->nTLayerType == MV_GENTL_CAMERALINK_DEVICE)
{
printf("UserDefinedName: %s\n", pstMVDevInfo->SpecialInfo.stCMLInfo.chUserDefinedName);
printf("Serial Number: %s\n", pstMVDevInfo->SpecialInfo.stCMLInfo.chSerialNumber);
printf("Model Name: %s\n\n", pstMVDevInfo->SpecialInfo.stCMLInfo.chModelName);
}
else if (pstMVDevInfo->nTLayerType == MV_GENTL_CXP_DEVICE)
{
printf("UserDefinedName: %s\n", pstMVDevInfo->SpecialInfo.stCXPInfo.chUserDefinedName);
printf("Serial Number: %s\n", pstMVDevInfo->SpecialInfo.stCXPInfo.chSerialNumber);
printf("Model Name: %s\n\n", pstMVDevInfo->SpecialInfo.stCXPInfo.chModelName);
}
else if (pstMVDevInfo->nTLayerType == MV_GENTL_XOF_DEVICE)
{
printf("UserDefinedName: %s\n", pstMVDevInfo->SpecialInfo.stXoFInfo.chUserDefinedName);
printf("Serial Number: %s\n", pstMVDevInfo->SpecialInfo.stXoFInfo.chSerialNumber);
printf("Model Name: %s\n\n", pstMVDevInfo->SpecialInfo.stXoFInfo.chModelName);
}
else
{
printf("Not support.\n");
}

return true;
}


void __stdcall ImageCallBackEx(unsigned char * pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser)
{
if (pFrameInfo)
{
printf("GetOneFrame, Width[%d], Height[%d], nFrameNum[%d]\n",
pFrameInfo->nExtendWidth, pFrameInfo->nExtendHeight, pFrameInfo->nFrameNum);
}
}

int main()
{
int nRet = MV_OK;

void* handle = NULL;
do
{
// ch:初始化SDK | en:Initialize SDK
nRet = MV_CC_Initialize();
if (MV_OK != nRet)
{
printf("Initialize SDK fail! nRet [0x%x]\n", nRet);
break;
}

MV_CC_DEVICE_INFO_LIST stDeviceList;
memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));

// 枚举设备
// enum device
nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE | MV_GENTL_CAMERALINK_DEVICE | MV_GENTL_CXP_DEVICE | MV_GENTL_XOF_DEVICE, &stDeviceList);
if (MV_OK != nRet)
{
printf("MV_CC_EnumDevices fail! nRet [%x]\n", nRet);
break;
}
if (stDeviceList.nDeviceNum > 0)
{
for (int i = 0; i < stDeviceList.nDeviceNum; i++)
{
printf("[device %d]:\n", i);
MV_CC_DEVICE_INFO* pDeviceInfo = stDeviceList.pDeviceInfo[i];
if (NULL == pDeviceInfo)
{
break;
}
PrintDeviceInfo(pDeviceInfo);
}
}
else
{
printf("Find No Devices!\n");
break;
}

printf("Please Intput camera index: ");
unsigned int nIndex = 0;
scanf("%d", &nIndex);

if (nIndex >= stDeviceList.nDeviceNum)
{
printf("Intput error!\n");
break;
}

// 选择设备并创建句柄
// select device and create handle
nRet = MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[nIndex]);
if (MV_OK != nRet)
{
printf("MV_CC_CreateHandle fail! nRet [%x]\n", nRet);
break;
}

// 打开设备
// open device
nRet = MV_CC_OpenDevice(handle);
if (MV_OK != nRet)
{
printf("MV_CC_OpenDevice fail! nRet [%x]\n", nRet);
break;
}

// ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
if (stDeviceList.pDeviceInfo[nIndex]->nTLayerType == MV_GIGE_DEVICE)
{
int nPacketSize = MV_CC_GetOptimalPacketSize(handle);
if (nPacketSize > 0)
{
nRet = MV_CC_SetIntValueEx(handle,"GevSCPSPacketSize",nPacketSize);
if(nRet != MV_OK)
{
printf("Warning: Set Packet Size fail nRet [0x%x]!\n", nRet);
}
}
else
{
printf("Warning: Get Packet Size fail nRet [0x%x]!\n", nPacketSize);
}
}

// 设置触发模式为off
// set trigger mode as off
nRet = MV_CC_SetEnumValue(handle, "TriggerMode", 0);
if (MV_OK != nRet)
{
printf("MV_CC_SetTriggerMode fail! nRet [%x]\n", nRet);
break;
}

// 注册抓图回调
// register image callback
nRet = MV_CC_RegisterImageCallBackEx(handle, ImageCallBackEx, handle);
if (MV_OK != nRet)
{
printf("MV_CC_RegisterImageCallBackEx fail! nRet [%x]\n", nRet);
break;
}

// 开始取流
// start grab image
nRet = MV_CC_StartGrabbing(handle);
if (MV_OK != nRet)
{
printf("MV_CC_StartGrabbing fail! nRet [%x]\n", nRet);
break;
}

PressEnterToExit();

// 停止取流
// end grab image
nRet = MV_CC_StopGrabbing(handle);
if (MV_OK != nRet)
{
printf("MV_CC_StopGrabbing fail! nRet [%x]\n", nRet);
break;
}

// 关闭设备
// close device
nRet = MV_CC_CloseDevice(handle);
if (MV_OK != nRet)
{
printf("MV_CC_CloseDevice fail! nRet [%x]\n", nRet);
break;
}

// 销毁句柄
// destroy handle
nRet = MV_CC_DestroyHandle(handle);
if (MV_OK != nRet)
{
printf("MV_CC_DestroyHandle fail! nRet [%x]\n", nRet);
break;
}
handle = NULL;
} while (0);

if (handle != NULL)
{
MV_CC_DestroyHandle(handle);
handle = NULL;
}


// ch:反初始化SDK | en:Finalize SDK
MV_CC_Finalize();

printf("exit\n");

return 0;
}

控制流程

img

  1. 调用MV_CC_Initialize()初始化 SDK 资源;

  2. (可选)调用MV_CC_EnumDevices()以枚举子网中与指定传输协议对应的所有设备;找到的设备的信息由pstDevList以 MV_CC_DEVICE_INFO_LIST()结构体返回;

  3. (可选)调用MV_CC_IsDeviceAccessible()以检查指定的设备是否可访问,然后再打开它;

  4. 调用MV_CC_CreateHandle()以创建设备句柄;

  5. (可选)执行以下一项或多项操作来获取/设置不同类型的参数:

    1. MV_CC_GetIntValueEx() / MV_CC_SetIntValueEx()

    2. MV_CC_GetFloatValue() / MV_CC_SetFloatValue()

    3. MV_CC_GetEnumValue() / MV_CC_SetEnumValue()

    4. MV_CC_GetBoolValue() / MV_CC_SetBoolValue()

    5. MV_CC_GetStringValue() / MV_CC_SetStringValue()

    6. MV_CC_SetCommandValue() MV_CC_SetCommandValue()

      • 所有 open 属性值都可以在 Camera Parameter Nodes 表中找到。该表提供了每个节点的名称、数据类型、取值范围、访问方式和介绍的详细说明
      • 可设置采集模式:设置和获取单帧、多帧和连续采集的采集模式;
      • 可设置触发方式:硬件触发,软件触发;
      • 可设置图像参数:图像宽度和高度、像素格式、帧速率、AIO 偏移、增益、曝光模式、曝光值、亮度、锐度、饱和度、灰度、白平衡、Gamma 值和其他参数;
  6. 调用 MV_CC_DisplayOneFrame()输入句柄并开始显示帧;

  7. 调用 MV_CC_StopGrabbing()以停止客户获取;

  8. 调用 MV_CC_CloseDevice()以关闭设备;

  9. 调用 MV_CC_DestroyHandle()销毁 handle 并释放资源;

  10. 调用 MV_CC_Finalize()释放 SDK 资源;

函数用法

  1. 调用 MV_CC_RegisterImageCallBackEx()设置数据回调函数;
  2. 调用 MV_CC_StartGrabbing()开始流式传输;
  3. 对于原始图像数据,您可以调用 MV_CC_ConvertPixelTypeEx()转换图像像素格式,或调用 MV_CC_SaveImageEx3()将图像转换为 JPEG 或 BMP 格式并另存为文件;
  4. 可以在回调函数中保存图像;

Get Image in Callback Function
http://example.com/2025/02/22/StructLight/camera/ImageCallback/
作者
ZhangHangming
发布于
2025年2月22日
许可协议