From 14d7f9e5717025186acfb679029116c66e781fed Mon Sep 17 00:00:00 2001 From: mzxwww Date: Sun, 13 Sep 2026 22:44:23 +0800 Subject: [PATCH] Add CameraGrabber camera wrapper and refactor main loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 inc/camera_set.hpp + src/camera_set.cpp:封装相机初始化、启停、参数设置与取帧 - main.cpp 改用 CameraGrabber,取流循环支持 ESC 退出 - xmake.lua 增加 inc/ 头文件目录与绝对路径 - .gitignore 忽略 wget 日志 --- .gitignore | 4 + .vscode/compile_commands.json | 7 +- inc/camera_set.hpp | 35 ++++++++ src/camera_set.cpp | 162 ++++++++++++++++++++++++++++++++++ src/main.cpp | 115 +++++++----------------- xmake.lua | 3 +- 6 files changed, 240 insertions(+), 86 deletions(-) create mode 100644 inc/camera_set.hpp create mode 100644 src/camera_set.cpp diff --git a/.gitignore b/.gitignore index b70e48d..ee24db6 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ build/ .vscode/.cache/ + +# wget 下载日志 +wget.log +*.log diff --git a/.vscode/compile_commands.json b/.vscode/compile_commands.json index 3aebe96..5b44700 100644 --- a/.vscode/compile_commands.json +++ b/.vscode/compile_commands.json @@ -1,6 +1,11 @@ [ { "directory": "/home/mzxiang/opencv_project/27RM", - "arguments": ["/usr/bin/g++", "-c", "-m64", "-g", "-O0", "-std=c++11", "-I/usr/local/include/opencv4", "-I/home/mzxiang/MindVisionSDK/include", "-o", "build/.objs/27RM/linux/x86_64/debug/src/main.cpp.o", "src/main.cpp"], + "arguments": ["/usr/bin/g++", "-c", "-m64", "-g", "-O0", "-std=c++11", "-I/home/mzxiang/opencv_project/27RM/inc", "-I/usr/local/include/opencv4", "-I/home/mzxiang/MindVisionSDK/include", "-o", "build/.objs/27RM/linux/x86_64/debug/src/main.cpp.o", "src/main.cpp"], "file": "src/main.cpp" +}, +{ + "directory": "/home/mzxiang/opencv_project/27RM", + "arguments": ["/usr/bin/g++", "-c", "-m64", "-g", "-O0", "-std=c++11", "-I/home/mzxiang/opencv_project/27RM/inc", "-I/usr/local/include/opencv4", "-I/home/mzxiang/MindVisionSDK/include", "-o", "build/.objs/27RM/linux/x86_64/debug/src/camera_set.cpp.o", "src/camera_set.cpp"], + "file": "src/camera_set.cpp" }] diff --git a/inc/camera_set.hpp b/inc/camera_set.hpp new file mode 100644 index 0000000..caf807d --- /dev/null +++ b/inc/camera_set.hpp @@ -0,0 +1,35 @@ +#ifndef CAMERA_SET_HPP +#define CAMERA_SET_HPP + +#include "CameraDefine.h" // 类型定义 +#include + + +class CameraGrabber +{ +public: + CameraGrabber(); // 构造函数声明 + ~CameraGrabber(); // 析构函数声明 + + bool initializeCamera(); // 初始化相机 + bool startCamera(); // 启动相机 + bool stopCamera(); // 停止相机 + bool setExposureTime(double exposureTime); // 设置曝光时间 + bool setGain(double gain); // 设置增益 + bool setWhiteBalance(double redGain, double blueGain); // 设置白平衡 + bool setResolution(int width, int height); // 设置分辨率 + bool setFrameRate(double frameRate); // 设置帧率 + bool getFrame(cv::Mat &frame); // 获取一帧图像 + +private: + CameraHandle hCamera = -1; // 相机句柄 + tSdkCameraCapbility capability; // 相机能力描述 + unsigned char *pRgbBuffer = nullptr; // 图像处理缓冲区 + int channel = 3; // 通道数:1 灰度,3 彩色 + bool isInitialized = false; // 是否已初始化 + bool isPlaying = false; // 是否已启动取流 + + +}; + +#endif diff --git a/src/camera_set.cpp b/src/camera_set.cpp new file mode 100644 index 0000000..0ed5854 --- /dev/null +++ b/src/camera_set.cpp @@ -0,0 +1,162 @@ +#include "camera_set.hpp" +#include +#include "CameraApi.h" +#include + +bool CameraGrabber::initializeCamera() +{ + // 初始化检查,防止重复初始化 + if (isInitialized) + { + return true; + } + + int iStatus=-1; // SDK函数返回状态 + tSdkCameraDevInfo tCameraEnumList; // 枚举设备信息列表 + int iCameraCounts = 1; // 设备数量 + + // 初始化相机SDK + CameraSdkInit(1); + + //枚举设备,并建立设备列表 + iStatus = CameraEnumerateDevice(&tCameraEnumList,&iCameraCounts); + + // printf("state = %d\n", CameraGrabber::iStatus); + // printf("count = %d\n", CameraGrabber::iCameraCounts); + + // 没有连接设备 + if(iCameraCounts == 0) + { + return false; + } + + // 相机初始化。初始化成功后,才能调用任何其他相机相关的操作接口 + iStatus = CameraInit(&tCameraEnumList,-1,-1,&hCamera); + + // 初始化失败 + // printf("state = %d\n", CameraGrabber::iStatus); + if(iStatus != CAMERA_STATUS_SUCCESS) + { + return false; + } + + // 获得相机的特性描述结构体。该结构体中包含了相机可设置的各种参数的范围信息。决定了相关函数的参数 + CameraGetCapability(hCamera,&capability); + + // 分配图像处理缓冲区 + pRgbBuffer = (unsigned char*)malloc(capability.sResolutionRange.iHeightMax*capability.sResolutionRange.iWidthMax*3); + //g_readBuf = (unsigned char*)malloc(tCapability.sResolutionRange.iHeightMax*tCapability.sResolutionRange.iWidthMax*3); + + // 设置图像输出格式 + if(capability.sIspCapacity.bMonoSensor) + { + channel=1; + CameraSetIspOutFormat(hCamera,CAMERA_MEDIA_TYPE_MONO8); + } + else + { + channel=3; + CameraSetIspOutFormat(hCamera,CAMERA_MEDIA_TYPE_BGR8); + } + + isInitialized = true; + return true; +} + +bool CameraGrabber::startCamera() +{ + // 初始化检查 + if (!isInitialized) + { + printf("startCamera failed: camera not initialized.\n"); + return false; + } + + // 防止重复启动 + if (isPlaying) + { + return true; + } + + // 开始接收图像 + CameraSdkStatus status = CameraPlay(hCamera); + if (status != CAMERA_STATUS_SUCCESS) + { + printf("CameraPlay failed, status = %d\n", status); + return false; + } + + // 标记状态 + isPlaying = true; + return true; +} + +bool CameraGrabber::stopCamera() +{ + // 停止取流 + if (isPlaying) + { + CameraPause(hCamera); + isPlaying = false; + } + + // 反初始化相机,释放 SDK 内部资源 + if (hCamera != -1) + { + CameraUnInit(hCamera); + hCamera = -1; + } + + // 释放图像缓冲区 + if (pRgbBuffer) + { + free(pRgbBuffer); + pRgbBuffer = nullptr; + } + + // 复位 + isInitialized = false; + return true; +} + +bool CameraGrabber::getFrame(cv::Mat &frame) +{ + // 前者条件检查 + if (!isInitialized || !isPlaying || hCamera == -1) + { + return false; + } + + tSdkFrameHead sFrameInfo; // 图像帧头信息 + BYTE *pbyBuffer = nullptr; // 图像缓冲区指针 + + // 获取图像缓冲区 + if (CameraGetImageBuffer(hCamera, &sFrameInfo, &pbyBuffer, 1000) != CAMERA_STATUS_SUCCESS) + { + return false; + } + + // 图像处理,将原始图像转换为 RGB 格式 + CameraImageProcess(hCamera, pbyBuffer, pRgbBuffer, &sFrameInfo); + + // 将图像数据转换为 OpenCV 的 Mat 对象,并深拷贝 + frame = cv::Mat( + cv::Size(sFrameInfo.iWidth, sFrameInfo.iHeight), + sFrameInfo.uiMediaType == CAMERA_MEDIA_TYPE_MONO8 ? CV_8UC1 : CV_8UC3, + pRgbBuffer + ).clone(); + + // 释放图像缓冲区 + CameraReleaseImageBuffer(hCamera, pbyBuffer); + return true; +} + +CameraGrabber::CameraGrabber() +{ + +} + +CameraGrabber::~CameraGrabber() +{ + stopCamera(); +} diff --git a/src/main.cpp b/src/main.cpp index b73d539..6c56e1d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,96 +1,43 @@ #include -#include -#include "CameraApi.h" +#include "camera_set.hpp" -unsigned char * g_pRgbBuffer; +// unsigned char * g_pRgbBuffer; int main(int argc, char **argv) { - int iCameraCounts = 1; - int iStatus=-1; - tSdkCameraDevInfo tCameraEnumList; - int hCamera; - tSdkCameraCapbility tCapability; //设备描述信息 - tSdkFrameHead sFrameInfo; - BYTE* pbyBuffer; - int iDisplayFrames = 10000; - int channel=3; + // 创建相机对象 + CameraGrabber cam; - CameraSdkInit(1); - - //枚举设备,并建立设备列表 - iStatus = CameraEnumerateDevice(&tCameraEnumList,&iCameraCounts); - printf("state = %d\n", iStatus); - - printf("count = %d\n", iCameraCounts); - //没有连接设备 - if(iCameraCounts==0){ - return -1; - } - - //相机初始化。初始化成功后,才能调用任何其他相机相关的操作接口 - iStatus = CameraInit(&tCameraEnumList,-1,-1,&hCamera); - - //初始化失败 - printf("state = %d\n", iStatus); - if(iStatus!=CAMERA_STATUS_SUCCESS){ - return -1; - } - - //获得相机的特性描述结构体。该结构体中包含了相机可设置的各种参数的范围信息。决定了相关函数的参数 - CameraGetCapability(hCamera,&tCapability); - - // - g_pRgbBuffer = (unsigned char*)malloc(tCapability.sResolutionRange.iHeightMax*tCapability.sResolutionRange.iWidthMax*3); - //g_readBuf = (unsigned char*)malloc(tCapability.sResolutionRange.iHeightMax*tCapability.sResolutionRange.iWidthMax*3); - - /*让SDK进入工作模式,开始接收来自相机发送的图像 - 数据。如果当前相机是触发模式,则需要接收到 - 触发帧以后才会更新图像。 */ - CameraPlay(hCamera); - - /*其他的相机参数设置 - 例如 CameraSetExposureTime CameraGetExposureTime 设置/读取曝光时间 - CameraSetImageResolution CameraGetImageResolution 设置/读取分辨率 - CameraSetGamma、CameraSetConrast、CameraSetGain等设置图像伽马、对比度、RGB数字增益等等。 - 本例程只是为了演示如何将SDK中获取的图像,转成OpenCV的图像格式,以便调用OpenCV的图像处理函数进行后续开发 - */ - - if(tCapability.sIspCapacity.bMonoSensor){ - channel=1; - CameraSetIspOutFormat(hCamera,CAMERA_MEDIA_TYPE_MONO8); - }else{ - channel=3; - CameraSetIspOutFormat(hCamera,CAMERA_MEDIA_TYPE_BGR8); - } - - - //循环显示1000帧图像 - while(iDisplayFrames--) + // 初始化相机 + if (!cam.initializeCamera()) { - if(CameraGetImageBuffer(hCamera,&sFrameInfo,&pbyBuffer,1000) == CAMERA_STATUS_SUCCESS) - { - CameraImageProcess(hCamera, pbyBuffer, g_pRgbBuffer,&sFrameInfo); - - cv::Mat matImage( - cv::Size(sFrameInfo.iWidth, sFrameInfo.iHeight), - sFrameInfo.uiMediaType == CAMERA_MEDIA_TYPE_MONO8 ? CV_8UC1 : CV_8UC3, - g_pRgbBuffer - ); - imshow("Opencv Demo", matImage); - - cv::waitKey(5); - - //在成功调用CameraGetImageBuffer后,必须调用CameraReleaseImageBuffer来释放获得的buffer。 - //否则再次调用CameraGetImageBuffer时,程序将被挂起一直阻塞,直到其他线程中调用CameraReleaseImageBuffer来释放了buffer - CameraReleaseImageBuffer(hCamera,pbyBuffer); - - } + printf("initializeCamera failed.\n"); + return -1; } - CameraUnInit(hCamera); - //注意,现反初始化后再free - free(g_pRgbBuffer); + // 取流 + if (!cam.startCamera()) + { + printf("startCamera failed.\n"); + return -1; + } + + // 循环取图并显示 + cv::Mat frame; + + while(true) + { + if (cam.getFrame(frame)) + { + cv::imshow("Opencv Demo", frame); + } + + // 按 ESC 退出 + if (cv::waitKey(5) == 27) + { + break; + } + } return 0; } diff --git a/xmake.lua b/xmake.lua index c9a0e99..ca27378 100644 --- a/xmake.lua +++ b/xmake.lua @@ -6,7 +6,8 @@ set_languages("c++11") target("27RM") set_kind("binary") - add_files("src/*.cpp") + add_files("$(scriptdir)/src/*.cpp") + add_includedirs("$(scriptdir)/inc/") -- openCV配置 add_includedirs("/usr/local/include/opencv4")