ROS+opencv 人脸,眼睛,手掌识别程序解读

算是第一次在CSDN上写博客,之前在windows下有onenote神器,然而在ubuntu下真的没有找到比较好的记笔记方法,所以来到CSDN这个圣殿来记录一下学习的印记。学习ROS已经有一个月的时间了,曲曲折折,之前的经历和经验会找时间补上。
接下来进入正题,ros与opencv的用法。
首先要配置好launch文件,代码如下:


<launch>
    <node pkg="robot_vision" name="eyes_detector" type="eyes_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" />
    <param name="cascade_3" value="$(find robot_vision)/data/haar_detectors/haarcascade_eye.xml" />
    <param name="cascade_4" value="$(find robot_vision)/data/haar_detectors/haarcascade_smile.xml" />
    <param name="cascade_5" value="$(find robot_vision)/data/haar_detectors/haarcascade_hand.xml" />
    node>
launch>

launch文件启动节点就不多讲了,eyes_detecor.py是一会要讲的程序,一会再说 ,rosparam是用来配置ros参数的,其中配置的是haar检测的相关参数,在我上篇转载的文章中有讲述到,下面的五个param是调用事先下载好的haarcascade,这个算法是2001年Viola和Jones提出来的基于Haar特征的级联分类器对象检测算法,想更多了解具体算法的话,自行谷歌。这里面是在github上下载的训练好的cascde,俗话理解就是在这些文件里面已经包含了很多人脸,眼睛的特征,只需要和你的脸进行匹配的算法。
接下来贴上节点代码:

#!/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", "")  #侧脸识别导入
        cascade_3 = rospy.get_param("~cascade_3", "")  #眼睛识别导入
        cascade_4 = rospy.get_param("~cascade_4", "")  #微笑识别导入
        cascade_5 = rospy.get_param("~cascade_5", "")  #手掌识别导入
        # 使用级联表初始化haar特征检测器
        self.cascade_1 = cv2.CascadeClassifier(cascade_1)
        self.cascade_2 = cv2.CascadeClassifier(cascade_2)
        self.cascade_3 = cv2.CascadeClassifier(cascade_3)
        self.cascade_4 = cv2.CascadeClassifier(cascade_4)
        self.cascade_5 = cv2.CascadeClassifier(cascade_5)
        # 设置级联表的参数,优化人脸识别,可以在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", 10)
        self.haar_maxSize      = rospy.get_param("~haar_maxSize", 30)
        self.color_green = (50, 255, 50)
        self.color_blue = (0, 0, 255)

        # 初始化订阅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)

        # 尝试检测眼睛,手 

    eye_result = self.detect_eye(grey_image)
    hand_result = self.detect_hand(grey_image)

    #框出眼睛
    if len(eye_result)>0:
        for eye in eye_result:
        ex,ey,ew,eh =eye
        cv2.rectangle(cv_image, (ex, ey), (ex+ew, ey+eh), self.color_green, 2)
    #框出手掌
    if len(hand_result)>0:
        for hand in hand_result:
        hx,hy,hw,hh =hand
        cv2.rectangle(cv_image, (hx, hy), (hx+hw, hy+hh), self.color_blue, 2)

        # 将识别后的图像转换成ROS消息并发布
        self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))

    #检测配置
    def detect_eye(self, input_image):
        eye = self.cascade_3.detectMultiScale(input_image, 
                self.haar_scaleFactor, 
                self.haar_minNeighbors, 
                cv2.CASCADE_SCALE_IMAGE, 
                (self.haar_minSize, self.haar_maxSize))
    return eye

    def detect_hand(self, input_image):
        hand = self.cascade_5.detectMultiScale(input_image, 
                self.haar_scaleFactor, 
                self.haar_minNeighbors, 
                cv2.CASCADE_SCALE_IMAGE, 
                (self.haar_minSize, self.haar_maxSize))
    return hand

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

python相关的知识就不细说了,要是没学过python的小伙伴可以花几个小时看看语法,很快就会入门了。在py程序当中,需要获取haar特征的级联表的XML文件,文件路径在launch 文件中传入,然后使用级联表初始化haar特征检测器;
在回调函数中,首先利用cvbridge(ros和opencv的接口)将usb摄像头发布的图像转换成opencv图像,从而在opencv中进行处理;获取opencv图像后先进行灰度化转换,并进行边缘处理和噪声过滤,创建平衡直方图;然后进行眼睛人脸等检测,在检测配置中将事先设置好的参数进行调入;然后利用检测到的边缘,打印方框,框在检测到的眼睛和人脸上;最后再次利用cvbridge,将opencv图像转换成ros图像,最后可以通过rqt来查看效果。
最后划一下重点:

  • 下载好haarcascade_xxxx.xml文件,放到工作空间的你知道的位置,下载地址给出:https://github.com/opencv/opencv/tree/master/data/haarcascades,这个里面没有haarcascsde_hand,下载网址:https://github.com/JongJuJu/webcam-hand-detect/blob/master/haarcascade_hand.xml
  • launch文件和程序节点中都要导入haarcascade文件
  • 通过cvbridge进行ros图像和opencv图像之间的转换
  • 配置参数可以优化检测效果,参数讲解在上篇文章
  • 我给出的程序是检测眼睛和手掌的,其实其他的都一样,只要加载要检测的haarcascade.xml文件就可以检测了
    附上效果图片:

ROS+opencv 人脸,眼睛,手掌识别程序解读_第1张图片
ROS+opencv 人脸,眼睛,手掌识别程序解读_第2张图片
ROS+opencv 人脸,眼睛,手掌识别程序解读_第3张图片
ROS+opencv 人脸,眼睛,手掌识别程序解读_第4张图片

第一次写,可能缩进相关的不好看,也没太组织好语言,之后会继续学习,继续完善。

怕什么真理无穷,进一步有进一步的喜悦。

你可能感兴趣的:(ros)