ROSNOTE : 视觉系列集


bus 001 Device 002是摄像头 ID 05a3:9230 ARC International
然后输入
dmesg

从上面的打印信息中找到了uvc设备
ROS 教程之 vision : 用各种摄像头获取图像
从视频中提取原图片
https://www.cnblogs.com/qixianyu/p/6575276.html
安装usb_camera
sudo apt install ros-melodic-usb-cam
安装好usb_cam包之后,判断设备确定自己的摄像头是viedo0还是viedo1还是...
cd /dev &&find . -name "video*"
读取图像:
roslaunch usb_cam usb_cam-test.launch
这里的launch文件默认是的"/dev/video0",如果你的是其它名称,则需要执行以下命令(这里以"/dev/video1"举例)
roslaunch usb_cam usb_cam-test.launch video_device:="/dev/video1"
此时ros会读取/dev/video1摄像头的数据
标定校准摄像头:
https://blog.csdn.net/weixin_45839124/article/details/106955386?biz_id=102&utm_term=melodic%20usb_camera%20%E6%A0%A1%E5%87%86&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-106955386&spm=1018.2118.3001.4187
https://blog.csdn.net/qq_41746268/article/details/84752914?biz_id=102&utm_term=melodic%20usb_camera%20%E6%A0%A1%E5%87%86&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-2-84752914&spm=1018.2118.3001.4187
https://blog.csdn.net/pengrui18/article/details/88958487?biz_id=102&utm_term=ros%20usb%20camera&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-88958487&spm=1018.2118.3001.4187
开始标定
rosrun camera_calibration cameracalibrator.py --size 8x6 --square 0.024 image:=/usb_cam/image_raw camera:=/usb_cam
出现

把标定板放入画面中
等到XYSIZESKEW 进度条变化
第一个按钮变亮,然后点击第一个按钮,然后等待一段时间,期间这个窗口会变灰色,但是不用关闭窗口,耐心等待。
参数计算之后会恢复,同时终端会显示标定的结果,点击“save"之后,标定文件会出现在默认的文件夹下,并在终端中看到路径。
(以下内容参考于:这个链接)
在用黑白格校准之后,点击“save"之后会在终端出现下图中的最后一行


进入 /tmp/calibrationdata


mv ost.txt ost.ini
rosrun camera_calibration_parsers convert ost.ini head_camera.yamlmkdir ~/.ros/camera_infomv head_camera.yaml ~/.ros/camera_info
gedit ~/.ros/camera_info/head_camera.yaml
最后只需要打开head_camera.yaml文件修改一下就能保证该校准参数文件正常使用了:


启动文件
//value 现在写的是固定路径,自行修改
-------------------------------------------------------------------------------------------------------------------------------------------------------
以上内容属于图像预处理部分的第一部分,图像的畸变矫正
-------------------------------------------------------------------------------------------------------------------------------------------------------
图像处理的流程:
先创建一个节点,然后创建一个cv_bridge object,使用cv_bridge将ROS的图像数据转换为opencv的图像格式,frame = self.bridge.imgmsg_to_cv2(ros_image, "bgr8"),然后调用处理函数对图像进行处理display_image = self.process_image(frame),先后显示处理后的结果。
ROS中HSV颜色提取:
代码:
#include
#include
#include
#include
using namespace cv;
#include
#include#include
#include
#include
#include
using namespace std;
//输入图像
Mat img;
//灰度值归一化
Mat bgr;
//HSV图像
Mat hsv;
//色相
int hmin = 0;
int hmin_Max = 360;
int hmax = 180;
int hmax_Max = 180;
//饱和度
int smin = 0;
int smin_Max = 255;
int smax = 255;
int smax_Max = 255;
//亮度
int vmin =0;
int vmin_Max = 255;
int vmax = 255;
int vmax_Max = 255;
//显示原图的窗口
string windowName = "src";
//输出图像的显示窗口
string dstName = "dst";
//输出图像
Mat dst;
//回调函数
void callBack(int, void*)
{//输出图像分配内存dst = Mat::zeros(img.size(), img.type());//掩码Mat mask;inRange(hsv, Scalar(hmin, smin, vmin), Scalar(hmax, smax, vmax), mask);//掩模到原图的转换for (int r = 0; r < bgr.rows; r++){for (int c = 0; c < bgr.cols; c++){if (mask.at(r, c) == 255){dst.at(r, c) = bgr.at(r, c);}}}//输出图像imshow(dstName, dst);//保存图像//dst.convertTo(dst, CV_8UC3, 255.0, 0);imwrite("HSV_inRange.jpg", dst);
}void callb(const sensor_msgs::ImageConstPtr& imgPtr)
{cv_bridge::CvImagePtr cv_ptr;cv_ptr = cv_bridge::toCvCopy(imgPtr, sensor_msgs::image_encodings::BGR8);cv_ptr->image.copyTo(img);imshow("img",img);bgr = img.clone();//颜色空间转换cvtColor(bgr, hsv, CV_BGR2HSV);//cout << hsv << endl;//定义输出图像的显示窗口namedWindow(dstName, WINDOW_GUI_EXPANDED);callBack(0,0);waitKey(1);
}int main(int argc, char** argv)
{ros::init(argc, argv, "tupian_debug");ros::NodeHandle nh;ros::Subscriber imageSub = nh.subscribe("/zed/rgb/image_raw_color",10,callb);//输入图像img = imread("/home/wang/Desktop/original_screenshot_14.08.2019.png");if (!img.data || img.channels() != 3)return -1;imshow(windowName, img);bgr = img.clone();//颜色空间转换cvtColor(bgr, hsv, CV_BGR2HSV);// cout << hsv << endl;//定义输出图像的显示窗口namedWindow(dstName, WINDOW_GUI_EXPANDED);//调节色相 HcreateTrackbar("hmin", dstName, &hmin, hmin_Max, callBack);createTrackbar("hmax", dstName, &hmax, hmax_Max, callBack);//调节饱和度 ScreateTrackbar("smin", dstName, &smin, smin_Max, callBack);createTrackbar("smax", dstName, &smax, smax_Max, callBack);//调节亮度 VcreateTrackbar("vmin", dstName, &vmin, vmin_Max, callBack);createTrackbar("vmax", dstName, &vmax, vmax_Max, callBack);//callBack(0,0);ros::spin();return 0;
}
修改:
1、在ROS工作空间修改launch文件以及CMakeLists文件,让其可以运行
2、修改代码中订阅的话题名字,修改为自己相机节点的名字
3、修改“输入图像”图像的位置,换成自己的
4、在调节框中调节所选目标的颜色区域,进行颜色分割,记录H 、S 、V的max以及min值
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
关于cv_bridge 以及 opencv
cv::Mat img; /// Input image in opencv matrix formatcv::Mat img_filt; /// Filtered image in opencv matrix formatint dir; /// Direction message to be published
cv::Mat 是类,它利用了类的特性,将内存管理和数据信息封装在类的内部,用户只需要对Mat类对象进行数据或面向对象操作即可。Mat本质上是由两个数据部分组成的类: (包含信息有矩阵的大小,用于存储的方法,矩阵存储的地址等) 的矩阵头和一个指针,指向包含了像素值的矩阵(可根据选择用于存储的方法采用任何维度存储数据)
CvScalar就是一个包含四个元素的结构体变量
cv::inRange 进行阈值处理
下面代码功能是:将一副图像从rgb颜色空间转换到hsv颜色空间,颜色去除白色背景部分
hsv = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2HSV)
然后利用cv2.inRange函数设阈值,去除背景部分
mask = cv2.inRange(hsv, lower_red, upper_red)
函数很简单,参数有三个
第一个参数:hsv指的是原图
第二个参数:lower_red指的是图像中低于这个lower_red的值,图像值变为0
第三个参数:upper_red指的是图像中高于这个upper_red的值,图像值变为0
mask = cv2.inRange(hsv, lower_red, upper_red) #lower20===>0,upper200==>0,lower~upper==>255
就是将低于lower_red和高于upper_red的部分分别变成0,lower_red~upper_red之间的值变成255
给机器人的线速度是在contro_robot.cpp中
感兴趣区域(ROI,region of interest)
机器视觉、图像处理中,从被处理的图像以方框、圆、椭圆、不规则多边形等方式勾勒出需要处理的区域,称为感兴趣区域,ROI。
在Halcon、OpenCV、Matlab等机器视觉软件上常用到各种算子(Operator)和函数来求得感兴趣区域ROI,并进行图像的下一步处理。 在图像处理领域,感兴趣区域(ROI) 是从图像中选择的一个图像区域,这个区域是你的图像分析所关注的重点。圈定该区域以便进行进一步处理。使用ROI圈定你想读的目标,可以减少处理时间,增加精度。
提取三个关键点是:
1、图像的预处理
2、作物行定位点提取
3、作物行直线拟合
关于第一点:

进行灰度处理,看用哪一种灰度算法处理 ,4种常用的灰度化方法:G-R、2G-R-B、ExG-ExR、在HSI空间提取S分量
对于作物识别或杂草的识别最常用的灰度化方法为超绿色法: ExG=2G-R-B
将图像分离通道
std::vector rgbChannels(3);
split(img, rgbChannels)
1、split—提取R、B、G分量(返回值顺序为:B、G、R)
图像灰度化,以及以640*480大小显示图像
/* gray image*/cvtColor(img,dst,CV_BGR2GRAY);namedWindow("Display gray Image", 0 );cvResizeWindow("Display gray Image",640,480);imshow("Display gray Image", dst);
二值化
Otsu
利用形态学的方法的方法去噪,然后Hough变换,然后利用最小二乘法进行直线拟合
形态学
开操作- open
先腐蚀后膨胀
可以去掉小的对象,假设对象是前景色,背景是黑色
闭操作- close
先膨胀后腐蚀(bin2)
可以填充小的洞(fill hole),假设对象是前景色,背景是黑色
以上都是图像的预处理
定位点的提取
基于特征点群的作物定位点提取算法,常用角点检测进行角点检测
SUSAN特征角点(SUSAN算子是一种高效的边缘和角点检测算子,并且具有结构保留的降噪功能)边缘检测
然后最小二乘法

/*vector > contours;vector hierarchy;findContours(close, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); //CV_RETR_EXTERNAL只检测外部轮廓,可根据自身需求进行调整Mat contoursImage(close.rows, close.cols, CV_8U, Scalar(255));for (int index = 0; index >= 0; index = hierarchy[index][0]) {cv::Scalar color(rand() & 255, rand() & 255, rand() & 255);//cv::drawContours(contoursImage, contours, index, Scalar(0), 3, 8, hierarchy);Rect rect = boundingRect(contours[index]);//检测外轮廓rectangle(contoursImage, rect, Scalar(0,0,255), 3);//对外轮廓加矩形框}//imwrite("/home/robot/pictures/00.jpg", contoursImage);imshow("contour_Image", contoursImage);
*/
压缩图象
参考文章

ROS图象<->OPENCV相互转换
参考原文
这里是一个节点,监听ROS图像信息话题,将图像转换为cv::Mat并在其上画圆,用opencv显示图像。然后图像将重新在ROS上显示。
#include
#include
#include
#include
#include
#include using namespace cv;
using namespace std;
//static const std::string OPENCV_WINDOW = "Image window";class ImageConverter
{ ros::NodeHandle nh_; image_transport::ImageTransport it_; image_transport::Subscriber image_sub_; image_transport::Publisher image_pub_;
public: ImageConverter() : it_(nh_) { // Subscrive to input video feed and publish output video feed image_sub_ = it_.subscribe("/camera/rgb/image_raw", 1,&ImageConverter::imageCb, this); image_pub_ = it_.advertise("/image_converter/output_video", 1); //cv::namedWindow(OPENCV_WINDOW); } ~ImageConverter() { //cv::destroyWindow(OPENCV_WINDOW); } void imageCb(const sensor_msgs::ImageConstPtr& msg) { cv_bridge::CvImagePtr cv_ptr; try { cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8); } catch (cv_bridge::Exception& e) { ROS_ERROR("cv_bridge exception: %s", e.what()); return; }cv::Mat output = detectAndDraw(cv_ptr->image);cv_ptr->image = output;// Output modified video stream image_pub_.publish(cv_ptr->toImageMsg());cv::waitKey(3);}
cv::Mat detectAndDraw(Mat& img){if (img.rows > 60 && img.cols > 60) cv::circle(img, cv::Point(200, 200), 100, CV_RGB(255,0,0)); // Update GUI Window //cv::imshow("crop tracker", img);//cv::imshow(OPENCV_WINDOW, img);return img;}
};int main(int argc, char** argv)
{ ros::init(argc, argv, "image_converter"); ImageConverter ic; ros::spin(); return 0;
}
代码 read_img_send.cpp
功能是订阅相机启动节点的图像,发布经过opencv处理后的图像
目前经过改编之后可以实现,先tx2上处理图像,然后把处理之后的结果发布,然后远程端是可以通过订阅话题看到处理之后的结果的
命令:
roslaunch start_camera uvc_camera.launch
rosrun follow_crop read_img_send
心得:要想成功的在远程端运行,有一点是绝对不能写的,就是不能用imshow(),不能有任何的窗口显示
代码删除没有用到的东西
#include
#include
#include
#include
#include
#include using namespace cv;
using namespace std;class ImageConverter
{ ros::NodeHandle nh_; image_transport::ImageTransport it_; image_transport::Subscriber image_sub_; image_transport::Publisher image_pub_;
public: ImageConverter() : it_(nh_) { image_sub_ = it_.subscribe("/camera/rgb/image_raw", 1,&ImageConverter::imageCb, this); image_pub_ = it_.advertise("/image_converter/output_video", 1); } ~ImageConverter() { } void imageCb(const sensor_msgs::ImageConstPtr& msg) { cv_bridge::CvImagePtr cv_ptr; try { cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8); } catch (cv_bridge::Exception& e) { ROS_ERROR("cv_bridge exception: %s", e.what()); return; }cv::Mat output = detectAndDraw(cv_ptr->image);cv_ptr->image = output;image_pub_.publish(cv_ptr->toImageMsg());cv::waitKey(1);}
cv::Mat detectAndDraw(Mat& img){if (img.rows > 60 && img.cols > 60) cv::circle(img, cv::Point(200, 200), 100, CV_RGB(255,0,0)); return img;
}
};int main(int argc, char** argv)
{ ros::init(argc, argv, "image_converter"); ImageConverter ic; ros::spin(); return 0;
}
整合完毕之后,先启动相机,然后启动识别秧苗线的程序,在rqt中查看话题,反馈回来的图象信息
感觉方向信息没有发布成功,之后进行测试。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
