平台:Ubuntu 16.04
相机: MER-301-125U3M
1. 安装大恒的SDK
从大恒官网下载linux的安装包,名称如Galaxy_Linux-x86_Gige-U3_32bits-64bits_1.2.1911.9122.tar.gz
解压后进入Galaxy_Linux-x86_Gige-U3_32bits-64bits_1.2.1911.9122
目录,
在终端中运行./Galaxy_camera.run,便会生成安装目录Galaxy_camera
大恒的头文件和库文件:
头文件: 在./Galaxy_camera/inc
目录,有DxImageProc.h
和GxIAPI.h
两个文件
库文件: 在系统库目录下,/usr/lib/libgxiapi.so
,所以cmake的时候可以直接去链接
2. 采图例程
下面的例子是用大恒相机连续采集1500张图像,并用opencv的窗口实时显示出来。
2.1 目录结构
例子的总体目录结构如下:
.
├── CMakeLists.txt
├── DxImageProc.h
├── generate_demo.sh
├── main.cpp
└── GxIAPI.h
-
GxIAPI.h
和DxImageProc.h
为大恒的头文件,从大恒安装目录的inc
目录里复制过来 -
CMakeLists.txt
cmake的配置文件 -
main.cpp
采图的源码文件 -
generate_demo.sh
一个便捷的生成脚本,里面调用了cmake
和make
,也可以自己在终端输入这些命令来完成。新建文件的时候要给执行权限:chmod +x generate_demo.sh
2.2 CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(daheng_grab_demo)
FIND_PACKAGE(OpenCV REQUIRED)
include_directories(./) # daheng include files
add_executable (${PROJECT_NAME} main.cpp)
target_link_libraries (${PROJECT_NAME} ${OpenCV_LIBS} gxiapi) # libgxiapi.so is daheng lib file
2.3 generate_demo.sh
#!/bin/bash
rm -rf build
mkdir build
cd build
cmake ..
make
2.4 main.cpp
下面的例子是用大恒相机连续采集1500张图像,并用opencv的窗口实时显示出来。
代码比较大,是因为加了很多错误判断和信息打印的代码,防止异常出现。
核心的获取图像代码是
status = GXDQBuf(hDevice, &pFrameBuffer, 1000);
和
status = GXQBuf(hDevice, pFrameBuffer);
之间的代码。
调用GXDQBuf()
获取一帧图像,
调用GXQBuf()
将图像buffer放回库中继续采图
#include "GxIAPI.h"
#include "DxImageProc.h"
#include
#include
using namespace std;
using namespace cv;
//Show error message
#define GX_VERIFY(emStatus) \
if (emStatus != GX_STATUS_SUCCESS) \
{ \
GetErrorString(emStatus); \
return emStatus; \
}
//Show error message, close device and lib
#define GX_VERIFY_EXIT(emStatus) \
if (emStatus != GX_STATUS_SUCCESS) \
{ \
GetErrorString(emStatus); \
GXCloseDevice(hDevice); \
hDevice = NULL; \
GXCloseLib(); \
printf("\n"); \
return emStatus; \
}
//Get description of error
void GetErrorString(GX_STATUS);
int main(int argc, char* argv[])
{
GX_STATUS status = GX_STATUS_SUCCESS;
GX_DEV_HANDLE hDevice = NULL;
uint32_t nDeviceNum = 0;
//Initialize libary
status = GXInitLib();
if (status != GX_STATUS_SUCCESS) {
GetErrorString(status);
GXCloseLib();
return 0;
}
//Get device enumerated number
status = GXUpdateDeviceList(&nDeviceNum, 1000);
if (status != GX_STATUS_SUCCESS) {
GetErrorString(status);
GXCloseLib();
return 0;
}
//If no device found, app exit
if(nDeviceNum <= 0) {
printf("\n");
GXCloseLib();
return 0;
}
//Open first device enumerated
status = GXOpenDeviceByIndex(1, &hDevice);
if (status != GX_STATUS_SUCCESS) {
GetErrorString(status);
GXCloseLib();
return 0;
}
//Set acquisition mode
status = GXSetEnum(hDevice, GX_ENUM_ACQUISITION_MODE, GX_ACQ_MODE_CONTINUOUS);
GX_VERIFY_EXIT(status);
//Set trigger mode
status = GXSetEnum(hDevice, GX_ENUM_TRIGGER_MODE, GX_TRIGGER_MODE_OFF);
GX_VERIFY_EXIT(status);
//Device start acquisition
status = GXStreamOn(hDevice);
if(status != GX_STATUS_SUCCESS) {
GX_VERIFY_EXIT(status);
}
PGX_FRAME_BUFFER pFrameBuffer = NULL;
// Grab images
int image_count = 1500;
while(image_count--) {
// Get a frame from Queue
status = GXDQBuf(hDevice, &pFrameBuffer, 1000);
if(status != GX_STATUS_SUCCESS) {
if (status == GX_STATUS_TIMEOUT) {
continue;
}
else {
GetErrorString(status);
break;
}
}
if(pFrameBuffer->nStatus != GX_FRAME_STATUS_SUCCESS) {
printf("\n", pFrameBuffer->nStatus);
}
// image process
int width = pFrameBuffer->nWidth;
int height = pFrameBuffer->nHeight;
cout <<"pFrameBuffer size: "<< width <<"x"<pImgBuf);
cv::resize(image, image, cv::Size(width, height) / 2);
cv::imshow("image", image);
cv::waitKey(20);
// break;
// GXQBuf to continue grab image
status = GXQBuf(hDevice, pFrameBuffer);
if(status != GX_STATUS_SUCCESS) {
GetErrorString(status);
break;
}
}
//Device stop acquisition
status = GXStreamOff(hDevice);
if(status != GX_STATUS_SUCCESS) {
GX_VERIFY_EXIT(status);
}
//Close device
status = GXCloseDevice(hDevice);
if(status != GX_STATUS_SUCCESS) {
GetErrorString(status);
hDevice = NULL;
GXCloseLib();
return status;
}
//Release libary
status = GXCloseLib();
if(status != GX_STATUS_SUCCESS) {
GetErrorString(status);
return status;
}
return 0;
}
//----------------------------------------------------------------------------------
/**
\brief Get description of input error code
\param emErrorStatus error code
\return void
*/
//----------------------------------------------------------------------------------
void GetErrorString(GX_STATUS emErrorStatus)
{
char *error_info = NULL;
size_t size = 0;
GX_STATUS emStatus = GX_STATUS_SUCCESS;
// Get length of error description
emStatus = GXGetLastError(&emErrorStatus, NULL, &size);
if(emStatus != GX_STATUS_SUCCESS)
{
printf("\n");
return;
}
// Alloc error resources
error_info = new char[size];
if (error_info == NULL)
{
printf("\n");
return ;
}
// Get error description
emStatus = GXGetLastError(&emErrorStatus, error_info, &size);
if (emStatus != GX_STATUS_SUCCESS)
{
printf("\n");
}
else
{
printf("%s\n", (char*)error_info);
}
// Realease error resources
if (error_info != NULL)
{
delete []error_info;
error_info = NULL;
}
}
2.5 编译运行
在终端执行./generate_demo.sh
便会生成build
目录并开始cmake和make。
make 成功之后会在build
目录下生成可执行程序 daheng_grab_demo
进入build
目录,运行./daheng_grab_demo
,便会实时抓取和显示图像
3. 参考
本文是根据下面的博客和大恒使用手册整理而得:
大恒相机MER-302-56U3M在Linux环境下采集图像
https://blog.csdn.net/qq_42143583/article/details/102523100