有一个小型的工业相机,
主管安排学习下工业相机的SDK的使用,做一个实时采图的demo
相机客户端下载:海康机器人-机器视觉-下载中心 (hikrobotics.com)
应该在后面几页里,叫机器视觉工业相机客户端MVS
开始我去了海康官网下的网络设备SDK,
后面看了大佬们的博客才知道,这个是要工业相机的SDK,
下载的是MVS软件,有相机客户端,相机客户端的使用手册及SDK文档和例子
比如用visual studio开发的例子,在此路径下
MVS/Development/Documentations/示例程序说明VS2008.pdf
里面也说了对应visual studio例子的位置
MVSDevelopmentSamplesVCVS
MVS相机客户端初始配置是把相机IP设为和连接的WLAN同网段的静态IP,
如WLAN的IP为:192.168.102.104
设置的相机IP为:192.168.102.2
连接相机,采集图像,可以采图,开始是黑白色的,
图像处理中的像素格式是Mono,改为RGB就是彩色的了,
然后退出该客户端,去参照例子做一个实时采图的demo
官方例子BasicDemo就是一个实时采图的例子,
它用的好像是主动取流,多线程的方式,
主管说要再弄个注册回调取流的demo,
就把官方demo中多线程的部分删掉,
又参照了众多大佬的博客,
最后倒是可以采图了,但保存图片有问题,
我感觉自己拼凑的回调取流有些问题,
又继续网上搜罗,看到有说官方例子里有回调取流的demo,
不过是c#的,在这个位置MVSDevelopmentSamplesC#MultipleDemo
代码文件MultiDemo.cs,还是有些用处的
参照着改了改,保存图片这里仍未解决
又参照了大佬的博客
海康相机SDK开发in VS2015+Qt5 - onefish51 - 博客园 (cnblogs.com)
保存图片可以了,但多次保存还是会有报错,比如Access violation writing location,
又去参照BasicDemo里的改了改,看的有些晕,
但是实时采图,保存图片都可以了,也可以多次保存图片了
放一些我感觉关键地方的代码吧,就是在BasicDemo上改的:
开始采集这里注册回调函数
// ch:按下开始采集按钮 | en:Click Start button
void CHIKBasicDemoCallBackDlg::OnBnClickedStartGrabbingButton()
{
if (FALSE == m_bOpenDevice || TRUE == m_bStartGrabbing || NULL == m_pcMyCamera)
{
return;
}
memset(&m_stImageInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));
//注册回调函数
int nRet = m_pcMyCamera->RegisterImageCallBack(ImageCallBackEx, this);
if (nRet != MV_OK)
{
ShowErrorMsg(TEXT("Register image callback fail"), nRet);
return;
}
nRet = m_pcMyCamera->StartGrabbing();
if (MV_OK != nRet)
{
ShowErrorMsg(TEXT("Start grabbing fail"), nRet);
return;
}
m_bStartGrabbing = TRUE;
EnableControls(TRUE);
return;
}
注册回调函数的具体实现,
在头文件中该回调函数声明为静态的了,参照大佬的博客弄的
//声明回调函数为静态函数 static void __stdcall ImageCallBackEx(unsigned char* pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser);
具体实现,
void __stdcall CHIKBasicDemoCallBackDlg::ImageCallBackEx(unsigned char* pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser)
{
CHIKBasicDemoCallBackDlg* callback_dlg = (CHIKBasicDemoCallBackDlg*)pUser;
// ch:抓取的帧数
++callback_dlg->m_nFrames;
//ch:判断是否需要保存图片
if (callback_dlg->m_bSaveImg)
{
callback_dlg->SaveImage(pData, *pFrameInfo);
callback_dlg->m_bSaveImg = false;
}
//显示实时图像
MV_DISPLAY_FRAME_INFO stDisplayInfo = {0};
stDisplayInfo.hWnd = callback_dlg->m_hwndDisplay;
stDisplayInfo.pData = pData;
stDisplayInfo.nDataLen = (*pFrameInfo).nFrameLen;
stDisplayInfo.nWidth = (*pFrameInfo).nWidth;
stDisplayInfo.nHeight = (*pFrameInfo).nHeight;
stDisplayInfo.enPixelType = (*pFrameInfo).enPixelType;
callback_dlg->m_pcMyCamera->DisplayOneFrame(&stDisplayInfo);
}
头文件与保存图片相关的变量
bool m_bSaveImg; // ch:保存图片标志位 unsigned int m_nBufSizeForSaveImage; unsigned char* m_pBufForSaveImage; // ch:用于保存图像的缓存
保存图片,
//ch:保存图片
void CHIKBasicDemoCallBackDlg::SaveImage(unsigned char* pData, MV_FRAME_OUT_INFO_EX pFrameInfo)
{
unsigned int nSaveImageNeedSize = pFrameInfo.nFrameLen * 3 + 2048;
if (NULL == m_pBufForSaveImage || m_nBufSizeForSaveImage < nSaveImageNeedSize)
{
if (m_pBufForSaveImage)
{
free(m_pBufForSaveImage);
m_pBufForSaveImage = NULL;
}
m_pBufForSaveImage = (unsigned char*)malloc(nSaveImageNeedSize);
if (NULL == m_pBufForSaveImage)
{
ShowErrorMsg(TEXT("Distributed Save failed"), 0 );
}
m_nBufSizeForSaveImage = nSaveImageNeedSize;
}
MV_SAVE_IMAGE_PARAM_EX pstSaveFileParam = {};
memset(&pstSaveFileParam, 0, sizeof(MV_SAVE_IMAGE_PARAM_EX));
pstSaveFileParam.enImageType = m_nSaveImageType; // ch:需要保存的图像类型 | en:Image format to save
pstSaveFileParam.enPixelType = pFrameInfo.enPixelType;
pstSaveFileParam.nWidth = pFrameInfo.nWidth;
pstSaveFileParam.nHeight = pFrameInfo.nHeight;
pstSaveFileParam.nDataLen = pFrameInfo.nFrameLen;
pstSaveFileParam.pData = pData;
pstSaveFileParam.pImageBuffer = m_pBufForSaveImage; // ch: 存放图像输出
pstSaveFileParam.nBufferSize = m_nBufSizeForSaveImage;
if (m_nSaveImageType == MV_Image_Jpeg)
{
pstSaveFileParam.nJpgQuality = 80;
}
char chImageName[IMAGE_NAME_LEN] = { 0 };
if (MV_Image_Jpeg == pstSaveFileParam.enImageType)
{
sprintf_s(chImageName, IMAGE_NAME_LEN, "Image_w%d_h%d_fn%03d.jpg", pstSaveFileParam.nWidth, pstSaveFileParam.nHeight, pFrameInfo.nFrameNum);
}
else if (MV_Image_Bmp == pstSaveFileParam.enImageType)
{
sprintf_s(chImageName, IMAGE_NAME_LEN, "Image_w%d_h%d_fn%03d.bmp", pstSaveFileParam.nWidth, pstSaveFileParam.nHeight, pFrameInfo.nFrameNum);
}
int nRet = m_pcMyCamera->SaveImage(&pstSaveFileParam);
if (MV_OK != nRet)
{
ShowErrorMsg(TEXT("Save failed"), nRet);
}
else
{
//将转换之后图片数据保存成文件
FILE* fp;
errno_t err =fopen_s(&fp, chImageName, "wb");
fwrite(m_pBufForSaveImage, 1, pstSaveFileParam.nImageLen, fp);
fclose(fp);
}
}
最后感谢各位大佬的博客分享,有你们真好!



