目录
一、PC驱动笔记本自带摄像头
开始摄像头标定
二、Opencv
人脸识别
物体跟踪
二维码识别
三、问题解决
N: 忽略‘ros-latest.listsudo’(于目录‘/etc/apt/sources.list.d/’),鉴于它的文件扩展名无效
错误:E: 无法定位软件包 libjasper-dev
-- IPPICV: Download: ippicv_2020_lnx_intel64_20191018_general.tgz
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文件加载该参数文件了
使用标定文件:
查看文件内容也就是之前保存的ost.yaml
文件,只不过文件里面的参数camera_name
改为head_camera
cat /home/q/.ros/camera_info/head_camera.yaml
标定Kinect
这里由于条件有限,没办法进行操作和实现
在此附上链接,有条件的读者可参考阅读
http://t.csdn.cn/3gQKb
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
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中提供了一个二维码识别的功能包,我们下载安装使用即可简单的了解二维码识别+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
/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()