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可视化工具查看

 关于图像数据显示

 摄像头标定

 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

 这里出现了安装包无法被定位的问题,如有出现相同问题请看后续问题解决

开始摄像头标定

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

在这里插入图片描述

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

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

 

 

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

在这里插入图片描述

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

 

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

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

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

然后点击CALBRATE按钮

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

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

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

文件保存 

点击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文件加载该参数文件了

使用标定文件:

在这里插入图片描述

<launch>
  <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
    <param name="video_device" value="/dev/video0" />
    <param name="image_width" value="640" />
    <param name="image_height" value="480" />
    <param name="pixel_format" value="yuyv" />
    <param name="camera_frame_id" value="usb_cam" />
    <param name="io_method" value="mmap"/>
    <!--加载标定文件-->
    <param name="camera_info_url" type="string" value="file://$(find ar_pose_adjust)/cam_info/ost.yaml"/>
  </node>
  <!--node name="image_view" pkg="image_view" type="image_view" respawn="false" output="screen">
    <remap from="image" to="/usb_cam/image_raw"/>
    <param name="autosize" value="true" />
  </node-->
</launch>

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

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

 

 标定Kinect

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

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

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

二、Opencv 

 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

 

这一步 

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

编译完成后即可进行安装

sudo make install

 

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

 

 此时已经配置完成。

下面启动仿真实例

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

<launch>

  <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
    <param name="video_device" value="/dev/video0" />
    <param name="image_width" value="640" />
    <param name="image_height" value="480" />
    <param name="pixel_format" value="yuyv" />
    <param name="camera_frame_id" value="usb_cam" />
    <param name="io_method" value="mmap"/>
  </node>

</launch>

face_detector.launch

<launch>
    <node pkg="robot_vision" name="face_detector" type="face_detector.py" output="screen">
        <remap from="input_rgb_image" to="/usb_cam/image_raw" />
        <rosparam>
            haar_scaleFactor: 1.2
            haar_minNeighbors: 2
            haar_minSize: 40
            haar_maxSize: 60
        </rosparam>
        <param name="cascade_1" value="$(find robot_vision)/data/haar_detectors/haarcascade_frontalface_alt.xml" />
        <param name="cascade_2" value="$(find robot_vision)/data/haar_detectors/haarcascade_profileface.xml" />
    </node>
</launch>

 然后启动即可

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中提供了一个二维码识别的功能包,我们下载安装使用即可简单的了解二维码识别+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
 

 首先将虚拟机关机,然后打开虚拟机设置,将如图所示位置勾选然后开机。

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

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

[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 

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

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

 二、

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

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

这时候只需要进行

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

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

 

 

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

{

问题拓展

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

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

  • 12
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值