目录
第一步:安装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 <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <GxIAPI.h>
#include <DxImageProc.h>
using namespace std;
using namespace cv;
GX_DEV_HANDLE m_hDevice; ///< 设备句柄
BYTE *m_pBufferRaw; ///< 原始图像数据
BYTE *m_pBufferRGB; ///< RGB图像数据,用于显示和保存bmp图像
int64_t m_nImageHeight; ///< 原始图像高
int64_t m_nImageWidth; ///< 原始图像宽
int64_t m_nPayLoadSize;
int64_t m_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 <m_nImageHeight; i++) {
memcpy(m_pImageBuffer + i*m_nImageWidth, m_pBufferRaw + (m_nImageHeight - i - 1)*m_nImageWidth, (size_t)m_nImageWidth);
}
IplImage* src;
src = cvCreateImage(cvSize(m_nImageWidth, m_nImageHeight), 8, 1);
src->imageData = (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 = (char*)m_pBufferRGB;
// cvSaveImage("./test.bmp", cv_Image);
//test.data = 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_t nDeviceNum = 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);
bool bColorFliter = 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 必备: |
条件:C++SDK配置、Opencv SDK配置
利用回调函数进行显示
# 实时显示——使用Mat Opencv
#include"stdafx.h"
#include<iostream>
#include <opencv2/core/core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\opencv.hpp>
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<iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\opencv.hpp>
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的问题
问题三【运行一次正常,如果手动中断程序,则不能再次访问相机】:
只能重启相机电源,因为该相机没有自动清除网络占有