agx 安装ros opencv_ROS学习笔记——机器视觉

d本次笔记主要记录了自己在ROS机器视觉这一部分的学习。在机器视觉系统中,计算机摄像头的光敏元件将光信号转换为数字信号,并且将其量化为数字矩阵,用此来表示物体反光的强弱。

首先是了解ROS中的图像的数据,因为不同的摄像头发布不同的rt图像数据格式,所以在处理这些数据之前,必须要对这些数据格式有一定的了解(本次学习主要以USB摄像头为例)。

1、驱动USB摄像头

ROS中使用USB摄像头非常容易,可以直接使用usb_cam功能包驱动。

sudo apt-get install ros-melodic-usb-cam #安装usb_cam功能包

安装完成之后就可以用以下命令启动摄像头:

roslaunch usb_cam usb_cam-test.launch
rqt_image_view    

启动成功之后就会自动弹出摄像头的窗口,如下图所示。

agx 安装ros opencv_ROS学习笔记——机器视觉_第1张图片

启动摄像头成功之后就可以使用以下命令来查看话题信息和图像消息的详细定义:

rostopic info /usb_cam/image_raw
rosmsg show sensor_msgs/Image

agx 安装ros opencv_ROS学习笔记——机器视觉_第2张图片

从上图可以看到图像话题的消息类型为sensor_msgs/Image,并且在第二个终端里可以看到图像数据的具体内容。

header:消息头
height(width):图像纵向(横向)分辨率
encoding:图像的编码格式
is_bigendian:图像数据的大小端存储模式

2、摄像头标定

由于摄像头内部以及外部的一些原因,生成的物体图像通常会发生畸变,为了避免数据源造成的误差,需要对摄像头参数进行标定。(此处需要制作一个标定靶)

sudo apt-get install ros-melodic-camera-calibration  #安装摄像头标定功能包
roslaunch robot_vision usb_cam.launch
rosrun camera_calibration cameracalibrator.py --size 8x6 --square 0.024 image:=/usb_cam/image_raw camera:=/usb_cam

其中第三条命令中cameracalibrator.py标定需要以下几个参数:

size:标定棋盘的内部的角点个数
square:这个参数对应每个棋盘格的边长,单位为m
image和camera:设置摄像头发布的图像话题

上面的命令启动成功之后,将制作好的标定靶放置在视野范围内,就可以看到下图所示的界面。

agx 安装ros opencv_ROS学习笔记——机器视觉_第3张图片

在标定过程中不断移动旋转标定靶直到”CALIBRATE”按钮变为绿色,标志着标定程序的参数采集完成。此时就可以点击”CALIBRATE”按钮,标定程序开始自动计算摄像头的标定参数。点击SAVE就可以将可以将标定参数保存在默认文件夹下,点击COMMIT按钮,提交数据并且退出。然后打开相应文件夹就可以看到标定结果的压缩文件calibrationdata.tar.gz;解压之后就如下图所示。里面的ost.yaml命名的为标定结果文件,可以将其复制重新命名就可以使用了。

agx 安装ros opencv_ROS学习笔记——机器视觉_第4张图片

3、OpenCV库及其人脸识别

基于OpenCV库,可以快速的开发机器视觉方面的应用,而ROS中集成了OpenCV库的相关接口功能包,使用下面的命令即可安装:

sudo apt-get install ros-melodic-vision-opencv libopencv-dev python-opencv

在ROS中提供了与OpenCV的接口功能包——cv_bridge,类似于之前的carla-autoware bridge,将两个相连接。开发者可以通过该功能包将ROS中的图像数据转换成OpenCV格式。

agx 安装ros opencv_ROS学习笔记——机器视觉_第5张图片
cv_bridge功能包的作用

此处启动一个小例程(此时需要有一个robot_viision功能包,然后编译工作空间),通过以下命令启动该例程(此处需要将py文件的权限改为可执行文件)

roslaunch robot_vision usb_cam.launch
rosrun robot_vision cv_bridge_test.launch
rqt_image_view

运行之后的效果图如下图所示。

agx 安装ros opencv_ROS学习笔记——机器视觉_第6张图片

实现上述功能的源码robot_vision/scripts/cv_bridge_test.py的步骤中首先是导入相应的模块,然后就是定义一个subscriber接收原始的图像消息,再定义一个Publisher发布OpenCV处理之后的图像消息。最后就是一些ROS图像消息与OpenCV图像数据之间的转换。

import cv2
from cv_bridge import CvBridge,CvBridgeError    #导入相应模块

定义一个Subscriber接受原始图像消息,再定义一个Publisher发布OpenCV处理后的图像消息,还需要一个CvBridge的句柄,便于调用相关转换接口。

self.image_pub = rospy.Publisher("cv_bridge_image",Image,queue_size = 1)
self.bridge = CvBridge()
self.image_sub = rospy.Subscriber("/usb_cam/image_raw",Image,self.callback)

在这个例程的源码中主要的是imgmsg_to_cv2()、cv2_to_imgmsg()这两个接口函数的使用方法。

此处来进行ROS和OpenCV的结合来实现人脸识别的机器视觉应用。OpenCV中的人脸识别算法首先将获取的图像进行灰度转化、边缘处理和噪声过滤;然后缩小图像、直方图均衡化,匹配分类器放大相同倍数直到大于检测图像,则返回匹配结果。

使用下面命令来启动摄像头,然后运行face_detector.launch启动人脸识别功能:

roslaunch robot_vision usb_cam.launch
roslaunch robot_vision face_detector.launch

启动完成之后就可以在摄像头中看到相应的效果,设别到人脸的区域使用绿色矩形框标识。

下面为face_detector.py的源码主要分为三部分。

1、初始化部分

主要完成ROS节点、图像、识别参数的设置。

  def __init__(self):
        rospy.on_shutdown(self.cleanup);

        # 创建cv_bridge
        self.bridge = CvBridge()
        self.image_pub = rospy.Publisher("cv_bridge_image", Image, queue_size=1)

        # 获取haar特征的级联表的XML文件,文件路径在launch文件中传入
        cascade_1 = rospy.get_param("~cascade_1", "")
        cascade_2 = rospy.get_param("~cascade_2", "")

        # 使用级联表初始化haar特征检测器
        self.cascade_1 = cv2.CascadeClassifier(cascade_1)
        self.cascade_2 = cv2.CascadeClassifier(cascade_2)

        # 设置级联表的参数,优化人脸识别,可以在launch文件中重新配置
        self.haar_scaleFactor  = rospy.get_param("~haar_scaleFactor", 1.2)
        self.haar_minNeighbors = rospy.get_param("~haar_minNeighbors", 2)
        self.haar_minSize      = rospy.get_param("~haar_minSize", 40)
        self.haar_maxSize      = rospy.get_param("~haar_maxSize", 60)
        self.color = (50, 255, 50)

        # 初始化订阅rgb格式图像数据的订阅者,此处图像topic的话题名可以在launch文件中重映射
        self.image_sub = rospy.Subscriber("input_rgb_image", Image, self.image_callback, queue_size=1)

2、ROS图像回调函数

当接收到摄像头发布的RGB图像数据之后进入回调函数,将图像转换成OpenCV的数据格式,然后处理之后调用人脸识别的功能函数,最后发布结果。

 def image_callback(self, data):
        # 使用cv_bridge将ROS的图像数据转换成OpenCV的图像格式
        try:
            cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")     
            frame = np.array(cv_image, dtype=np.uint8)
        except CvBridgeError, e:
            print e

        # 创建灰度图像
        grey_image = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # 创建平衡直方图,减少光线影响
        grey_image = cv2.equalizeHist(grey_image)

        # 尝试检测人脸
        faces_result = self.detect_face(grey_image)

        # 在opencv的窗口中框出所有人脸区域
        if len(faces_result)>0:
            for face in faces_result: 
                x, y, w, h = face
                cv2.rectangle(cv_image, (x, y), (x+w, y+h), self.color, 2)

        # 将识别后的图像转换成ROS消息并发布
        self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))

3、人脸识别

人脸识别部分直接调用了OpenCV提供的人脸识别接口,与库中的人脸特征进行匹配。

 def detect_face(self, input_image):
        # 首先匹配正面人脸的模型
        if self.cascade_1:
            faces = self.cascade_1.detectMultiScale(input_image, 
                    self.haar_scaleFactor, 
                    self.haar_minNeighbors, 
                    cv2.CASCADE_SCALE_IMAGE, 
                    (self.haar_minSize, self.haar_maxSize))
                                         
        # 如果正面人脸匹配失败,那么就尝试匹配侧面人脸的模型
        if len(faces) == 0 and self.cascade_2:
            faces = self.cascade_2.detectMultiScale(input_image, 
                    self.haar_scaleFactor, 
                    self.haar_minNeighbors, 
                    cv2.CASCADE_SCALE_IMAGE, 
                    (self.haar_minSize, self.haar_maxSize))
        
        return faces

本文相关源代码获取:链接:https://pan.baidu.com/s/1Kep7-FlKmBNpu6wI0bEoqQ 提取码:5181

参考

  • 《ROS机器人开发实践》

你可能感兴趣的:(agx,安装ros,opencv)