【Linux學習】OpenCV+ROS 實現人臉識別(Ubantu16.04)

哈哈哈hh發表於2022-07-08

映象下載、域名解析、時間同步  阿里雲開源映象站

前言

本文主要學習 ROS機器人作業系統 ,在ROS系統裡呼叫 OpenCV庫 實現人臉識別任務

一、環境配置

1.安裝ROS

sudo apt-get install ros-kinetic-desktop-full

2.攝像頭呼叫

安裝攝像頭元件相關的包,命令列如下:

sudo apt-get install ros-kinetic-usb-cam

啟動攝像頭,命令列如下:

roslaunch usb_cam usb_cam-test.launch

呼叫攝像頭成功,如下圖所示:

file

攝像頭的驅動釋出的相關資料,如下圖所示:

file

攝像頭 usb_cam/image_raw 這個話題,釋出的訊息的具體型別,如下圖所示:

file

那麼影像訊息裡面的成員變數有哪些呢?

列印一下就知道了!一個訊息型別裡面的具體成員變數,如下圖所示:

file

  • Header:很多話題訊息裡面都包含的

    訊息頭:包含訊息序號,時間戳和繫結座標系

    訊息的序號:表示我們這個訊息釋出是排第幾位的,並不需要我們手動去標定,每次

    釋出訊息的時候會自動地去累加

    繫結座標系:表示的是我們是針對哪一個座標系去釋出的header有時候也不需要去配置

  • height:影像的縱向解析度

  • width:影像的橫向解析度

  • encoding:影像的編碼格式,包含RGB、YUV等常用格式,都是原始影像的編碼格式,不涉及影像壓縮編碼

  • is_bigendian: 影像資料的大小端儲存模式

  • step:一行影像資料的位元組數量,作為資料的步長引數

  • data:儲存影像資料的陣列,大小為step×height個位元組

  • format:影像的壓縮編碼格式(jpeg、png、bmp)

3.匯入OpenCV

file

在ROS當中完成OpenCV的安裝,命令列如下圖所示:

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

安裝完成

file

二、建立工作空間和功能包

1.建立工作空間

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
  • 建立完成工作空間後,在根目錄下面,執行編譯整個工作空間
cd ~/catkin_ws/
catkin_make
  • 工作空間中會自動生成兩個資料夾:devel,build

  • devel資料夾中產生幾個setup.*sh形成的環境變數設定指令碼,使用source命令執行這些指令碼檔案,則工作空間中的環境變數得以生效

source devel/setup.sh
  • 將環境變數設定到/.bashrc檔案中
gedit ~/.bashrc
  • 在開啟的檔案,最下面貼上以下程式碼即可設定環境變數
source ~/catkin_ws/devel/setup.bash

2.建立功能包

開始建立

cd ~/catkin_ws/src
catkin_create_pkg learning std_msgs rospy roscpp

回到根目錄,編譯並設定環境變數

cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.sh

三、人臉識別檢測相關程式碼

基於 Haar 特徵的級聯分類器檢測演算法

核心內容,如下所示:

  • 灰階色彩轉換
  • 縮小攝像頭影像
  • 直方圖均衡化
  • 檢測人臉

1.python檔案

face_detector.py

#!/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 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()
 
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()

2.lanuch

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="test2" 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>

3.CvBridge

  • ROS 與 OpenCV 之間的資料連線是透過 CvBridge 來實現的
  • ROS Image Message與 OpenCV Ipllmage 之間連線的一個橋樑

cv_bridge_test.py

#!/usr/bin/env python
# -*- 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):    
        # 建立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
 
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()

四、程式碼實測

1.執行命令列

分別在三個終端下執行,命令列如下:

啟動攝像頭

roslaunch robot_vision usb_cam.launch

啟動人臉識別

roslaunch robot_vision face_detector.launch

開啟人臉識別視窗

rqt_image_view

2.人臉識別效果

拿了C站官方送的書來進行測試,識別的效果還是相當不錯的,效果如下圖所示:

file

五、報錯解決

報錯1:E:無法定位軟體包 ros-kinetic-usb-cam

file

解決方法: 網上下載編譯安裝

$ cd catkin_ws/src

$ git clone 

$ cd ~/catkin_ws

$ catkin_make

成功解決:

file

報錯2:啟動攝像頭報錯

file

file決方法:輸入以下命令列,再啟動攝像頭

source ~/catkin_ws/devel/setup.bash

成功解決:

file

報錯3:虛擬機器攝像頭沒連線報錯

file

解決方法:開啟虛擬機器設定,更改usb版本為3.1

file

可移動裝置將攝像頭設定連線

file

六、總結

  • 在ROS作業系統中呼叫 OpenCV 完成人臉識別還是比較有意思的,目前影像處理和人臉識別還是比較常用到的,本文主要記錄學習過程,以及遇到的相關報錯問題進行記錄

  • 如何對於特定目標的檢測並顯示出結果?如何最佳化讓人臉識別的更精準?目前還在朝著這個方向進行思考和探究


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70003733/viewspace-2904820/,如需轉載,請註明出處,否則將追究法律責任。

相關文章