最近在做无人驾驶方面的东西,老师给了一个摄像头,是Gige协议,公司叫microview的不知名公司,连驱动也只有ubuntu16.04的。百度一搜,有关ROS的都是USB摄像头,仔细想想,USB摄像头还是小儿科了一点,性能应该不如千兆网口的。基本现在市面买的摄像头也没提供ros方案。于是只能自己写package。
用千兆网口摄像机的几种解决方案
1千兆网口,但协议是rstp之类的网络摄像头。这种摄像头是输出h.265或者MJPEG之类的格式。不管在opencv还是ros都容易调用
2 gige/gig version协议摄像头。这是本文重点。
如果买的是巴斯勒(basler)或者prosilica牌子的摄像头,你可以:
1 使用现有包
basler有官方的ros包,名称叫做pylon-ros-camera。这是专门为basler品牌设计的ros package。同时,basler官网可以下载pylon软件,功能界面都不错,方便调参。prosilica_driver是prosilica相机的package。经过测试,我的相机不能被它们识别。
当你买的是其他品牌时候:
首先我找到了camera_aravis这个ros package。相当不错,基本支持了所有的摄像机协议,同时默认发布两个topic: /camera/image_raw和/camera/camera_info。
其实这时候就完全可以在ros下使用了。可是在rviz的image界面订阅/camera/image_raw的时候,图像黑屏,奇怪的是一直在显示接收到图片。最终发现,camera_aravis自动将增益设置为1。正常情况下,增益不应该低于15。
进一步改进
此时,你应该已经能在rviz下看到接收到的图像了。但你发现是黑白的,为了有更好的效果,以及为了后期使用视觉算法,我决定将其转换成OPENCV的 MAT图像格式。
一开始我想用image_proc包实现,但始终报错,
编译自己的ROS包
我考虑过对每个像素进行操作,通过指针的方式,处理bayergr8原始图像数据,但始终有core dump的报错(问题可能出在没有动态分配内存)。总之,我决定使用opencv自带的转换参数:cv::COLOR_Bayer2RGB即可。
代码如下:
main.cpp
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "std_msgs/String.h"
#include<vector>
#include<iostream>
#include <opencv2/opencv.hpp>
//
/// \brief cxg_bgr
/// \param array_bayer
///this is convert of raw bayerrg8 to rgb format(1280*1024)
/
void cxg_bgr(unsigned char *array_bayer)
{
cv::Mat opencv_Bayer(cv::Size(1280,1024),CV_8UC1); // bayer data in opencv (value is equl to raw ros bayer data)
cv::Mat opencv_Bgr(cv::Size(1280,1024),CV_8UC3); //final bgr data in opencv
int framesize = 1280 * 1024;
unsigned char * bayerdata=( unsigned char *) malloc (sizeof( unsigned char * ) * framesize);
bayerdata=array_bayer; //bayerdata is a temp variable
opencv_Bayer.data=bayerdata;
printf("opencv bayer: %d\n",opencv_Bayer.data[10000]);
cv::cvtColor(opencv_Bayer, opencv_Bgr, cv::COLOR_BayerGR2RGB);
printf("opencv bgr channel1:%d channel2:%d channel3:%d\n",opencv_Bgr.at<cv::Vec3b>(1000,1000)[0],opencv_Bgr.at<cv::Vec3b>(1000,1000)[1],opencv_Bgr.at<cv::Vec3b>(0,0)[2]);
imshow("view",opencv_Bgr);
cv::waitKey(30);
}
void convertCallback(const sensor_msgs::ImageConstPtr& msg)
{
// unsigned char *data;
try
{
//ROS_INFO("%d",msg->step);
// std::vector<unsigned char> dataccc;
const unsigned char * tmp = &(msg->data[0]);
unsigned char array[1310720];
unsigned char *array_bayer = (unsigned char *)tmp;
unsigned char *array_bgr;
cxg_bgr(array_bayer);
}
catch (cv_bridge::Exception& e)
{
ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
}
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "cxg_camera");
ros::NodeHandle cxg;
cv::namedWindow("view");
cv::startWindowThread();
image_transport::ImageTransport it(cxg);
image_transport::Subscriber sub = it.subscribe("/camera/image_raw", 1000, convertCallback);
ros::spin();
return 0;
}
CMakelist.txt
# http://ros.org/doc/groovy/api/catkin/html/user_guide/supposed.html
cmake_minimum_required(VERSION 2.8.3)
project(cxg_camera)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules)
find_package(OpenCV REQUIRED)
find_package(catkin REQUIRED COMPONENTS roscpp sensor_msgs image_transport camera_info_manager dynamic_reconfigure driver_base tf dynamic_reconfigure cv_bridge std_msgs)
catkin_package(
CATKIN_DEPENDS roscpp sensor_msgs image_transport camera_info_manager dynamic_reconfigure driver_base tf cv_bridge std_msgs
INCLUDE_DIRS
LIBRARIES
)
include_directories(include ${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} )
add_executable(cxg main.cpp)
target_link_libraries(cxg ${catkin_LIBRARIES} ${OpenCV_LIBS})
add_dependencies(cxg ${PROJECT_NAME}_gencfg).
packae.xml
<package>
<name>cxg_camera</name>
<version>2.0.0</version>
<description>camera_aravis: An ethernet camera driver for ROS.</description>
<maintainer email="stevesafarik@gmail.com">Steve Safarik</maintainer>
<author email="stevesafarik@gmail.com">Steve Safarik</author>
<author email="andrew.straw@imp.ac.at">Andrew Straw</author>
<license>LGPLv2</license>
<url type="website">http://github.com/ssafarik/camera_aravis</url>
<author>strawlab</author>
<author>Steve Safarik</author>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>camera_info_manager</build_depend>
<build_depend>dynamic_reconfigure</build_depend>
<build_depend>driver_base</build_depend>
<build_depend>tf</build_depend>
<build_depend>cv_bridge</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>opencv2</build_depend>
<run_depend>roscpp</run_depend>
<run_depend>sensor_msgs</run_depend>
<run_depend>image_transport</run_depend>
<run_depend>camera_info_manager</run_depend>
<run_depend>dynamic_reconfigure</run_depend>
<run_depend>driver_base</run_depend>
<run_depend>tf</run_depend>
<run_depend>cv_bridge</run_depend>
<run_depend>std_msgs</run_depend>
<run_depend>opencv2</run_depend>
</package>
最终效果: