#|机器视觉_相机开发(二)——大恒相机

目录
第一步:安装Gaalxy_view软件:Galaxy_V18.06.25.01_X86_Win_cn.exe
第二步:测试相机:MER-1070-10GC相机,应用软件打开该相机体验。
第三步:利用SDK-API进行编程,主要功能(开启、采集、录像、停止、关闭)
C接口
利用回调函数进行显示
C++ 接口
利用回调函数进行显示
利用获取帧进行显示
第四步:MFC联合SDK进行项目开发(当前项目瓷砖检测)。

第一步:安装Gaalxy_view软件:Galaxy_V18.06.25.01_X86_Win_cn.exe 软件从官网-技术支持-下载中心-选择需求软件(可单独使用SDK包、本文使用SDK+客户端软件一体)
链接:https://pan.baidu.com/s/1Il2qr_LD8Zz8gpb0QNQBaw 提取码:kh2w
#|机器视觉_相机开发(二)——大恒相机
文章图片
#|机器视觉_相机开发(二)——大恒相机
文章图片

第二步:测试相机:MER-1070-10GC相机,应用软件打开该相机体验。 MER-1070-10GC相机为以太网通信的相机,之前开发的项目都是走FlyCapture的sdk,不能开启该相机,所有先测试体验下。
#|机器视觉_相机开发(二)——大恒相机
文章图片

第三步:利用SDK-API进行编程,主要功能(开启、采集、录像、停止、关闭) 重中之重,如何开发所需功能,鄙人使用联合Opencv图像库联合开发。
使用C接口和C++ 接口两个程序分别实现:
总体思路:
初始化接口库——》枚举设备——》打开设备打开流
——》注册设备掉线事件【目前只有千兆网系列相机支持此事件通知】
——》获取远端设备属性控制器
————》注册远端设备事件【属性控制器】
——》注册回调采集(显示)
————》发送开采命令【属性控制器】
————》发送停采命令【属性控制器】
——》注销采集回调
——》注销远端设备事件
——》注销设备掉线事件
——》释放资源
C接口 (参考网上代码,C++的是看接口说明文档进行的)
配置:VC SDK的inc和lib、Opencv SDK配置
利用回调函数进行显示

#include #include #include #include #include #include using namespace std; using namespace cv; GX_DEV_HANDLEm_hDevice; ///< 设备句柄 BYTE*m_pBufferRaw; ///< 原始图像数据 BYTE*m_pBufferRGB; ///< RGB图像数据,用于显示和保存bmp图像 int64_tm_nImageHeight; ///< 原始图像高 int64_tm_nImageWidth; ///< 原始图像宽 int64_tm_nPayLoadSize; int64_tm_nPixelColorFilter; ///< Bayer格式 Mat test; //图像回调处理函数 static void GX_STDC OnFrameCallbackFun(GX_FRAME_CALLBACK_PARAM* pFrame) { //PrepareForShowImg(); if (pFrame->status == 0) { //对图像进行某些操作 /*memcpy(m_pBufferRaw, pFrame->pImgBuf, pFrame->nImgSize); // 黑白相机需要翻转数据后显示 for (int i = 0; i imageData = https://www.it610.com/article/(char*)m_pImageBuffer; cvSaveImage("src.jpg", src); */ memcpy(m_pBufferRaw, pFrame->pImgBuf, pFrame->nImgSize); // RGB转换 DxRaw8toRGB24(m_pBufferRaw , m_pBufferRGB , (VxUint32)(m_nImageWidth) , (VxUint32)(m_nImageHeight) , RAW2RGB_NEIGHBOUR , DX_PIXEL_COLOR_FILTER(m_nPixelColorFilter) , false); //cv_Image->imageData = https://www.it610.com/article/(char*)m_pBufferRGB; //cvSaveImage("./test.bmp", cv_Image); //test.data = https://www.it610.com/article/m_pBufferRaw; memcpy(test.data, m_pBufferRGB, m_nImageWidth*m_nImageHeight * 3); imwrite("./test1.bmp", test); namedWindow("test"); imshow("test", test); waitKey(15); } return; }int main(int argc, char* argv[]) { GX_STATUS emStatus = GX_STATUS_SUCCESS; GX_OPEN_PARAM openParam; uint32_tnDeviceNum = 0; openParam.accessMode = GX_ACCESS_EXCLUSIVE; openParam.openMode = GX_OPEN_INDEX; openParam.pszContent = "1"; // 初始化库 emStatus = GXInitLib(); if (emStatus != GX_STATUS_SUCCESS) { return 0; } // 枚举设备列表 emStatus = GXUpdateDeviceList(&nDeviceNum, 1000); if ((emStatus != GX_STATUS_SUCCESS) || (nDeviceNum <= 0)) { return 0; } //打开设备 emStatus = GXOpenDevice(&openParam, &m_hDevice); //设置采集模式连续采集 emStatus = GXSetEnum(m_hDevice, GX_ENUM_ACQUISITION_MODE, GX_ACQ_MODE_CONTINUOUS); emStatus = GXSetInt(m_hDevice, GX_INT_ACQUISITION_SPEED_LEVEL, 1); emStatus = GXSetEnum(m_hDevice, GX_ENUM_BALANCE_WHITE_AUTO, GX_BALANCE_WHITE_AUTO_CONTINUOUS); boolbColorFliter = false; // 获取图像大小 emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &m_nPayLoadSize); // 获取宽度 emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &m_nImageWidth); // 获取高度 emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &m_nImageHeight); test.create(m_nImageHeight, m_nImageWidth, CV_8UC3); //判断相机是否支持bayer格式 bool m_bColorFilter; emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter); if (m_bColorFilter) { emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_nPixelColorFilter); } m_pBufferRGB = new BYTE[(size_t)(m_nImageWidth * m_nImageHeight * 3)]; if (m_pBufferRGB == NULL) { return false; } //为存储原始图像数据申请空间 m_pBufferRaw = new BYTE[(size_t)m_nPayLoadSize]; if (m_pBufferRaw == NULL) { delete[]m_pBufferRGB; m_pBufferRGB = NULL; return false; } //注册图像处理回调函数 emStatus = GXRegisterCaptureCallback(m_hDevice, NULL, OnFrameCallbackFun); //发送开采命令 emStatus = GXSendCommand(m_hDevice, GX_COMMAND_ACQUISITION_START); //--------------------- // //在这个区间图像会通过OnFrameCallbackFun接口返给用户 Sleep(100000); // //--------------------- //发送停采命令 emStatus = GXSendCommand(m_hDevice, GX_COMMAND_ACQUISITION_STOP); //注销采集回调 emStatus = GXUnregisterCaptureCallback(m_hDevice); if (m_pBufferRGB != NULL) { delete[]m_pBufferRGB; m_pBufferRGB = NULL; } if (m_pBufferRaw != NULL) { delete[]m_pBufferRaw; m_pBufferRaw = NULL; } emStatus = GXCloseDevice(m_hDevice); emStatus = GXCloseLib(); return 0; }

C++ 接口
CCD采集的像素,该相机的图形格式GX_PIXEL_FORMAT_BAYER_GR8:Bayer Green-Red 8-bit
必备:https://blog.csdn.net/joe9280/article/details/46952947
条件:C++SDK配置、Opencv SDK配置
利用回调函数进行显示
# 实时显示——使用Mat Opencv #include"stdafx.h" #include #include #include #include using namespace cv; using namespace std; //请用户提前配置好工程头文件目录,需要包含GalaxyIncludes.h #include"GalaxyIncludes.h"//用户继承掉线事件处理类 class CSampleDeviceOfflineEventHandler : public IDeviceOfflineEventHandler { public: void DoOnDeviceOfflineEvent(void* pUserParam) { cout << "收到设备掉线事件!" << endl; } }; //用户继承属性更新事件处理类 class CSampleFeatureEventHandler : public IFeatureEventHandler { public: void DoOnFeatureEvent(const GxIAPICPP::gxstring&strFeatureName, void* pUserParam) { cout << "收到曝光结束事件!" << endl; } }; //用户继承采集事件处理类 class CSampleCaptureEventHandler : public ICaptureEventHandler { public: void DoOnImageCaptured(CImageDataPointer&objImageDataPointer, void* pUserParam) { cout << "收到一帧图像!" << endl; cout << "ImageInfo: " << objImageDataPointer->GetStatus() << endl; cout << "ImageInfo: " << objImageDataPointer->GetWidth() << endl; cout << "ImageInfo: " << objImageDataPointer->GetHeight() << endl; cout << "ImageInfo: " << objImageDataPointer->GetPayloadSize() << endl; cout << objImageDataPointer->GetPixelFormat() << endl; cout << GX_PIXEL_FORMAT_BAYER_GR8 << endl; void* pRGB24Buffer = NULL; //假设原始数据是BayerRG8图像 pRGB24Buffer = objImageDataPointer->ConvertToRGB24(GX_BIT_0_7, GX_RAW2RGB_NEIGHBOUR, true); Mat test; test.create(objImageDataPointer->GetHeight(), objImageDataPointer->GetWidth(), CV_8UC3); memcpy(test.data, pRGB24Buffer, objImageDataPointer->GetPayloadSize() * 3); namedWindow("测试", 0); imshow("测试", test); waitKey(10); } }; int _tmain(int argc, _TCHAR* argv[]) { //声明事件回调对象指针 IDeviceOfflineEventHandler* pDeviceOfflineEventHandler = NULL; ///<掉线事件回调对象 IFeatureEventHandler* pFeatureEventHandler = NULL; ///<远端设备事件回调对象 ICaptureEventHandler* pCaptureEventHandler = NULL; ///<采集回调对象 //初始化 IGXFactory::GetInstance().Init(); try { do { //枚举设备 gxdeviceinfo_vector vectorDeviceInfo; IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo); if (0 == vectorDeviceInfo.size()) { cout << "无可用设备!" << endl; break; }//打开第一台设备以及设备下面第一个流 CGXDevicePointer ObjDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN( vectorDeviceInfo[0].GetSN(), GX_ACCESS_EXCLUSIVE); CGXStreamPointer ObjStreamPtr = ObjDevicePtr->OpenStream(0); //注册设备掉线事件【目前只有千兆网系列相机支持此事件通知】 GX_DEVICE_OFFLINE_CALLBACK_HANDLE hDeviceOffline = NULL; pDeviceOfflineEventHandler = new CSampleDeviceOfflineEventHandler(); hDeviceOffline = ObjDevicePtr->RegisterDeviceOfflineCallback(pDeviceOfflineEventHandler, NULL); //获取远端设备属性控制器 CGXFeatureControlPointer ObjFeatureControlPtr = ObjDevicePtr->GetRemoteFeatureControl(); //设置曝光时间(示例中写死us,只是示例,并不代表真正可工作参数,可以尝试,但是不要乱用) //ObjFeatureControlPtr->GetFloatFeature("ExposureTime")->SetValue(500); //注册远端设备事件:曝光结束事件【目前只有千兆网系列相机支持曝光结束事件】 //选择事件源 ObjFeatureControlPtr->GetEnumFeature("EventSelector")->SetValue("ExposureEnd"); //使能事件 ObjFeatureControlPtr->GetEnumFeature("EventNotification")->SetValue("On"); GX_FEATURE_CALLBACK_HANDLE hFeatureEvent = NULL; pFeatureEventHandler = new CSampleFeatureEventHandler(); hFeatureEvent = ObjFeatureControlPtr->RegisterFeatureCallback( "EventExposureEnd", pFeatureEventHandler, NULL); //注册回调采集 pCaptureEventHandler = new CSampleCaptureEventHandler(); ObjStreamPtr->RegisterCaptureCallback(pCaptureEventHandler, NULL); //发送开采命令 ObjStreamPtr->StartGrab(); ObjFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute(); //此时开采成功,控制台打印信息,直到输入任意键继续 getchar(); //发送停采命令 ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); ObjStreamPtr->StopGrab(); //注销采集回调 ObjStreamPtr->UnregisterCaptureCallback(); //注销远端设备事件 ObjFeatureControlPtr->UnregisterFeatureCallback(hFeatureEvent); //注销设备掉线事件 ObjDevicePtr->UnregisterDeviceOfflineCallback(hDeviceOffline); //释放资源 ObjStreamPtr->Close(); ObjDevicePtr->Close(); } while (0); } catch (CGalaxyException&e) { cout << "错误码: " << e.GetErrorCode() << endl; cout << "错误描述信息: " << e.what() << endl; } catch (std::exception&e) { cout << "错误描述信息: " << e.what() << endl; } //反初始化库 IGXFactory::GetInstance().Uninit(); //销毁事件回调指针 if (NULL != pCaptureEventHandler) { delete pCaptureEventHandler; pCaptureEventHandler = NULL; } if (NULL != pDeviceOfflineEventHandler) { delete pDeviceOfflineEventHandler; pDeviceOfflineEventHandler = NULL; } if (NULL != pFeatureEventHandler) { delete pFeatureEventHandler; pFeatureEventHandler = NULL; } return 0; }

#|机器视觉_相机开发(二)——大恒相机
文章图片

利用获取帧进行显示
条件:C++SDK配置、Opencv SDK配置
#include"stdafx.h" #include #include #include #include using namespace cv; using namespace std; //请用户提前配置好工程头文件目录,需要包含GalaxyIncludes.h #include"GalaxyIncludes.h"Mat src; int _tmain(int argc, _TCHAR* argv[]) { //初始化 IGXFactory::GetInstance().Init(); try { do { //枚举设备 gxdeviceinfo_vector vectorDeviceInfo; IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo); if (0 == vectorDeviceInfo.size()) { cout << "无可用设备!" << endl; break; }//打开第一台设备以及设备下面第一个流 CGXDevicePointer ObjDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN( vectorDeviceInfo[0].GetSN(), GX_ACCESS_EXCLUSIVE); CGXStreamPointer ObjStreamPtr = ObjDevicePtr->OpenStream(0); //获取远端设备属性控制器 CGXFeatureControlPointer ObjFeatureControlPtr = ObjDevicePtr->GetRemoteFeatureControl(); //发送开采命令 ObjStreamPtr->StartGrab(); ObjFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute(); //主程序 //采单帧 int a = 1; while (a) { CImageDataPointer objImageDataPtr; objImageDataPtr = ObjStreamPtr->GetImage(500); //超时时间使用500ms,用户可以自行设定 if (objImageDataPtr->GetStatus() == GX_FRAME_STATUS_SUCCESS) { //getchar(); //采图成功而且是完整帧,可以进行图像处理... cout << "收到一帧图像!" << endl; cout << "ImageInfo: " << objImageDataPtr->GetStatus() << endl; cout << "ImageInfo: " << objImageDataPtr->GetWidth() << endl; cout << "ImageInfo: " << objImageDataPtr->GetHeight() << endl; cout << "ImageInfo: " << objImageDataPtr->GetPayloadSize() << endl; cout << objImageDataPtr->GetPixelFormat() << endl; cout << GX_PIXEL_FORMAT_BAYER_GR8 << endl; //假设原始数据是BayerRG8图像,则 GX_BIT_0_7 void* pRGB24Buffer = NULL; pRGB24Buffer = objImageDataPtr->ConvertToRGB24(GX_BIT_0_7, GX_RAW2RGB_NEIGHBOUR, true); Mat test; test.create(objImageDataPtr->GetHeight(), objImageDataPtr->GetWidth(), CV_8UC3); memcpy(test.data, pRGB24Buffer, objImageDataPtr->GetPayloadSize() * 3); namedWindow("测试", 0); imshow("测试", test); //waitKey(10); test.copyTo(src); //system("pause"); if (waitKey(20)==27) { a = 0; break; } } }//发送停采命令 ObjFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); ObjStreamPtr->StopGrab(); //释放资源 ObjStreamPtr->Close(); ObjDevicePtr->Close(); } while (false); } catch (CGalaxyException&e) { cout << "错误码: " << e.GetErrorCode() << endl; cout << "错误描述信息: " << e.what() << endl; } catch (std::exception&e) { cout << "错误描述信息: " << e.what() << endl; } //反初始化库 IGXFactory::GetInstance().Uninit(); return 0; }

#|机器视觉_相机开发(二)——大恒相机
文章图片

问题解决:
问题一【图示】:该问题为库的配置没有连接好,解决方案:查看配置(ilb、inc、dll)的文件缺省,检测完成,重启电脑。
#|机器视觉_相机开发(二)——大恒相机
文章图片

问题二【图示】:图片流转Mat的问题
#|机器视觉_相机开发(二)——大恒相机
文章图片

问题三【运行一次正常,如果手动中断程序,则不能再次访问相机】:
【#|机器视觉_相机开发(二)——大恒相机】只能重启相机电源,因为该相机没有自动清除网络占有
第四步:MFC联合SDK进行项目开发之一(MFC相机界面)

    推荐阅读