在ROS中使用opencv-识别白线

2023-10-18 17:50
文章标签 使用 opencv ros 识别 白线

本文主要是介绍在ROS中使用opencv-识别白线,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

当时写的一个识别白线的程序,还不算完整,后面要自己用程序算出两天线之间中点的坐标,并反馈坐标信息回来,跟底层通讯,做一个闭环。
在这里插入图片描述

#include<ros/ros.h> //ros标准库头文件
#include<iostream> //C++标准输入输出库
#include<cv_bridge/cv_bridge.h>
#include<sensor_msgs/image_encodings.h>
#include<image_transport/image_transport.h>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <cv.h>
#include <math.h>
using namespace std;
using namespace cv;static const std::string OPENCV_WINDOW1 = "Image window"; //定义输入窗口名称
static const std::string OPENCV_WINDOW2 = "Gray window"; //定义输出窗口名称
static const std::string OPENCV_WINDOW3 = "Canny window"; //定义输出窗口名称
static const std::string OPENCV_WINDOW4 = "Hough window"; //定义输出窗口名称
//定义一个转换的类
class RGB_GRAY
{
private:ros::NodeHandle nh_; //定义ROS句柄image_transport::ImageTransport it_; //定义一个image_transport实例image_transport::Subscriber image_sub_; //定义ROS图象接收器image_transport::Publisher image_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);cv::namedWindow(OPENCV_WINDOW4);}~RGB_GRAY() //析构函数{cv::destroyWindow(OPENCV_WINDOW1);cv::destroyWindow(OPENCV_WINDOW2);cv::destroyWindow(OPENCV_WINDOW3);cv::destroyWindow(OPENCV_WINDOW4);}/*这是一个ROS和OpenCV的格式转换回调函数,将图象格式从sensor_msgs/Image  --->  cv::Mat*/void convert_callback(const sensor_msgs::ImageConstPtr& msg){cv_bridge::CvImagePtr cv_ptr1; // 声明一个CvImage指针的实例cv_bridge::CvImagePtr cv_ptr2; // 声明一个CvImage指针的实例cv_bridge::CvImagePtr cv_ptr3; // 声明一个CvImage指针的实例cv_bridge::CvImagePtr cv_ptr4; // 声明一个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指针cv_ptr3 =  cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8); //将ROS消息中的图象信息提取,生成新cv类型的图象,复制给CvImage指针cv_ptr4 =  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中,将结果传送给处理函数image_process3(cv_ptr3->image); //得到了cv::Mat类型的图象,在CvImage指针的image中,将结果传送给处理函数image_process3(cv_ptr3->image); //得到了cv::Mat类型的图象,在CvImage指针的image中,将结果传送给处理函数}/*这是图象处理的主要函数,一般会把图像处理的主要程序写在这个函数中。这里的例子只是一个彩色图象到灰度图象的转化*/void image_process1(cv::Mat img1)//这里是灰度处理{cv::Mat img_out1;cv::cvtColor(img1, img_out1, CV_RGB2GRAY);  //转换成灰度图象cv::imshow(OPENCV_WINDOW1, img1);cv::imshow(OPENCV_WINDOW2, img_out1);cv::waitKey(5);}void image_process2(cv::Mat img2)//这里是边缘检测{cv::Mat dstframe;cv::Mat edge;cv::Mat grayVideo;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);}void image_process3(cv::Mat img3){cv::Mat dst2;cv::Mat cdst2;cv::Canny(img3, dst2, 50, 200, 3);cv::cvtColor(dst2, cdst2, CV_GRAY2BGR);//灰度化vector<Vec2f> lines;HoughLines(dst2, lines, 1, CV_PI/180, 100, 0, 0 );for( size_t i = 0; i < lines.size(); i++ )//将求得的线条画出来{float rho = lines[i][0], theta = lines[i][1];Point pt1, pt2;double a = cos(theta), b = sin(theta);double x0 = a*rho, y0 = b*rho;pt1.x = cvRound(x0 + 1000*(-b));pt1.y = cvRound(y0 + 1000*(a));pt2.x = cvRound(x0 - 1000*(-b));pt2.y = cvRound(y0 - 1000*(a));line( cdst2, pt1, pt2, Scalar(0,0,255), 2, CV_AA);cv::imshow(OPENCV_WINDOW4, cdst2);cout<<"x="<<(pt1.x+pt2.x)/2<<endl;        cout<<"y="<<(pt1.y+pt2.y)/2<<endl;}cv::waitKey(5);}};//主函数int main(int argc, char** argv){ros::init(argc, argv, "RGB");RGB_GRAY obj;ros::spin();}

当时写的一个识别白线的程序,还不算完整,后面要自己用程序算出两天线之间中点的坐标,并反馈坐标信息回来,跟底层通讯,做一个闭环。

#include<ros/ros.h> //ros标准库头文件
#include<iostream> //C++标准输入输出库
#include<cv_bridge/cv_bridge.h>
#include<sensor_msgs/image_encodings.h>
#include<image_transport/image_transport.h>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <cv.h>
#include <math.h>
using namespace std;
using namespace cv;static const std::string OPENCV_WINDOW1 = "Image window"; //定义输入窗口名称
static const std::string OPENCV_WINDOW2 = "Gray window"; //定义输出窗口名称
static const std::string OPENCV_WINDOW3 = "Canny window"; //定义输出窗口名称
static const std::string OPENCV_WINDOW4 = "Hough window"; //定义输出窗口名称
//定义一个转换的类
class RGB_GRAY
{
private:ros::NodeHandle nh_; //定义ROS句柄image_transport::ImageTransport it_; //定义一个image_transport实例image_transport::Subscriber image_sub_; //定义ROS图象接收器image_transport::Publisher image_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);cv::namedWindow(OPENCV_WINDOW4);}~RGB_GRAY() //析构函数{cv::destroyWindow(OPENCV_WINDOW1);cv::destroyWindow(OPENCV_WINDOW2);cv::destroyWindow(OPENCV_WINDOW3);cv::destroyWindow(OPENCV_WINDOW4);}/*这是一个ROS和OpenCV的格式转换回调函数,将图象格式从sensor_msgs/Image  --->  cv::Mat*/void convert_callback(const sensor_msgs::ImageConstPtr& msg){cv_bridge::CvImagePtr cv_ptr1; // 声明一个CvImage指针的实例cv_bridge::CvImagePtr cv_ptr2; // 声明一个CvImage指针的实例cv_bridge::CvImagePtr cv_ptr3; // 声明一个CvImage指针的实例cv_bridge::CvImagePtr cv_ptr4; // 声明一个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指针cv_ptr3 =  cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8); //将ROS消息中的图象信息提取,生成新cv类型的图象,复制给CvImage指针cv_ptr4 =  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中,将结果传送给处理函数image_process3(cv_ptr3->image); //得到了cv::Mat类型的图象,在CvImage指针的image中,将结果传送给处理函数image_process3(cv_ptr3->image); //得到了cv::Mat类型的图象,在CvImage指针的image中,将结果传送给处理函数}/*这是图象处理的主要函数,一般会把图像处理的主要程序写在这个函数中。这里的例子只是一个彩色图象到灰度图象的转化*/void image_process1(cv::Mat img1)//这里是灰度处理{cv::Mat img_out1;cv::cvtColor(img1, img_out1, CV_RGB2GRAY);  //转换成灰度图象cv::imshow(OPENCV_WINDOW1, img1);cv::imshow(OPENCV_WINDOW2, img_out1);cv::waitKey(5);}void image_process2(cv::Mat img2)//这里是边缘检测{cv::Mat dstframe;cv::Mat edge;cv::Mat grayVideo;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);}void image_process3(cv::Mat img3){cv::Mat dst2;cv::Mat cdst2;cv::Canny(img3, dst2, 50, 200, 3);cv::cvtColor(dst2, cdst2, CV_GRAY2BGR);//灰度化vector<Vec2f> lines;HoughLines(dst2, lines, 1, CV_PI/180, 100, 0, 0 );for( size_t i = 0; i < lines.size(); i++ )//将求得的线条画出来{float rho = lines[i][0], theta = lines[i][1];Point pt1, pt2;double a = cos(theta), b = sin(theta);double x0 = a*rho, y0 = b*rho;pt1.x = cvRound(x0 + 1000*(-b));pt1.y = cvRound(y0 + 1000*(a));pt2.x = cvRound(x0 - 1000*(-b));pt2.y = cvRound(y0 - 1000*(a));line( cdst2, pt1, pt2, Scalar(0,0,255), 2, CV_AA);cv::imshow(OPENCV_WINDOW4, cdst2);cout<<"x="<<(pt1.x+pt2.x)/2<<endl;        cout<<"y="<<(pt1.y+pt2.y)/2<<endl;}cv::waitKey(5);}
};
//主函数
int main(int argc, char** argv)
{ros::init(argc, argv, "RGB");RGB_GRAY obj;ros::spin();
}

看着好烦,稍微简化了一下,我写代码的风格是代码量越少越好。可能坐标计算这里还需要改进。

#include<ros/ros.h> //ros标准库头文件
#include<iostream> //C++标准输入输出库
#include<cv_bridge/cv_bridge.h>
#include<sensor_msgs/image_encodings.h>
#include<image_transport/image_transport.h>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;static const std::string OPENCV_WINDOW = "Hough window"; //定义输出窗口名称
//定义一个转换的类
class RGB_GRAY
{
private:ros::NodeHandle nh_; //定义ROS句柄image_transport::ImageTransport it_; //定义一个image_transport实例image_transport::Subscriber image_sub_; //定义ROS图象接收器image_transport::Publisher image_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_WINDOW);}~RGB_GRAY() //析构函数{cv::destroyWindow(OPENCV_WINDOW);}/*这是一个ROS和OpenCV的格式转换回调函数,将图象格式从sensor_msgs/Image  --->  cv::Mat */void convert_callback(const sensor_msgs::ImageConstPtr& msg){cv_bridge::CvImagePtr cv_ptr; // 声明一个CvImage指针的实例try{cv_ptr =  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_process(cv_ptr->image); //得到了cv::Mat类型的图象,在CvImage指针的image中,将结果传送给处理函数}/*这是图象处理的主要函数,一般会把图像处理的主要程序写在这个函数中。这里的例子只是一个彩色图象到灰度图象的转化*/void image_process(cv::Mat img)//这里是灰度处理{Mat dst;Mat cdst;Canny(img, dst, 50, 200, 3);cvtColor(dst, cdst, CV_GRAY2BGR);//灰度化vector<Vec2f> lines;HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );for( size_t i = 0; i < lines.size(); i++ )//将求得的线条画出来{float rho = lines[i][0], theta = lines[i][1];Point pt1, pt2;double a = cos(theta), b = sin(theta);double x0 = a*rho, y0 = b*rho;pt1.x = cvRound(x0 + 1000*(-b));pt1.y = cvRound(y0 + 1000*(a));pt2.x = cvRound(x0 - 1000*(-b));pt2.y = cvRound(y0 - 1000*(a));line( cdst, pt1, pt2, Scalar(0,0,255), 2, CV_AA);cout<<"x="<<(pt1.x+pt2.x)/2<<endl;        cout<<"y="<<(pt1.y+pt2.y)/2<<endl;}imshow(OPENCV_WINDOW, cdst);waitKey(5);}
};
//主函数
int main(int argc, char** argv)
{ros::init(argc, argv, "RGB");RGB_GRAY obj;ros::spin();
}

这篇关于在ROS中使用opencv-识别白线的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/234198

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti