海康相机---采集图像
理论知识
一、环境准备
1. 系统要求
Linux,Windows,Mac都可,由于linux的工业应用普遍性,在此用Linux为例讲解。
2. 硬件连接
- USB相机:通过USB3.0线缆连接相机,确保供电充足(建议使用有源USB hub)。
- GigE相机:
- 配置相机IP:使用海康官方工具(如MVS Linux版)或
ifconfig
设置电脑IP与相机同网段(默认相机IP为192.168.1.60
)。 - 安装
libpcap
库:用于网络通信,执行sudo apt-get install libpcap-dev
(Ubuntu)或sudo yum install libpcap-devel
(CentOS)。
- 配置相机IP:使用海康官方工具(如MVS Linux版)或
3. 依赖库安装
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y libusb-1.0-0-dev libudev-dev libopencv-dev# CentOS/RHEL
sudo yum install -y libusb-devel libudev-devel opencv-devel
二、SDK下载与安装
1. 获取SDK
- 访问海康威视机器视觉官网,下载对应版本的Linux MVSDK(区分32位/64位,工业相机SDK包名通常为
Hikvision_MV_SDK_Linux_x86_64_Vx.x.x.tar.gz
)。
2. 解压与配置
tar -zxvf Hikvision_MV_SDK_Linux_x86_64_Vx.x.x.tar.gz -C /usr/local/hikvision_mvsdk
cd /usr/local/hikvision_mvsdk
- 目录结构:
include/
:头文件(MvCameraControl.h
为核心接口)。lib/
:动态链接库(libMvCameraControl.so
为核心库)。samples/
:示例代码(C++/Python)。
3. 添加库路径
# 临时生效(当前终端)
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/hikvision_mvsdk/lib# 永久生效(全局)
sudo sh -c 'echo "/usr/local/hikvision_mvsdk/lib" >> /etc/ld.so.conf.d/hikvision.conf'
sudo ldconfig
三、权限配置
1. USB相机权限
# 创建udev规则
sudo tee /etc/udev/rules.d/51-hikvision-camera.rules <<EOF
SUBSYSTEM=="usb", ATTRS{idVendor}=="0408", MODE="0666", GROUP="plugdev"
EOF
sudo udevadm control --reload-rules && sudo udevadm trigger
# 将当前用户加入plugdev组
sudo usermod -aG plugdev $USER
newgrp plugdev # 重新登录后生效
2. GigE相机权限
# 允许非root用户访问网络设备(需谨慎)
sudo setcap cap_net_raw,cap_net_admin+eip $(which your_program)
四、核心API流程与代码示例
1. 关键API调用流程
2. C++示例代码(同步采集单张图像)
#include <iostream>
#include "MvCameraControl.h"using namespace std;int main() {// 1. 初始化SDKMV_CC_InitSDK();// 2. 枚举设备MV_CC_DEVICE_INFO_LIST stDeviceList;int nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);if (nRet != MV_OK) {cerr << "枚举设备失败, 错误码: " << nRet << endl;return -1;}if (stDeviceList.nDeviceNum == 0) {cerr << "未发现设备" << endl;return -1;}// 3. 创建句柄并打开设备(以第一个设备为例)MV_CC_HANDLE hDevice;nRet = MV_CC_CreateHandle(&hDevice, stDeviceList.pDeviceInfo[0]);if (nRet != MV_OK) {cerr << "创建设备句柄失败, 错误码: " << nRet << endl;return -1;}nRet = MV_CC_OpenDevice(hDevice);if (nRet != MV_OK) {cerr << "打开设备失败, 错误码: " << nRet << endl;MV_CC_DestroyHandle(hDevice);return -1;}// 4. 配置参数(示例:设置自动曝光)MV_EXPOSURE_MODE_TYPE eExpMode = MV_EXPOSURE_MODE_AUTO;nRet = MV_CC_SetEnumValue(hDevice, "ExposureMode", eExpMode);if (nRet != MV_OK) {cerr << "设置曝光模式失败, 错误码: " << nRet << endl;}// 5. 开始抓图nRet = MV_CC_StartGrabbing(hDevice);if (nRet != MV_OK) {cerr << "开始抓图失败, 错误码: " << nRet << endl;MV_CC_CloseDevice(hDevice);MV_CC_DestroyHandle(hDevice);return -1;}// 6. 同步获取图像(超时时间1000ms)MV_FRAME_OUT_INFO_EX stFrameInfo = {0};unsigned char* pData = nullptr;nRet = MV_CC_GetImageBuffer(hDevice, &pData, &stFrameInfo, 1000);if (nRet == MV_OK && stFrameInfo.nFrameStatus == MV_FRAME_STATUS_SUCCESS) {cout << "获取图像成功, 宽度: " << stFrameInfo.nWidth << ", 高度: " << stFrameInfo.nHeight << ", 像素格式: " << stFrameInfo.enPixelType << endl;// 7. 示例:转换为BGR格式(需OpenCV支持)if (stFrameInfo.enPixelType == PixelType_Gvsp_Mono8) {cv::Mat img(stFrameInfo.nHeight, stFrameInfo.nWidth, CV_8UC1, pData);cv::imwrite("capture.jpg", img);cout << "图像已保存为capture.jpg" << endl;}} else {cerr << "获取图像失败, 错误码: " << nRet << endl;}// 8. 停止抓图并释放资源MV_CC_StopGrabbing(hDevice);MV_CC_CloseDevice(hDevice);MV_CC_DestroyHandle(hDevice);MV_CC_UnInitSDK();return 0;
}
3. 编译命令(使用GCC)
g++ -o capture capture.cpp -I/usr/local/hikvision_mvsdk/include \
-L/usr/local/hikvision_mvsdk/lib -lMvCameraControl -lpthread -ldl -lopencv_core -lopencv_highgui
五、参数配置与高级功能
1. 常用参数设置
参数名称 | 接口函数 | 示例代码 |
---|---|---|
分辨率 | MV_CC_SetEnumValue | MV_CC_SetEnumValue(hDevice, "Width", 1920); |
帧率限制 | MV_CC_SetFloatValue | MV_CC_SetFloatValue(hDevice, "AcquisitionFrameRate", 30.0); |
手动曝光时间 | MV_CC_SetFloatValue | MV_CC_SetFloatValue(hDevice, "ExposureTime", 10000.0); (单位:μs) |
增益 | MV_CC_SetIntValue | MV_CC_SetIntValue(hDevice, "Gain", 10); |
ROI区域 | MV_CC_SetStructValue | MV_Roi roi = {x, y, width, height}; MV_CC_SetStructValue(hDevice, "Roi", &roi); |
触发模式(软触发) | MV_CC_SetEnumValue + MV_CC_SoftTrigger | MV_CC_SetEnumValue(hDevice, "TriggerMode", MV_TRIGGER_MODE_ON); MV_CC_SoftTrigger(hDevice); |
2. 图像格式转换
// 将RAW格式转换为BGR(以Mono8转BGR为例)
MV_PIXEL_CONVERT_PARAM stConvertParam = {0};
stConvertParam.nWidth = stFrameInfo.nWidth;
stConvertParam.nHeight = stFrameInfo.nHeight;
stConvertParam.pSrcData = pData;
stConvertParam.nSrcDataLen = stFrameInfo.nFrameLen;
stConvertParam.enSrcPixelType = stFrameInfo.enPixelType;
stConvertParam.enDstPixelType = PixelType_BGR8;
unsigned char* pConvertData = new unsigned char[stFrameInfo.nWidth * stFrameInfo.nHeight * 3];
stConvertParam.pDstData = pConvertData;
nRet = MV_CC_ConvertPixelType(hDevice, &stConvertParam);
if (nRet == MV_OK) {// 使用pConvertData创建OpenCV图像cv::Mat bgrImg(stFrameInfo.nHeight, stFrameInfo.nWidth, CV_8UC3, pConvertData);
}
delete[] pConvertData;
六、多相机并发采集
1. 线程安全方案
- 为每个相机创建独立线程,避免句柄竞争。
- 使用互斥锁保护全局资源(如日志输出)。
#include <thread>
#include <mutex>std::mutex mtx;void CaptureThread(MV_CC_HANDLE hDevice) {mtx.lock();MV_CC_StartGrabbing(hDevice);mtx.unlock();// 线程内采集逻辑...mtx.lock();MV_CC_StopGrabbing(hDevice);mtx.unlock();
}int main() {// 枚举所有设备并创建设备句柄...std::vector<MV_CC_HANDLE> handles = {hDevice1, hDevice2};std::vector<std::thread> threads;for (auto& h : handles) {threads.emplace_back(CaptureThread, h);}for (auto& t : threads) {t.join();}return 0;
}
七、常见问题与解决方案
1. 设备枚举失败
- 原因:USB权限不足或GigE相机IP未配置。
- 解决:
- 重新加载udev规则并重启电脑。
- 使用
ifconfig
确认电脑IP与相机同网段(GigE相机)。 - 检查相机电源与线缆连接。
2. 图像采集异常(花屏/丢帧)
- 原因:传输带宽不足或缓冲区设置过小。
- 解决:
- USB相机:确保使用USB3.0接口,调整
TransferBufferNumber
参数(默认8,可增大至16)。 - GigE相机:启用PacketSize自动协商,执行
sudo ethtool -K eth0 gso off
关闭GSO功能。
- USB相机:确保使用USB3.0接口,调整
3. 动态库找不到
- 原因:
LD_LIBRARY_PATH
未正确配置。 - 解决:
- 执行
echo $LD_LIBRARY_PATH
确认路径包含SDK的lib
目录。 - 重新运行
sudo ldconfig
更新系统库缓存。
- 执行
4. 触发模式不生效
- 原因:触发参数未正确配置或触发源错误。
- 解决:
- 确保触发模式设置为
MV_TRIGGER_MODE_ON
,触发源设置为MV_TRIGGER_SOURCE_SOFTWARE
(软触发)或硬件触发源。 - 调用
MV_CC_SoftTrigger
触发采集(软触发场景)。
- 确保触发模式设置为
八、性能优化建议
-
缓冲区管理:
- 增大
GrabBufferNumber
(默认3,可设为5-10)以减少丢帧。 - 使用异步采集接口
MV_CC_RegisterImageCallBackEx
提升吞吐量。
- 增大
-
网络优化(GigE相机):
- 设置相机
GevSCPSPacketSize
为最大值(通常9000,需交换机支持Jumbo Frame)。 - 禁用相机
GevTimestampEnable
以降低CPU占用。
- 设置相机
-
预处理优化:
- 在
MV_FRAME_OUT_INFO_EX
中判断nFrameStatus
,跳过无效帧(如MV_FRAME_STATUS_TIMEOUT
)。 - 直接使用原始像素数据(如Mono8),避免不必要的格式转换。
- 在
九、官方资源与支持
- 开发文档:
/usr/local/hikvision_mvsdk/doc/MV_SDK_Programming_Guide.pdf
- 示例代码:
samples/C++/MvSampleGrabImage
(同步采集)、samples/C++/MvSampleGrabImageAsync
(异步采集) - 技术支持:海康威视机器视觉技术支持邮箱(mv_support@hikvision.com)或官网工单系统。
通过以上步骤,可全面掌握Linux下使用海康MVSDK进行图像采集的核心流程与高级功能,覆盖设备控制、参数调优、多线程开发及问题排查等关键知识点。实际开发中建议结合官方文档与调试工具(如strace
跟踪系统调用)进行深度优化。
示例
完整的用Cmake架构,调用Hik相机的代码示例:
//main.cpp
#include "MvCameraControl.h"#include <opencv2/opencv.hpp>
#include <iostream>int main() {// 创建设备列表MV_CC_DEVICE_INFO_LIST stDeviceList;memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));// 枚举设备int nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);if (nRet != MV_OK || stDeviceList.nDeviceNum == 0) {std::cout << "No devices found!" << std::endl;return -1;}// 创建句柄并打开设备void* handle = nullptr;nRet = MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[0]);if (nRet != MV_OK) {std::cout << "Create handle failed!" << std::endl;return -1;}nRet = MV_CC_OpenDevice(handle);if (nRet != MV_OK) {std::cout << "Open device failed!" << std::endl;return -1;}// 开始采集nRet = MV_CC_StartGrabbing(handle);if (nRet != MV_OK) {std::cout << "Start grabbing failed!" << std::endl;return -1;}// 获取图像MV_FRAME_OUT_INFO_EX stImageInfo = {0};unsigned char* pData = (unsigned char*)malloc(1920 * 1080 * 3); // 假设最大分辨率为 1920x1080while (true) {nRet = MV_CC_GetOneFrameTimeout(handle, pData, 1920 * 1080 * 3, &stImageInfo, 1000);if (nRet == MV_OK) {// 转换为 OpenCV 格式cv::Mat img(stImageInfo.nHeight, stImageInfo.nWidth, CV_8UC3, pData);cv::imshow("Image", img);if (cv::waitKey(1) == 27) break; // 按 ESC 退出}}// 停止采集并释放资源MV_CC_StopGrabbing(handle);MV_CC_CloseDevice(handle);MV_CC_DestroyHandle(handle);free(pData);return 0;
}
cmake_minimum_required(VERSION 3.15)
project(HikTest)# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)# 查找 OpenCV 库
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})# 包含海康相机 SDK 的头文件目录
include_directories(/opt/MVS/include) # 请替换为实际的海康 SDK 头文件目录
link_directories(/opt/MVS/lib/64)# 添加可执行文件
add_executable(hik_test hik_test.cpp)# 链接 OpenCV 库
target_link_libraries(hik_test ${OpenCV_LIBS})target_link_libraries(hik_test MvCameraControl)