ubuntu16.04下ROS操作系统学习笔记(六 )机器视觉-摄像头标定-ROS+OpenCv-人脸识别-物体跟踪-二维码识别(下)

简介: ubuntu16.04下ROS操作系统学习笔记(六 )机器视觉-摄像头标定-ROS+OpenCv-人脸识别-物体跟踪-二维码识别(下)

Kinetic标定:

之后的操作都类似,具体可以参考原视频。

Opencv

Open Source Computer Vision Library

在ROS当中完成Opencv的安装:

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

ROS与Opencv之间的数据连接是通过CvBridge来实现的。ROS Image Message与OpenCv Ipllmage之间连接的一个桥。

接下来我们测试一下:

roslaunch robot_vision usb_cam.launch

这个命令运行完之后是没有结果输出的,我们之后再启动节点:

rosrun robot_vision cv_bridge_test.py

再打开ROS测试:

显示成功之后表示测试没有问题。

第一张图片显示的是opencv的图像,是经过opencv的接口,与ros没有关系。而第二张图片是通过ros当中订阅话题来显示的。首先是在ros当中启动了一个节点,那么发布的消息也是ros消息的这种类型,然后通过bridge转接到了opencv系统,然后在opencv里面完成一些处理,像在左上角画出一个圈,并且把处理的图片通过opencv显示出来,再通过bridge发回到ros系统里面,ros再订阅这个话题就可以了。

我们可以看一下 刚刚的命令-《 rosrun robot_vision cv_bridge_test.py 》启动的这个节点:

我们首先看一下main函数:

 if __name__ == '__main__':
 try:
 # 初始化ros节点
         rospy.init_node("cv_bridge_test")
         rospy.loginfo("Starting cv_bridge_test node")
         image_converter()
         rospy.spin()
 except KeyboardInterrupt:
 print "Shutting down cv_bridge_test node."
         cv2.destroyAllWindows()

在main函数里面,第一行我们初始化这个节点,第二行输出这个节点的日志信息,第三行调用图像转换函数,第四行通过spin等待回调函数。

之后看一下image_converter类函数。

 class image_converter:
 def __init__(self):    
 # 创建cv_bridge,声明图像的发布者和订阅者
         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)
 def callback(self,data):
 # 使用cv_bridge将ROS的图像数据转换成OpenCV的图像格式
 try:
             cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
 except CvBridgeError as e:
 print e
 # 在opencv的显示窗口中绘制一个圆,作为标记
         (rows,cols,channels) = cv_image.shape
 if cols > 60 and rows > 60 :
             cv2.circle(cv_image, (60, 60), 30, (0,0,255), -1)
 # 显示Opencv格式的图像
         cv2.imshow("Image window", cv_image)
         cv2.waitKey(3)
 # 再将opencv格式额数据转换成ros image格式的数据发布
 try:
             self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))
 except CvBridgeError as e:
 print e

在这个类的初始化里面,声明了一个发布者和一个订阅者。订阅者订阅的是usb摄像头发布的话题“”/usb_cam/image_raw“,后面还有一个callback函数。发布者发布的是最终经过opencv处理之后的图像,也就是我们之前在rqt工具里面看到的图像 ”cv_bridge_image“。之后还调用了一下CvBridge。self.bridge = CvBridge()。

订阅者接收到图像之后就调用回调函数callback:

在callback函数里面,我们将从ros中接收到的图片数据转换为opencv能够读取的格式。通过调用CvBridge函数就可以实现上述功能,最终的cv_image就是opencv能够去处理的格式。之后我们使用opencv函数里面的一些函数cv2.circle去绘制圆。然后将其显示出来。之后我们再通过bridge.cv2_to_imgmsg将其转换为ros系统的数据格式,再将其发布出去。

这里的话需要重点去知道两个函数:

imgmsg_to_cv2():将ros图像消息转换成OpenCv图像数据;

cv2_to_imgmsg():将OpenCv格式的图像数据转换成ros图像消息;

人脸检测

基于Haar特征的级联分类器检测算法主要步骤:

  1. 灰阶色彩转换
  2. 缩小摄像头图像
  3. 直方图均衡化
  4. 检测人脸

代码文件以及视频解释等相关文件在我github里面都可以去找到,这里不方便贴出来。分别在三个终端运行以下命令:

roslaunch robot_vision usb_cam.launch
roslaunch robot_vision face_detector.launch
rqt_image_view

显示结果:

 

我们接下来看一下代码:

if __name__ == '__main__':
    try:
        # 初始化ros节点
        rospy.init_node("face_detector")
        faceDetector()
        rospy.loginfo("Face detector is started..")
        rospy.loginfo("Please subscribe the ROS image.")
        rospy.spin()
    except KeyboardInterrupt:
        print "Shutting down face detector node."
        cv2.destroyAllWindows()

我们首先需要初始化ros节点,之后调用人脸检测器,然后打印出日志信息,等待回调函数等等。

class faceDetector:
    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)
    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"))
    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
    def cleanup(self):
        print "Shutting down vision node."
        cv2.destroyAllWindows()

我们首先初始化一些参数,之后当我们接收到ros来的图像的话,我们调用回调函数,将图像转换成OpenCv的数据格式,在opencv里面创建灰度图像,创建平衡直方图,减少光线影响,之后检测人脸,这些操作都是通过调用函数来实现的,然后将人脸用一个方框框出来。

机器视觉-物体跟踪

通过第一帧与后面帧图像特征点的匹配,来实现物体跟踪,流程如下:

  1. 图像输入
  2. 特征点采样
  3. 两帧图像灰度值对比
  4. 特征点估计
  5. 特征点过滤
  6. 结果输出

代码文件以及视频解释等相关文件在我github里面都可以去找到,这里不方便贴出来。分别在三个终端运行以下命令:

roslaunch robot_vision usb_cam.launch
roslaunch robot_vision motion_detector.launch
rqt_image_view

这里效果太差,就不给予演示了。函数如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
import cv2
import numpy as np
from sensor_msgs.msg import Image, RegionOfInterest
from cv_bridge import CvBridge, CvBridgeError
class motionDetector:
    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)
        # 设置参数:最小区域、阈值
        self.minArea   = rospy.get_param("~minArea",   500)
        self.threshold = rospy.get_param("~threshold", 25)
        self.firstFrame = None
        self.text = "Unoccupied"
        # 初始化订阅rgb格式图像数据的订阅者,此处图像topic的话题名可以在launch文件中重映射
        self.image_sub = rospy.Subscriber("input_rgb_image", Image, self.image_callback, queue_size=1)
    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
        # 创建灰度图像
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        gray = cv2.GaussianBlur(gray, (21, 21), 0)
        # 使用两帧图像做比较,检测移动物体的区域
        if self.firstFrame is None:
            self.firstFrame = gray
            return  
        frameDelta = cv2.absdiff(self.firstFrame, gray)
        thresh = cv2.threshold(frameDelta, self.threshold, 255, cv2.THRESH_BINARY)[1]
        thresh = cv2.dilate(thresh, None, iterations=2)
        binary, cnts, hierarchy= cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        for c in cnts:
            # 如果检测到的区域小于设置值,则忽略
            if cv2.contourArea(c) < self.minArea:
               continue 
            # 在输出画面上框出识别到的物体
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.rectangle(frame, (x, y), (x + w, y + h), (50, 255, 50), 2)
            self.text = "Occupied"
        # 在输出画面上打当前状态和时间戳信息
        cv2.putText(frame, "Status: {}".format(self.text), (10, 20),
            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
        # 将识别后的图像转换成ROS消息并发布
        self.image_pub.publish(self.bridge.cv2_to_imgmsg(frame, "bgr8"))
    def cleanup(self):
        print "Shutting down vision node."
        cv2.destroyAllWindows()
if __name__ == '__main__':
    try:
        # 初始化ros节点
        rospy.init_node("motion_detector")
        rospy.loginfo("motion_detector node is started...")
        rospy.loginfo("Please subscribe the ROS image.")
        motionDetector()
        rospy.spin()
    except KeyboardInterrupt:
        print "Shutting down motion detector node."
        cv2.destroyAllWindows()

里面代码的意思跟之前的也都差不多。不同点在,这里主要是基于图像差异识别到运动的物体,最后标识,识别并结果发布。

二维码识别

安装以下功能包:

sudo apt-get install ros-kinetic-ar-track-alvar

我们可以在以下目录中找到相应的安装的文件。这个功能包也有很多工具能够帮助我们去创建二维码。

roscore

rosrun ar_track_alvar createMarker

我们可以通过多种方式,像数字、文件、网址等等来创建二维码,还可以去定义我们二维码的大小什么的。接下来我们实现对它的识别:

上述命令分别是创建一个大小为5的数字0,大小为5的数字1,大小为5的数字2。

接下来我们去工作空间下看一下launch文件:

核心部分是node节点,通过启动individualMarkersNoKinect节点去识别二维码。里面加一些参数,像什么二维码的尺寸等。

roslaunch robot_vision usb_cam_with_calibration.launch

roslaunch robot_vision ar_track_camera.launch

rostopic echo /ar_pose_marker查看二维码姿态

我的微信公众号名称:深度学习与先进智能决策

微信公众号ID:MultiAgenxt1024

公众号介绍:主要研究强化学习、计算机视觉、深度学习、机器学习等相关内容,分享学习过程中的学习笔记和心得!期待您的关注,欢迎一起学习交流进步!

相关实践学习
使用ROS创建VPC和VSwitch
本场景主要介绍如何利用阿里云资源编排服务,定义资源编排模板,实现自动化创建阿里云专有网络和交换机。
阿里云资源编排ROS使用教程
资源编排(Resource Orchestration)是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有资源的创建和配置,以达到自动化部署、运维等目的。编排模板同时也是一种标准化的资源和应用交付方式,并且可以随时编辑修改,使基础设施即代码(Infrastructure as Code)成为可能。 产品详情:https://www.aliyun.com/product/ros/
相关文章
|
3月前
|
并行计算 PyTorch TensorFlow
Ubuntu安装笔记(一):安装显卡驱动、cuda/cudnn、Anaconda、Pytorch、Tensorflow、Opencv、Visdom、FFMPEG、卸载一些不必要的预装软件
这篇文章是关于如何在Ubuntu操作系统上安装显卡驱动、CUDA、CUDNN、Anaconda、PyTorch、TensorFlow、OpenCV、FFMPEG以及卸载不必要的预装软件的详细指南。
5346 3
|
3月前
|
Ubuntu 应用服务中间件 nginx
Ubuntu安装笔记(三):ffmpeg(3.2.16)源码编译opencv(3.4.0)
本文是关于Ubuntu系统中使用ffmpeg 3.2.16源码编译OpenCV 3.4.0的安装笔记,包括安装ffmpeg、编译OpenCV、卸载OpenCV以及常见报错处理。
240 2
Ubuntu安装笔记(三):ffmpeg(3.2.16)源码编译opencv(3.4.0)
|
3月前
|
Ubuntu Linux C语言
Ubuntu安装笔记(二):ubuntu18.04编译安装opencv 3.4.0 opencv_contrib3.4.0
本文介绍了在Ubuntu 18.04系统上编译安装OpenCV 3.4.0及其扩展包opencv_contrib 3.4.0的详细步骤,包括下载源码、安装依赖、配置CMake和编译安装,以及常见问题的解决方法。
345 1
Ubuntu安装笔记(二):ubuntu18.04编译安装opencv 3.4.0 opencv_contrib3.4.0
|
3月前
|
PyTorch TensorFlow 算法框架/工具
Jetson环境安装(一):Ubuntu18.04安装pytorch、opencv、onnx、tensorflow、setuptools、pycuda....
本文提供了在Ubuntu 18.04操作系统的NVIDIA Jetson平台上安装深度学习和计算机视觉相关库的详细步骤,包括PyTorch、OpenCV、ONNX、TensorFlow等。
152 1
Jetson环境安装(一):Ubuntu18.04安装pytorch、opencv、onnx、tensorflow、setuptools、pycuda....
|
3月前
|
Ubuntu 编译器 计算机视觉
Ubuntu系统编译OpenCV4.8源码
【10月更文挑战第17天】只要三步即可搞定,第一步是下载指定版本的源码包;第二步是安装OpenCV4.8编译需要的编译器与第三方库支持;第三步就是编译OpenCV源码包生成安装文件并安装。
|
3月前
|
Ubuntu Linux 编译器
Linux/Ubuntu下使用VS Code配置C/C++项目环境调用OpenCV
通过以上步骤,您已经成功在Ubuntu系统下的VS Code中配置了C/C++项目环境,并能够调用OpenCV库进行开发。请确保每一步都按照您的系统实际情况进行适当调整。
696 3
|
3月前
|
Ubuntu 编译器 开发工具
香橙派5Pro+虚拟机Ubuntu18.04交叉编译+Opencv4.7
香橙派5Pro+虚拟机Ubuntu18.04交叉编译+Opencv4.7
|
4月前
|
Ubuntu 网络安全 开发工具
Ubuntu19.04的安装过程详解以及操作系统初始化配置
本文详细介绍了Ubuntu 19.04操作系统的安装过程、初始化配置、网络设置、软件源配置、SSH远程登录以及终端显示设置。
133 1
Ubuntu19.04的安装过程详解以及操作系统初始化配置
|
5月前
|
Ubuntu Shell C++
在Ubuntu18.04上安装ros2的环境,ros2的常用命令:播放包、录制包等
在Ubuntu18.04上安装ros2的环境,ros2的常用命令:播放包、录制包等
236 1
|
5月前
|
Ubuntu 计算机视觉
Ubuntu上的OpenCV
Ubuntu上的OpenCV
41 0

热门文章

最新文章