1. 程式人生 > >ubuntu16.04下ROS作業系統學習(七 / 二)機器視覺-人臉識別

ubuntu16.04下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裡面建立灰度影象,建立平衡直方圖,減少光線影響,之後檢測人臉,這些操作都是通過呼叫函式來實現的,然後將人臉用一個方框框出來。