ROS——机器视觉

目录

一、PC驱动笔记本自带摄像头

           开始摄像头标定

二、Opencv

        人脸识别

        物体跟踪

        二维码识别

三、问题解决

        N: 忽略‘ros-latest.listsudo’(于目录‘/etc/apt/sources.list.d/’),鉴于它的文件扩展名无效

        错误:E: 无法定位软件包 libjasper-dev

        -- IPPICV: Download: ippicv_2020_lnx_intel64_20191018_general.tgz



一、PC驱动笔记本自带摄像头

USB摄像头最为普遍,例如笔记本自带的内置摄像头,在ros中使用这类设备只需要使用usb_cam

功能包驱动即可。

安装命令如下

sudo apt-get install ros-noetic-usb-cam
//ubuntu 20.04
sudo apt-get install ros-kinetic-usb-cam
//ubuntu 18.04

启动驱动测试

roslaunch usb_cam usb_cam-test.launch

 

除此之外,我们的ROS提供的工具箱里依旧为我们提供了一个图像显示工具。 

roscore
//另起终端
rqt_image_view

 这个需要首先使用roslaunch将usb摄像头启动才能使用qt可视化工具查看

 关于图像数据显示

ROS——机器视觉_第1张图片

ROS——机器视觉_第2张图片

ROS——机器视觉_第3张图片

ROS——机器视觉_第4张图片

ROS——机器视觉_第5张图片

 摄像头标定

 1.安装标定功能包

sudo apt-get install ros-noetic-camera-calibration
//Ubuntu20.04
sudo apt-get install ros-kinetic-camera-calibration
//Ubuntu18.04
自己的ros对应版本是啥就对应更改即可
sudo apt-get install ros-xxxxx-camera-calibration

 这里出现了安装包无法被定位的问题,如有出现相同问题请看后续问题解决ROS——机器视觉_第6张图片

开始摄像头标定

 注意开始标定之前我们需要打印一个标定靶

在这里插入图片描述

读者可以复制下来自行打印 

roslaunch usb_cam usb_cam-test.launch
//首先启动摄像头
rosrun camera_calibration cameracalibrator.py --size 8x6 --square 0.024 image:=/usb_cam/image_raw camera:=/usb_cam

 ROS——机器视觉_第7张图片

 ROS——机器视觉_第8张图片

ROS——机器视觉_第9张图片

 然后启动后我们会看到警告

在这里插入图片描述

这个我们可以不用去注意,这是摄像头启动的自矫正文件,目前处于缺失状态

 ROS——机器视觉_第10张图片

在没有标定成功前,右边的按钮都为灰色,不能点击
将标定靶放在摄像头视野内,我们可以看到以上图形界面 

 注意:为了提高标定的准确性
应该尽量让标定把出现在摄像头视野范围内的各个区域,界面右上角的进度条会提示标定进度

 不断在视野中移动标定配,直到CALIBRATE按钮变色,表示标定程序的参数采集完成
最好保证所有的进度条都是绿色满格的,如果实在没办法满格也没关系,大体上满了就行。

然后点击CALBRATE按钮

这个过程满要等待一段时间(几分钟), 界面可能会变成灰色无响应状态(注意无响应最长可达十到二十分钟,期间不要关闭。)
参数计算完成后界面回复,而且终端也会有标定结果的显示

刻度为0.0意味着图像的大小,以便校正图像中的所有像素都是有效的
校正后的图像没有边框,但原始图像中的一些像素被丢弃

刻度为1.0意味着原始图像中的所有像素都是可见的
但是校正后的图像有黑色边框,在原始图像中没有输入像素

文件保存 

ROS——机器视觉_第11张图片

点击save按钮,终端会打印生成文件及路径(目录/tmp下)

('Wrote calibration data to', '/tmp/calibrationdata.tar.gz')

 终端打印出了生成的标定文件的路径

 点击commit按钮,提交数据并退出程序
可以看到提示写入文件head_camera.yaml此时

也就是开始欠缺的,现在重新启动摄像头的话就无上述警告了

然后在计算机目录打开/tmp文件夹,可以看到calibrationdata.tar.gz
解压文件后从中找到ost.yaml文件

将该文件复制放到“cam_info”文件夹下,将文件里面的参数camera_name改为head_camera,然后就可以在相机的launch文件加载该参数文件了

使用标定文件:

ROS——机器视觉_第12张图片


  
    
    
    
    
    
    
    
    
  
  

查看文件内容也就是之前保存的ost.yaml文件,只不过文件里面的参数camera_name改为head_camera

cat /home/q/.ros/camera_info/head_camera.yaml

 ROS——机器视觉_第13张图片

 标定Kinect

这里由于条件有限,没办法进行操作和实现

在此附上链接,有条件的读者可参考阅读

http://t.csdn.cn/3gQKb

二、Opencv 

ROS——机器视觉_第14张图片

 Opencv 安装

sudo apt-get install ros-noetic-vision-opencv libopencv-dev python-opencv
//ubuntu 20.04
sudo apt-get install ros-kinetic-vision-opencv libopencv-dev python-opencv
//ubuntu 18.04

 这里我出现了无法定位软件包的问题,这里只能采用解压opencv压缩包并且编译的最原始办法进行安装

打开浏览器,进入下载地址Release OpenCV 3.4.15 · opencv/opencv · GitHub,选择Source code(zip)进行下载

 下载好后将压缩包放到/home/你的用户名

也就是家目录下

cd ~
unzip opencv-3.4.15.zip
cd opencv-3.4.15
sudo apt-get update 
sudo apt-get install cmake
//安装相关的依赖库
sudo apt install build-essential

sudo apt install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev

 sudo apt install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
//这里出现了错误:E: 无法定位软件包 libjasper-dev的问题

解决方法见后文问题解决 

下一步

cd ~/opencv-3.4.15
mkdir build
cd ./build
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules -D DOPENCV_GENERATE_PKGCONFIG=ON ..

使用make创建编译

cd ./build
sudo make -j4

 ROS——机器视觉_第15张图片

这一步 

需要时间较长,请耐心等待 

编译完成后即可进行安装

sudo make install

 ROS——机器视觉_第16张图片

opencv 环境配置 

sudo gedit /etc/ld.so.conf.d/opencv.conf
//编辑文件内容
 /usr/local/lib

保存后在终端中输入

sudo ldconfig 

 sudo gedit /etc/bash.bashrc
//编辑文件内容,添加
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH

然后另起终端 

source /etc/bash.bashrc
sudo updatedb

 到这里opencv的配置已经结束了,下面验证是否成功配置

pkg-config --modversion opencv

 ROS——机器视觉_第17张图片

 此时已经配置完成。

下面启动仿真实例

roslaunch robot_vision usb_cam.launch
rosrun robot_vision cv_bridge_test.py
rqt_image_view

 中间启动cv_bridge_test.py时会遇见语法问题以及版本不兼容问题

简而言之就是对应安装python依赖包,以及如果是noetic的话应该是python3的版本

#!/usr/bin/env python——————修改为#!/usr/bin/env python3

sudo apt-get install python-yaml // python2
sudo apt-get install python3-yaml //python3

 还有printf语法格式需要改为 printf(........)

noetic版本直接使用我已经修改好的代码即可

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import rospy
import cv2
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image

class image_converter:
    def __init__(self):    
        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):
        try:
            cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
        except CvBridgeError as e:
            print (e)

        (rows,cols,channels) = cv_image.shape
        if cols > 60 and rows > 60 :
            cv2.circle(cv_image, (60, 60), 30, (0,0,255), -1)

        cv2.imshow("Image window", cv_image)
        cv2.waitKey(3)

        try:
            self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))
        except CvBridgeError as e:
            print (e)

if __name__ == '__main__':
    try:
        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()

 结果显示:

人脸识别

如果已经有robot_vision的功能包的话下面可以直接进行仿真演示

roslaunch robot_vision usb_cam.launch
roslaunch robot_vision face_detector.launch
rqt_image_view

 在打开的qt可视化工具中选择

/cv_bridge_image即可 

 如果没有robot_vision里自带的人脸识别项目包,可以自行创建

$ source /opt/ros/noetic/setup.bash
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/src
$ catkin_init_workspace
$ cd ~/catkin_ws
$ catkin_make 
$ souce ~/catkiin_ws/devel/setup.bash
$ cd ~/catkin_ws/src
$ catkin_create_pkg face rospy roscpp std_msgs sensor_msgs cv_bridge image_transport 
$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash

然后进入创建好的功能包中

 

cd ./face
mkdir launch scripts

 

cd face/scripts

touch face_detector.py

 

#!/usr/bin/env python3
# -*- 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 faceDetector:
    def __init__(self):
        rospy.on_shutdown(self.cleanup);


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


        cascade_1 = rospy.get_param("~cascade_1", "")
        cascade_2 = rospy.get_param("~cascade_2", "")


        self.cascade_1 = cv2.CascadeClassifier(cascade_1)
        self.cascade_2 = cv2.CascadeClassifier(cascade_2)


        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)


        self.image_sub = rospy.Subscriber("input_rgb_image", Image, self.image_callback, queue_size=1)

    def image_callback(self, data):

        try:
            cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")     
            frame = np.array(cv_image, dtype=np.uint8)
        except CvBridgeError as e:
            print (e)

    
        grey_image = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    
        grey_image = cv2.equalizeHist(grey_image)

 
        faces_result = self.detect_face(grey_image)


        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)

    
        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()

if __name__ == '__main__':
    try:

        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()

然后编写launch启动文件

cd ~/catkin_ws/src/face
cd ./launch
touch usb_cam.launch face_detector.launch

 usb_cam.launch



  
    
    
    
    
    
    
  

face_detector.launch

 


    
        
        
            haar_scaleFactor: 1.2
            haar_minNeighbors: 2
            haar_minSize: 40
            haar_maxSize: 60
        
        
        
    

 然后启动即可

roslaunch face usb_cam.launch
roslaunch face face_detector.launch
rqt_image_view

 物体跟踪

roslaunch robot_vision usb_cam.launch
roslaunch robot_vision motion_detector.launch
rqt_image_view

 启动发生报错

还是因为python3不兼容问题

见后文详细问题四解决改正即可

ROS——机器视觉_第18张图片

 二维码识别

ros中提供了一个二维码识别的功能包,我们下载安装使用即可简单的了解二维码识别+ros

安装

sudo apt-get install ros_kinetic-ar-track-alvar

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

这里我依旧出现了无法定位功能包的问题。没办法,只能git,git就完了 

git clone https://github.com/machinekoder/ar_track_alvar.git
//第一个连不上用第二个,第二个再连不上就用ssh地址git
实在不行的话如果不是你脸黑,可以用热点再试试
git clone https://gitclone.com/github.com/machinekoder/ar_track_alvar.git

注意移动到 /opt/ros/noetic/share下

其余的请参考具体内容,这里不做过多介绍。

三、问题解决

一、
在使用

roslaunch usb_cam usb_cam-test.launch

启动摄像头驱动的时候出现错误

[ERROR] [1666493852.564127973]: Cannot identify '/dev/video0': 2, No such file or directory
[usb_cam-2] process has died [pid 3480, exit code 1, cmd /opt/ros/noetic/lib/usb_cam/usb_cam_node __name:=usb_cam __log:=/home/q/.ros/log/6fdb5b62-527e-11ed-9564-a522b293e3b4/usb_cam-2.log].
log file: /home/q/.ros/log/6fdb5b62-527e-11ed-9564-a522b293e3b4/usb_cam-2*.log
 

 首先将虚拟机关机,然后打开虚拟机设置,将如图所示位置勾选然后开机。ROS——机器视觉_第19张图片

 开机后选择虚拟机——可移动设备——自己的内置摄像头——连接(与主机断开连接)——系统提示是否与主机断开连接——选择确定——启动摄像头驱动文件。

如果发现摄像头亮起但是马上熄灭,而且报错以下内容

[ERROR] [1666494707.159268534]: select timeout
[usb_cam-2] process has died [pid 2322, exit code 1, cmd /opt/ros/noetic/lib/usb_cam/usb_cam_node __name:=usb_cam __log:=/home/q/.ros/log/6a45bfd8-5280-11ed-befa-8ffa538c4fc6/usb_cam-2.log].
log file: /home/q/.ros/log/6a45bfd8-5280-11ed-befa-8ffa538c4fc6/usb_cam-2*.log
 

则需要将usb兼容性改为usb 3.1 

结果如下所示——成功显示

 关于警告问题。这里可能是由于自动对焦参数未修改,也可能是摄像头不具备自动对焦功能,所以给出警告,这里可以忽略。

ROS——机器视觉_第20张图片

 二、

在进行安装摄像头标定功能包的时候出现了软件包无法被定位的问题

sudo apt-get install ros-noetic-camera-calibrationp

这时候只需要进行

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install ros-noetic-camera-calibrationp

如果还是不行,则需要更改软件源

 ROS——机器视觉_第21张图片

 ROS——机器视觉_第22张图片

 一般情况下使用中科大的软件源就可解决问题。如果还是无法定位到摄像头标定功能包则需要更改其他软件源尝试。

{

问题拓展

我在更换软件源的过程中出现了

N: 忽略‘ros-latest.listsudo’(于目录‘/etc/apt/sources.list.d/’),鉴于它的文件扩展名无效

这样的问题

只需要

su
//此时处于root用户下
cd /etc/apt/sources.list.d
rm -f ros-latest.list
//将对应报错文件执行删除即可,需要注意的是使用sudo进行删除操作的时候会无法删除该文挡,所以还会持续报错

}

错误:E: 无法定位软件包 libjasper-dev

sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
sudo apt update
sudo apt install libjasper1 libjasper-dev

 再进行安装即可

sudo apt install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev

三、 

-- IPPICV: Download: ippicv_2020_lnx_intel64_20191018_general.tgz
 

编译时卡在这动不了

 https://pan.baidu.com/s/1C05qBz-eSAUIxdwljce0kw
//4q33
  1. 修改配置文件
/home/你的用户名/opencv-4.5.0/3rdparty/ippicv

找到

"https://raw.githubusercontent.com/opencv/opencv_3rdparty/${IPPICV_COMMIT}/ippicv/"

将其改为你你保存ippicv_2020_lnx_intel64_20191018_general.tgz文件的路径即可
然后重新Cmake即可

四、

ERROR: cannot launch node of type [robot_vision/face_detector.py]: Cannot locate node of type [face_detector.py] in package [robot_vision]. Make sure file exists in package path and permission is set to executable (chmod +x)

执行人脸识别例程中的错误提示,这里需要更改相应的face_detector.py的可执行权限。确保该文件可执行即可

[face_detector-1] process has died [pid 19759, exit code 1, cmd /home/q/catkin_ws/src/robot_vision/scripts/face_detector.py input_rgb_image:=/usb_cam/image_raw __name:=face_detector __log:=/home/q/.ros/log/73f91038-5330-11ed-a276-75b34a6004f4/face_detector-1.log].
log file: /home/q/.ros/log/73f91038-5330-11ed-a276-75b34a6004f4/face_detector-1*.log
 

这里应该是face_detector.py的语法出现了问题,按照我以下方法进行更改即可。 

     except CvBridgeError,e:
                        ^
SyntaxError: invalid syntax

python3需要改为使用 print   xxx  as   xxx兼容写法。

即except CvBridgeError as e: 

注意文件开头也需要改为

#!/usr/bin/env python3

以下为Ubuntu20.04+python3跑通源码

motion_detector.py

#!/usr/bin/env python3
# -*- 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 as 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()

你可能感兴趣的:(ubuntu,linux,运维,1024程序员节)