因为比赛需要,打算开拓一个新领域,在ROS中写opencv,然后调用opencv里面的函数进行循白线的程序,接着串口通讯给单片机。
ROS这个工具总的来说在结合多传感器进行多任务处理的时候优势非常大,最明显的是像导航机器人或者无人驾驶这种需要用到。多点熟悉这个工具吧。
ROS中的语法跟opencv不太一样,不过也是可以转换的,使用cv_bridge这个包来进行转换,先从简单的开始写吧,按照学opencv的方法全部用ROS改写就行了。
下面这个是简单的灰度处理与边缘检测结合的程序,建议opencv全部使用Mat来写,可移植性强。
还需要注意的是CvImage的指针用法,貌似一个指针只能处理一个cv::Mat类型的图像。
测试效果图:
使用rqt_graph查看关系
#include//ros标准库头文件
#include//C++标准输入输出库
#include
#include
#include
#include
#include
#include
staticconststd::stringOPENCV_WINDOW1="Image window";//定义输入窗口名称
staticconststd::stringOPENCV_WINDOW2="Gray window";//定义输出窗口名称
staticconststd::stringOPENCV_WINDOW3="Canny window";//定义输出窗口名称
//定义一个转换的类
classRGB_GRAY
{
private:
ros::NodeHandlenh_;//定义ROS句柄
image_transport::ImageTransportit_;//定义一个image_transport实例
image_transport::Subscriberimage_sub_;//定义ROS图象接收器
image_transport::Publisherimage_pub_;//定义ROS图象发布器
public:
RGB_GRAY()
:it_(nh_)//构造函数
{
image_sub_=it_.subscribe("/cv_camera/image_raw",1,&RGB_GRAY::convert_callback,this);//定义图象接受器,订阅话题是“camera/rgb/image_raw”
image_pub_=it_.advertise("/image_converter/output_video",1);//定义图象发布器
//初始化输入输出窗口
cv::namedWindow(OPENCV_WINDOW1);
cv::namedWindow(OPENCV_WINDOW2);
cv::namedWindow(OPENCV_WINDOW3);
}
~RGB_GRAY()//析构函数
{
cv::destroyWindow(OPENCV_WINDOW1);
cv::destroyWindow(OPENCV_WINDOW2);
cv::destroyWindow(OPENCV_WINDOW3);
}
/*
这是一个ROS和OpenCV的格式转换回调函数,将图象格式从sensor_msgs/Image ---> cv::Mat
*/
voidconvert_callback(constsensor_msgs::ImageConstPtr&msg)
{
cv_bridge::CvImagePtrcv_ptr1;// 声明一个CvImage指针的实例
cv_bridge::CvImagePtrcv_ptr2;// 声明一个CvImage指针的实例
try
{
cv_ptr1=cv_bridge::toCvCopy(msg,sensor_msgs::image_encodings::BGR8);//将ROS消息中的图象信息提取,生成新cv类型的图象,复制给CvImage指针
cv_ptr2=cv_bridge::toCvCopy(msg,sensor_msgs::image_encodings::BGR8);//将ROS消息中的图象信息提取,生成新cv类型的图象,复制给CvImage指针
}
catch(cv_bridge::Exception&e)//异常处理
{
ROS_ERROR("cv_bridge exception: %s",e.what());
return;
}
image_process1(cv_ptr1->image);//得到了cv::Mat类型的图象,在CvImage指针的image中,将结果传送给处理函数
image_process2(cv_ptr2->image);//得到了cv::Mat类型的图象,在CvImage指针的image中,将结果传送给处理函数
}
/*这是图象处理的主要函数,一般会把图像处理的主要程序写在这个函数中。这里的例子只是一个彩色图象到灰度图象的转化*/
voidimage_process1(cv::Matimg1)//这里是灰度处理
{
cv::Matimg_out1;
cv::cvtColor(img1,img_out1,CV_RGB2GRAY);//转换成灰度图象
cv::imshow(OPENCV_WINDOW1,img1);
cv::imshow(OPENCV_WINDOW2,img_out1);
cv::waitKey(5);
}
voidimage_process2(cv::Matimg2)//这里是边缘检测
{
cv::Matdstframe;
cv::Matedge;
cv::MatgrayVideo;
dstframe.create(img2.size(),img2.type());
cv::cvtColor(img2,grayVideo,CV_BGR2GRAY);
cv::blur(grayVideo,edge,cvSize(15,15));
cv::Canny(edge,edge,0,30,3);
cv::imshow(OPENCV_WINDOW3,edge);
cv::waitKey(5);
}
};
//主函数
intmain(intargc,char**argv)
{
ros::init(argc,argv,"RGB");
RGB_GRAY obj;
ros::spin();
}