本代码实现海康工业相机拍照并保存功能(MV_CC_ConvertPixelType)。
参考:MVS/MVS/Development/Documentations/海康工业相机SDK使用手册.chm
- C接口定义
- 图像处理
- MV_CC_ConvertPixelType
- 图像处理
void CMvCamera::grabLoop()
{
cv::Mat frame;
int bytesPerPixel;
int frameCounter = -1;
// ============================= 初始化 =============================
int nRet = -1; // 初始化 nRet
void* m_handle = NULL; // 初始化 m_handle
MV_CC_DEVICE_INFO m_stDevInfo = { 0 }; // 初始化一台设备 m_stDevInfo
MVCC_INTVALUE stIntvalue = { 0 }; // 初始化一帧数据 stIntvalue
unsigned char* pFrameBuf = NULL; // 定义图像缓存 pFrameBuf
MV_FRAME_OUT_INFO_EX stInfo; // 定义图像 stInfo
unsigned char *pDataForRGB = NULL; // 定义 RGB 像素格式
// ============================= 初始化 =============================
memcpy(&m_stDevInfo, m_capture, sizeof(MV_CC_DEVICE_INFO)); // 复制设备地址
nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo); // 创建句柄
if (MV_OK != nRet) qDebug() << "error: CreateHandle fail in grabLoop" << endl;
else qDebug() << "CreateHandle success in grabLoop" << endl;
nRet = MV_CC_OpenDevice(m_handle); // 连接设备
if (MV_OK != nRet) qDebug() << "error: OpenDevice fail in grabLoop" << endl;
else qDebug() << "OpenDevice success in grabLoop" << endl;
// ======================================== 预设相机属性 ========================================
nRet = MV_CC_SetEnumValue(m_handle, "TriggerMode", MV_TRIGGER_MODE_OFF); // 关闭触发源,设置连续模式
nRet = MV_CC_SetEnumValue(m_handle, "ExposureAuto", 2); // 设置自动曝光
//nRet = MV_CC_SetEnumValue(m_handle, "ExposureMode", 0); // 设置曝光模式
//nRet = MV_CC_SetEnumValue(m_handle, "ExposureTime", 900000.0); // 设置曝光时间
nRet = MV_CC_SetEnumValue(m_handle, "GainAuto", 2); // 设置自动增益
nRet = MV_CC_SetEnumValue(m_handle, "BalanceWhiteAuto", 1); // 设置自动白平衡
if (MV_OK != nRet) printf("error: Properties preset fail in plugin [%x]\n", nRet);
else qDebug() << "Properties preset sucess in plugin" << endl;
// ====================================== 相机属性预设结束 ======================================
nRet = MV_CC_StartGrabbing(m_handle); // 开始采集图像
if (MV_OK != nRet) qDebug() << "error: StartGrabbing fail in grabLoop" << endl;
else qDebug() << "StartGrabbing success in grabLoop" << endl;
nRet = MV_CC_GetIntValue(m_handle, "PayloadSize", &stIntvalue); // 获取一帧数据的大小
int nBufSize = stIntvalue.nCurValue; // 定义一帧数据大小
pFrameBuf = (unsigned char*)malloc(nBufSize); // 动态分配图像缓存 memory allocation
memset(&stInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX)); // 初始化图像 stInfo
// 丢掉前几帧
for (int i = 0; i < 40; i++) {
nRet = MV_CC_GetOneFrameTimeout(m_handle, pFrameBuf, nBufSize, &stInfo, 500);
//continue;
}
while (!m_stopThreadRequested && m_capture) {
/// thread safe
//QMutexLocker locker(&m_mutex);
if (!m_mutex.tryLock(100))
{
continue;
}
/ grab & retrieve next frame
nRet = MV_CC_GetOneFrameTimeout(m_handle, pFrameBuf, nBufSize, &stInfo, 500);
if (MV_OK != nRet)
{
Sleep(10);
}
else {
/*
MV_SAVE_IMG_TO_FILE_PARAM stParam; // 定义输入数据保存文件参数
stParam.enImageType = MV_Image_Png; // 需要保存的图像类型,支持 MV_Image_Jpeg,MV_Image_Bmp,MV_Image_Tif
stParam.enPixelType = stInfo.enPixelType; // 输入像素格式
stParam.nWidth = stInfo.nWidth; // 图像宽
stParam.nHeight = stInfo.nHeight; // 图像高
stParam.nDataLen = stInfo.nFrameLen; // 输入数据大小
stParam.pData = pFrameBuf; // 输入数据缓存
stParam.nQuality = 1; // jpg图像质量范围为(50-99], png图像质量范围为[0-9]
stParam.iMethodValue = 0;
*/
// 像素格式转换
pDataForRGB = (unsigned char*)malloc(stInfo.nWidth * stInfo.nHeight * 3);
unsigned int nDataSizeForRGB = stInfo.nWidth * stInfo.nHeight * 3;
MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 }; // 定义像素格式转换输入输出参数
memset(&stConvertParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM));
// 源数据
stConvertParam.nWidth = stInfo.nWidth; // 图像宽
stConvertParam.nHeight = stInfo.nHeight; // 图像高
stConvertParam.pSrcData = pFrameBuf; // 输入数据缓存
stConvertParam.nSrcDataLen = stInfo.nFrameLen; // 输入数据大小
stConvertParam.enSrcPixelType = stInfo.enPixelType; // 输入数据像素格式
// 目标数据
stConvertParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed; // 输出像素格式
stConvertParam.pDstBuffer = pDataForRGB; // 输出数据缓存
stConvertParam.nDstBufferSize = nDataSizeForRGB; // 输出缓存大小
nRet = MV_CC_ConvertPixelType(m_handle, &stConvertParam);
// 原 OpenCV 读图方法
switch (frame.type()) {
case CV_8UC3: // (0-255)
bytesPerPixel = 3;
break;
case CV_16UC3: // (0-65535)
bytesPerPixel = 3;
break;
default:
bytesPerPixel = 3;
}
bytesPerPixel = 3;
mCurrentImage = getNextBufferImage(stInfo.nWidth, stInfo.nHeight, 0, 0, bytesPerPixel);
/// copy data
mCurrentImage->setBuffer(pDataForRGB);
/// set image number
mCurrentImage->setNumber(++frameCounter);
m_lastRetrievedImage = &mCurrentImage;
/// notify
emit newImageReceived(mCurrentImage);
}
m_mutex.unlock();
}
qDebug() << "acquired" << frameCounter << "images";
if (!m_stopThreadRequested)
{
/// if we stopped because of some error, notify
stopAcquisition();
nRet = MV_CC_StopGrabbing(m_handle); // 停止采集图像
if (MV_OK != nRet) qDebug() << "error: StopGrabbing fail in grabLoop" << endl;
else qDebug() << "StopGrabbing success in grabLoop" << endl;
nRet = MV_CC_CloseDevice(m_handle); // 关闭设备,释放资源
if (MV_OK != nRet) qDebug() << "error: CloseDevice fail in grabLoop" << endl;
else qDebug() << "CloseDevice success in grabLoop" << endl;
nRet = MV_CC_DestroyHandle(m_handle); // 销毁句柄,释放资源
if (MV_OK != nRet) qDebug() << "error: DestroyHandle fail in grabLoop" << endl;
else qDebug() << "DestroyHandle success in grabLoop" << endl;
if (m_handle != NULL) {
MV_CC_DestroyHandle(m_handle);
m_handle = NULL;
}
// 释放图像缓存
free(pFrameBuf);
free(pDataForRGB);
pFrameBuf = NULL;
pDataForRGB = NULL;
}
}