OpenCV(一)ROS下的OpenCV实现人脸检测

发布时间:2023-09-24 10:00

一、实现目标及效果

利用笔记本电脑上的摄像头,通过ROS和OpenCV,利用Haar Cascade进行人脸检测

参考文档:https://docs.opencv.org/4.5.2/db/d28/tutorial_cascade_classifier.html

\"OpenCV(一)ROS下的OpenCV实现人脸检测_第1张图片\"(不宜露脸)

二、实现过程

1、安装usb_cam

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

2、创建功能包,把xml文件下载到包里
\"OpenCV(一)ROS下的OpenCV实现人脸检测_第2张图片\"
xml是分类器文件,在OpenCV官网上可以下载到,我个人git账号上也有https://github.com/Grizi-ju/robot_vision
3、启动命令

$ roslaunch robot_vision usb_cam.launch
$ roslaunch robot_vision face_detector.launch
$ rqt_image_view

三、代码部分(Python)

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

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

两个launch文件
3、usb_cam.launch
4、face_detector.launch

源码都传到git上了

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号