感知笔记3:平面和物体检测

news2024/9/20 23:44:25
  • 识别平面表面:这项技能使机器人能够检测物体通常所在的位置,如桌子和架子。这是搜索物体的第一步。
  • 识别物体:一旦您知道在哪里寻找,就必须在场景中识别不同的物体,并根据机器人的位置(坐标系)定位它们。

3.1 环境介绍

您将使用以下环境:

  • PR2 机器人:它是一种多功能机器人,可以全向移动,有两只手臂和一个可移动的躯干。它还配有激光器和点云相机。它是物体识别和操控的完美候选者。
  • 桌子上的物体选择:您会在桌子上找到几个物体。它们是为了在检测中提供多样性。物体中有一把枪,因为我们想解释如何检测有武装人员的危险情况。

您可以使用以下列出的键盘遥控和关节命令移动PR2机器人。

roslaunch pr2_tc_teleop keyboard_teleop.launch

使用Q键将速度增加到大约8.0,以查看PR2机器人移动。

点击图形界面图标,打开图形工具,通过简单的GUI移动PR2机器人的关节:

您应该看到与下图类似的图像:

选择 head_joint_controller 以移动头部的俯仰和倾斜。这将有助于检查您的物体检测是否正常工作。

3.2 平面检测器

识别物体的第一步是知道这些物体的位置。您将使用 surface_perception 包来检测平面并在RViz中表示检测结果。surface_perception 包还可以检测平面上的物体。这是一个优秀的ROS包,制作精良,考虑到它自ROS-indigo以来就没有更新过,并且它在ROS-Noetic中工作。

第一步是创建一个对象识别包:

cd /home/user/catkin_ws/src
catkin_create_pkg my_object_recognition_pkg rospy
cd my_object_recognition
mkdir launch
touch launch/surface_detection.launch
cd /home/user/catkin_ws
catkin_make
source devel/setup.bash
rospack profile
surface_detection.launch
<?xml version="1.0"?>
<launch>
    <node name="surface_perception_node" pkg="surface_perception" type="demo" output="screen" args="base_link">
        <remap from="cloud_in" to="/camera/depth_registered/points"/>
    </node>
</launch>

此二进制文件需要两个元素才能工作:

  • 输入我们将以此为基础进行检测的 Tf 坐标框架。在这种情况下,base_link 就足够了。
  • cloud_in 重新映射到您的机器人从深度传感器发布点云的主题。在我们的例子中,这是 /camera/depth_registered/points

让我们启动表面检测包并看看会发生什么:

roslaunch my_object_recognition_pkg surface_detection.launch

您现在应该看到类似下图的图像:

 如果您没有看到标记,请确保在 RViz 面板中看到指向主题 /surface_objects 的元素类型标记:

您可以看到,仅使用此系统,您就可以获得:

  • 标记代表您的机器人检测到的不同水平表面。它们以紫色标记表示。
  • 标记代表检测到的物体。它们以绿色标记表示。

练习 3.2.1

  • 创建一个名为surface_data_extraction.py的Python脚本,该脚本提取由surface_detection.launch生成的标记数据,并仅过滤与桌子高度相对应的水平表面物体。
  • 桌子高度约为0.8米,因此您应该过滤该高度周围的表面物体。
  • 您可以将表面与物体区分开来,因为它们的名称是surface_X,而物体是surface_X_object_Y_axes

稍后,可以使用这些数据仅在该空间区域周围查找物体并用于抓取。

请记住使Python脚本可执行;否则,ROS将无法执行它:

chmod +x surface_data_extraction.py
my_object_recognition_pkg/scripts/surface_data_extraction.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import rospy
import numpy

from visualization_msgs.msg import Marker

class SurfaceObjectFilter:

   def __init__(self, table_height_init=0.8, error_height=0.2):

      self._rate = rospy.Rate(5)

      self.table_height = table_height_init
      self._error_height = error_height
      self.surface_dict = {}
      self.surface_topic = "/surface_objects"
      self._check_surface_ready()
      rospy.Subscriber(self.surface_topic, Marker, self.surface_callback)
     
      rospy.loginfo('Ready to detect Surfaces!')

   def _check_surface_ready(self):
      self._surface_data = None
      while self._surface_data is None and not rospy.is_shutdown():
         try:
               self._surface_data = rospy.wait_for_message(self.surface_topic, Marker, timeout=1.0)
               rospy.logdebug("Current "+self.surface_topic+" READY=>" + str(self._surface_data))

         except:
               rospy.logerr("Current "+self.surface_topic+" not ready yet, retrying.")

   def update_table_height(self,new_table_height):
      self.table_height = new_table_height

   def look_for_table_surface(self, z_value):
      """

      """
      delta_min = z_value - self._error_height
      delta_max = z_value + self._error_height
      is_the_table = delta_min < self.table_height < delta_max

      return is_the_table

   def surface_callback(self, msg):

      name = msg.ns
      surface_pose = msg.pose

      if "surface_" in name and not "_axes" in name:
         # We check the heigh in z to see if its the table
         if self.look_for_table_surface(msg.pose.position.z):
            if name in self.surface_dict:
               rospy.loginfo("This surface was alreday found")
            else:
               self.surface_dict[name] = surface_pose
               rospy.loginfo("Found New Surface=")
      else:
         rospy.logdebug("Surface Object Not found "+str(name))


   def get_surface_dict_detected(self):
      return self.surface_dict

   def run(self):


      while not rospy.is_shutdown():
         table_surfaces_detected = self.get_surface_dict_detected()
         rospy.loginfo(str(table_surfaces_detected))
         self._rate.sleep()



if __name__ == '__main__':
   rospy.init_node('surface_data_extract_node', log_level=rospy.INFO)

   try:
      SurfaceObjectFilter().run()
   except KeyboardInterrupt:
      rospy.loginfo('Shutting down')
   def update_table_height(self,new_table_height):
      self.table_height = new_table_height
    
    
    ...
    
    def look_for_table_surface(self, z_value):
      """

      """
      delta_min = z_value - self._error_height
      delta_max = z_value + self._error_height
      is_the_table = delta_min < self.table_height < delta_max

      return is_the_table

我们如何检查一个检测是否是桌子。我们在 self.table_height 中设置了一个特定的高度值,通过 update_table_height 更新,然后确认通过 look_for_table_surface 得到的 z_value 大致等于更新后的高度。

通过同时启动表面检测和 surface_data_extraction.py,您应该只获得桌子的检测结果。

cd /home/user/catkin_ws
source devel/setup.bash
rospack profile
# Now launch
roslaunch my_object_recognition_pkg surface_detection.launch
cd /home/user/catkin_ws
source devel/setup.bash
rospack profile
# Now launch
rosrun my_object_recognition_pkg surface_data_extraction.py

当系统检测到给定高度周围的表面时,您应该得到类似于以下输出的输出:

[INFO] [1615891002.402422, 276.540000]: {'surface_1': position:
  x: 1.5979965925216675
  y: 1.1848139762878418
  z: 0.9700260162353516
orientation:
  x: 0.0
  y: 0.0
  z: 0.008941666223108768
  w: 0.9999600648880005}

3.3 物体检测:扩展物体检测

MoscowskyAnton 创建了这个扩展物体检测系统。该包试图将所有基本的物体和人类识别算法整合到一个统一、全面的结构中,以支持嵌套检测。

它有出色的文档,您可以在Wiki上查看。

您可以做的事情包括:

  • 检测斑点
  • 使用 Haar 特征级联
  • 使用 TensorFlow
  • QR 码跟踪
  • 特征匹配
  • 基本运动检测
  • 还有更多。在这一单元中,我们提供了多个示例,并解释如何将它们组合以创建您自己的检测器。

物体检测:简单/复杂物体检测

该系统的主要思想是使用 .xml 文件来定义您将用于检测物体的不同属性。然后,您将这些属性组合起来以检测特定的简单物体。让我们看看在这一单元中将使用的示例:

roscd my_object_recognition_pkg
mkdir -p config/object_base_example
roscd my_object_recognition_pkg/config/object_base_example
touch Simple_Gun.xml
Simple_Gun.xml
<?xml version="1.0" ?>

<AttributeLib>
    <Attribute Name="HistColorPortalGun" Type="HistColor" Histogram="histograms/PortalGun.yaml"/>
    <Attribute Name="PotalGunSize" Type="Size" MinAreaPc="0.00" MaxAreaPc="100"/>
    <Attribute Name="NotFractal" Type="Size" MinAreaPc="0.5" MaxAreaPc="100"/>
    
    <Attribute Name="HSVColorBlackGun" Type="HSVColor" Hmin="0" Hmax="0" Smin="0" Smax="0" Vmin="31" Vmax="161"/>
    <Attribute Name="HaarGun" Type="HaarCascade" Cascade="gun_haar/classifier/cascade.xml"/>
    <Attribute Name="MyBlobAttribute" Type="Blob" minThreshold="54" maxThreshold="125" blobColor="0" minArea="1500" minCircularity="0.03" minConvexity="0.64" minInertiaRatio="0.00"/>

</AttributeLib>

<SimpleObjectBase>  
      
    <SimpleObject Name="PortalGun" ID="1">              
        <Attribute Type="Detect">HistColorPortalGun</Attribute>  
        <Attribute Type="Check">PotalGunSize</Attribute>  
        <Attribute Type="Check">NotFractal</Attribute> 
    </SimpleObject>    

    <SimpleObject Name="BlackGun" ID="2">              
        <Attribute Type="Detect">HSVColorBlackGun</Attribute> 
        <Attribute Type="Check">NotFractal</Attribute>
    </SimpleObject>

    <SimpleObject Name="HaarBlackGun" ID="3" Mode="Hard" MergingPolicy="Union">              
        <Attribute Type="Detect">HaarGun</Attribute>
        <Attribute Type="Detect">MyBlobAttribute</Attribute> 
    </SimpleObject>  

</SimpleObjectBase>


<RelationLib>    

    
    
</RelationLib>


<ComplexObjectBase>
    
    
</ComplexObjectBase>

这些 XML 文件有三个主要部分:

  • Attributes:在这里,我们定义每个检测器。在这个例子中,我们定义:
    • HistColorPortalGun:我们使用颜色直方图(我们将学习如何生成)来追踪特定的颜色轮廓(类似于斑点)。
    • PortalGunSize:类型为大小检查,物体的面积大于(MinAreaPc 图像面积)且小于(MaxAreaPc 图像面积)。
    • NotFractal:这是为了避免检测到非常小或非常大的斑点。
    • HSVColorBlackGun:在这里,我们不是通过直方图,而是通过基本颜色进行检测。
    • HaarGun:我们通过 Haar 特征级联进行检测,在这种情况下,检测枪的形态是通过 HaarGunGit 完成的。
    • MyBlobAttribute:这是一个黑白斑点检测器。有关斑点检测器的更多信息,请参见 BlobDocs。
  • Simple objects:在这里,我们定义我们想要检测的主要物体,使用哪些属性,以及如何将它们组合。这是通过模式(hard, soft)来完成的。基本上是设置 AND 或 OR 条件,如果某个属性检测到东西。还有合并策略 DOCS。这定义了属性的边界框是否合并为最大的边界框、所有框的联合,或任何其他组合。
  • Relation.lib and complex objects:这两个标签是一起使用的,因为它们定义了复杂物体的检测和构建方式。复杂物体不超过两个或更多简单物体的组合,并具有某种空间关系,例如检测一个物体在另一个物体内部或相邻特定距离。在这种情况下,我们没有定义任何。

简单物体:Portal Gun

我们使用 HistColorPortalGunNotFractal。它的工作原理是,HistColorPortalGun 设置为检测类型;因此,我们将图像数据输入给它。如果它检测到某物,我们就通过 NotFractal 检查。如果没有发现任何分形,则检测有效。否则,就是无效的。

在下一部分中,我们将看到如何生成所有这些,但这里有一个例子,展示我们将使用颜色直方图生成的两个物体。您会看到,这作为物体的指纹非常有用。正如您所见,这两个物体具有非常独特的直方图,这使得它们的检测变得容易得多。

这些图是每个对象的颜色直方图。请注意,这是对象最具标志性的区域的直方图。如果我们要为整个对象创建图像的直方图,它们将非常相似,因为白色在两个图像中占主导地位。这些是输入到直方图生成器的图像:

创建直方图
我们将使用您可以在扩展对象检测包中找到的工具。

roscd my_object_recognition_pkg/config/object_base_example
mkdir histograms
# And now we create histogram generator launch:
roscd my_object_recognition_pkg
touch launch/hist_color_params_collector_point.launch

hist_color_params_collector_point.launch

<launch>
    <arg name="output" value="screen"/>
    <arg name="hist_name" default="PortalGun"/>
    <arg name="hist_path" default="$(find my_object_recognition_pkg)/config/object_base_example/histograms/$(arg hist_name).yaml"/>
      
    <node name="hist_color_params_collector_point_node" pkg="extended_object_detection" type="hist_color_params_collector_point_node" output="screen" required="true">        
        <param name="out_filename" value="$(arg hist_path)"/>
        <remap from="image_raw" to="/camera/rgb/image_raw"/>                
    </node>
          
    
</launch>

这些是您必须根据机器人和物体更改的变量:

  • hist_name:您将生成的直方图文件的名称。
  • hist_path:您希望程序保存直方图文件的位置。
  • /camera/rgb/image_raw:这是 RGB 相机图像主题。根据您的机器人,这可能会改变。

现在让我们启动它并生成传送枪的直方图文件。

首先,使用 PR2 机器人尽可能靠近桌子和物体。使用键盘命令,将机器人移近桌子并降低机器人的头部以更好地查看物体。

要让它移动,线速度必须至少为 10.0。所以如果它不动,不要惊慌。只需按 Q 直到线速度达到 10.0 左右即可

roslaunch pr2_tc_teleop keyboard_teleop.launch

左键单击对象上最具代表性的颜色。在本例中,我们单击的是灰色支架。

看到它生成了有意义的轮廓后,无需移动相机,右键单击图像。这将修复值并开始根据直方图值进行检测。当它变成绿色时,您就知道它起作用了,类似于下面的图片:

别担心大小或 thesh 值。它们在这里不使用。

如果一切顺利,当您在图形工具中按下 ESC 键时,选择 histogram point creator GUI 窗口,它应该会生成 PortalGun.yaml 文件并输出这两行。

这里告诉您在 SimpleObject.xml 文件中作为属性放置的内容,用于通过直方图检测 PortalGun。

<Attribute Name="MyHistColorAttribute" Type="HistColor" Histogram="/home/user/catkin_ws/src/perception_course_solutions/perception_unit3_solutions/my_object_recognition_pkg/config/object_base_example/histograms/PortalGun.yaml"/>
<Attribute Name="MySizeAttribute" Type="Size" MinAreaPc="0.00" MaxAreaPc="100"/>

现在,让我们使用 Simple_Gun.xml 文件来测试它是否有效。

我们需要检查 Simple_Gun.xml 中是否设置了 PortalGun Histogram 的正确路径。路径可以是:

  • 相对路径:相对于您保存 Simple_Gun.xml 的路径。因此,在这种情况下为 histograms/PortalGun.yaml
  • 绝对路径:/home/user/catkin_ws/src/my_object_recognition_pkg/config/object_base_example/histograms/PortalGun.yaml

相对路径通常看起来更简洁,所以我们使用相对路径。

我们还将把属性的名称更改为 HistColorPortalGun

并且我们还将把大小属性的名称更改为 PortalGunSize

最终的内容应类似于以下示例:

Simple_Gun.xml
<?xml version="1.0" ?>

<AttributeLib>
    <Attribute Name="HistColorPortalGun" Type="HistColor" Histogram="histograms/PortalGun.yaml"/>
    <Attribute Name="PotalGunSize" Type="Size" MinAreaPc="0.00" MaxAreaPc="100"/>
    <Attribute Name="NotFractal" Type="Size" MinAreaPc="0.5" MaxAreaPc="100"/>
    
    <Attribute Name="HSVColorBlackGun" Type="HSVColor" Hmin="0" Hmax="0" Smin="0" Smax="0" Vmin="31" Vmax="161"/>
    <Attribute Name="HaarGun" Type="HaarCascade" Cascade="gun_haar/classifier/cascade.xml"/>
    <Attribute Name="MyBlobAttribute" Type="Blob" minThreshold="54" maxThreshold="125" blobColor="0" minArea="1500" minCircularity="0.03" minConvexity="0.64" minInertiaRatio="0.00"/>

</AttributeLib>

<SimpleObjectBase>  
      
    <SimpleObject Name="PortalGun" ID="1">              
        <Attribute Type="Detect">HistColorPortalGun</Attribute>  
        <Attribute Type="Check">PotalGunSize</Attribute>  
        <Attribute Type="Check">NotFractal</Attribute> 
    </SimpleObject>    

    <SimpleObject Name="BlackGun" ID="2">              
        <Attribute Type="Detect">HSVColorBlackGun</Attribute> 
        <Attribute Type="Check">NotFractal</Attribute>
    </SimpleObject>

    <SimpleObject Name="HaarBlackGun" ID="3" Mode="Hard" MergingPolicy="Union">              
        <Attribute Type="Detect">HaarGun</Attribute>
        <Attribute Type="Detect">MyBlobAttribute</Attribute> 
    </SimpleObject>  

</SimpleObjectBase>


<RelationLib>    

    
    
</RelationLib>


<ComplexObjectBase>
    
    
</ComplexObjectBase>

我们创建启动器来使用 Simple_Gun.xml

roscd my_object_recognition_pkg
touch launch/gun_detection.launch

gun_detection.launch

<launch>
    <arg name="output" default="screen"/>
    <arg name="objectBasePath" default="$(find my_object_recognition_pkg)/config/object_base_example/Simple_Gun.xml"/>
    
    <node name="extended_object_detection" pkg="extended_object_detection" type="extended_object_detection_node" output="screen">
        
        <param name="objectBasePath" value="$(arg objectBasePath)"/>
        <param name="videoProcessUpdateRate" value="5"/>
        <param name="screenOutput" value="false"/>
        <param name="publishImage" value="true"/>
        <param name="publishMarkers" value="true"/>
        <param name="subscribeDepth" value="false"/>        
        <param name="maxContourPoints" value="-1"/>        
        
        <rosparam param="selectedOnStartSimple">[1]</rosparam>
        <rosparam param="selectedOnStartComplex">[-1]</rosparam>
        
    </node>        
    
</launch>

对 gun_detection-launch 文件中几个值得注意的元素的注释:

<arg name="objectBasePath" default="$(find my_object_recognition_pkg)/config/object_base_example/Simple_Gun.xml"/>

这里我们指出了 Simple_Gun.xml 文件,我们将在其中定义所有简单对象和属性。

<rosparam param="selectedOnStartSimple">[1]</rosparam>
<rosparam param="selectedOnStartComplex">[-1]</rosparam>

在这里,我们设置了将在检测中激活和搜索的简单物体和复杂物体。

  • []:如果数组中没有放置任何内容,则所有简单或复杂物体将被激活。
  • [1,4,...,25]:每个数字表示简单或复杂物体的 ID。例如,如果我们只放置 [1],这意味着只有 ID=1 的简单物体会被激活,此时是 PortalGun。[-1]:表示不会激活任何物体。

启动它并查看 RViz:

roslaunch my_object_recognition_pkg gun_detection.launch

点击图形界面图标以查看直方图 GUI 生成器。如果您的 RViz 界面与所示的不一样,您可以在本单元的解决方案中查看 RViz 配置文件,路径为 my_object_recognition_pkg/rviz/object_recognition.rviz

练习 3.3.1

  • 根据我们用于 PortalGun 的相同步骤,为香蕉创建直方图检测器。
  • 将修改添加到 Simple_Gun.xml 和 gun_detector.launch 以检测香蕉和 PortalGun。
  • 注意:由于香蕉的形状,您可能需要删除分形属性。

Simple_Gun.xml
<?xml version="1.0" ?>

<AttributeLib>
    <Attribute Name="HistColorPortalGun" Type="HistColor" Histogram="histograms/PortalGun.yaml"/>
    <Attribute Name="PotalGunSize" Type="Size" MinAreaPc="0.00" MaxAreaPc="100"/>
    <Attribute Name="NotFractal" Type="Size" MinAreaPc="0.5" MaxAreaPc="100"/>

    <Attribute Name="HistColorBanana" Type="HistColor" Histogram="histograms/Banana.yaml"/>
    <Attribute Name="BananaSize" Type="Size" MinAreaPc="0.05" MaxAreaPc="100"/>
    
    <Attribute Name="HSVColorBlackGun" Type="HSVColor" Hmin="0" Hmax="0" Smin="0" Smax="0" Vmin="22" Vmax="61"/>
    
    <Attribute Name="HaarGun" Type="HaarCascade" Cascade="gun_haar/classifier/cascade.xml"/>
    <Attribute Name="MyBlobAttribute" Type="Blob" minThreshold="54" maxThreshold="125" blobColor="0" minArea="1500" minCircularity="0.03" minConvexity="0.64" minInertiaRatio="0.00"/>

</AttributeLib>

<SimpleObjectBase>  
      
    <SimpleObject Name="PortalGun" ID="1">              
        <Attribute Type="Detect">HistColorPortalGun</Attribute>  
        <Attribute Type="Check">PotalGunSize</Attribute>  
        <Attribute Type="Check">NotFractal</Attribute> 
    </SimpleObject>

    <SimpleObject Name="Banana" ID="2">              
        <Attribute Type="Detect">HistColorBanana</Attribute>  
        <Attribute Type="Check">BananaSize</Attribute>  
         
    </SimpleObject>    

    <SimpleObject Name="BlackGun" ID="3">              
        <Attribute Type="Detect">HSVColorBlackGun</Attribute> 
        <Attribute Type="Check">NotFractal</Attribute>
    </SimpleObject>

    <SimpleObject Name="HaarBlackGun" ID="4" Mode="Hard" MergingPolicy="Union">              
        <Attribute Type="Detect">HaarGun</Attribute>
        <Attribute Type="Detect">MyBlobAttribute</Attribute> 
    </SimpleObject>  

</SimpleObjectBase>


<RelationLib>    

    
    
</RelationLib>


<ComplexObjectBase>

gun_detection.launch

<launch>
    <arg name="output" default="screen"/>
    <arg name="objectBasePath" default="$(find my_object_recognition_pkg)/config/object_base_example/Simple_Gun.xml"/>
    
    <node name="extended_object_detection" pkg="extended_object_detection" type="extended_object_detection_node" output="screen">
        
        <param name="objectBasePath" value="$(arg objectBasePath)"/>
        <param name="videoProcessUpdateRate" value="5"/>
        <param name="screenOutput" value="false"/>
        <param name="publishImage" value="true"/>
        <param name="publishMarkers" value="true"/>
        <param name="subscribeDepth" value="false"/>        
        <param name="maxContourPoints" value="-1"/>        
        
        <rosparam param="selectedOnStartSimple">[1,2]</rosparam>
        <rosparam param="selectedOnStartComplex">[-1]</rosparam>
        
    </node>        
    
</launch>

一些解决方案的注意事项:

  • 如您所见,NotFractal 属性未被使用。这是因为在香蕉上用直方图检测到的部分太小,因而被视为分形,无法检测。
  • 但是,如果您移除分形属性,您将获得过多的检测结果。这是因为每个与直方图对应的小区域都被视为一个检测。因此,我们必须调整大小。
  • 将最小大小设置为 MinAreaPc=0.05 后,我们只考虑大于该值的有效检测区域,从而清理检测结果,只保留一到两个。
  • 以下是带有分形属性的结果:

  • 请参见以下未调整分形和尺寸的结果:

# This variable set is because of current Accademy system being remote. Localy you wouldn't need to do it.
QT_X11_NO_MITSHM=1
echo $QT_X11_NO_MITSHM
roslaunch my_object_recognition_pkg hist_color_params_collector_point_banana.launch
roslaunch my_object_recognition_pkg gun_detection.launch

简单对象:黑色枪
它的工作原理与上一个练习相同,但使用 HSVColorBlackGun 属性。

创建 HSV 检测

我们将使用您可以在扩展对象检测包中找到的工具。

# We create a HSV sampler launch:
roscd my_object_recognition_pkg
touch launch/hsv_color_params_collector.launch

hsv_color_params_collector.launch

<launch>
    <arg name="output" value="screen"/>
    
    <node name="hsv_color_params_collector_node" pkg="extended_object_detection" type="hsv_color_params_collector_node" output="screen" required="true" >                
        <remap from="image_raw" to="/camera/rgb/image_raw"/>                 
    </node>
          
    
</launch>

启动launch文件获取HSV的值:

# This variable set is because of current Accademy system being remote. Localy you wouldn't need to do it.
QT_X11_NO_MITSHM=1
echo $QT_X11_NO_MITSHM
roslaunch my_object_recognition_pkg hsv_color_params_collector.launch

如您所见,如果我们仅调整 HSV 值,它将检测到所有具有黑色枪的点。不仅在枪中,而且在瓶子或甜甜圈的阴影中。

为了初步了解 HSV 的值,我们建议您使用基于 Web 的颜色选择器,例如 ColorZilla 或任何允许您获取图像的 HSV 值的浏览器插件,然后选择此笔记本中显示枪的图像(例如,上面几行)。

再次,我们将使用 size 属性来检测明显较大的区域以避免这种情况。

但这并不能解决巨大的暗区(如桌子的侧面)也会被检测为枪的问题。为了解决这个问题,我们还必须限制最大尺寸。但这必须在 Simple_Gun.xml 属性定义中完成。

一旦您获得了满意的值,请在 GUI 处于焦点状态时按下键盘上的 ESC 键,启动将终止,并输出您需要添加到 Simple_Gun.xml 的属性,以使用 HSV 检测枪。

[ WARN] [1615908901.726154378, 4258.786000000]: YOUR ATTRIBUTES
<Attribute Name="MyHSVColorAttribute" Type="HSVColor" Hmin="0" Hmax="0" Smin="0" Smax="0" Vmin="22" Vmax="61"/>
<Attribute Name="MySizeAttribute" Type="Size" MinAreaPc="0.01" MaxAreaPc="100"/>
Simple_Gun.xml

我们更改了 BlackGunSizeAttribute 中的 MaxAreaPc=20 以避免检测桌子的侧面。

<?xml version="1.0" ?>

<AttributeLib>
    <Attribute Name="HistColorPortalGun" Type="HistColor" Histogram="histograms/PortalGun.yaml"/>
    <Attribute Name="PotalGunSize" Type="Size" MinAreaPc="0.00" MaxAreaPc="100"/>
    <Attribute Name="NotFractal" Type="Size" MinAreaPc="0.5" MaxAreaPc="100"/>

    <Attribute Name="HistColorBanana" Type="HistColor" Histogram="histograms/Banana.yaml"/>
    <Attribute Name="BananaSize" Type="Size" MinAreaPc="0.05" MaxAreaPc="100"/>


    <Attribute Name="HSVColorBlackGun" Type="HSVColor" Hmin="0" Hmax="0" Smin="0" Smax="0" Vmin="22" Vmax="61"/>
    <Attribute Name="BlackGunSizeAttribute" Type="Size" MinAreaPc="0.01" MaxAreaPc="20"/>
    
    <Attribute Name="HaarGun" Type="HaarCascade" Cascade="gun_haar/classifier/cascade.xml"/>
    <Attribute Name="MyBlobAttribute" Type="Blob" minThreshold="54" maxThreshold="125" blobColor="0" minArea="1500" minCircularity="0.03" minConvexity="0.64" minInertiaRatio="0.00"/>

</AttributeLib>

<SimpleObjectBase>  
      
    <SimpleObject Name="PortalGun" ID="1">              
        <Attribute Type="Detect">HistColorPortalGun</Attribute>  
        <Attribute Type="Check">PotalGunSize</Attribute>  
        <Attribute Type="Check">NotFractal</Attribute> 
    </SimpleObject>

    <SimpleObject Name="Banana" ID="2">              
        <Attribute Type="Detect">HistColorBanana</Attribute>  
        <Attribute Type="Check">BananaSize</Attribute>  
         
    </SimpleObject>    

    <SimpleObject Name="BlackGun" ID="3">              
        <Attribute Type="Detect">HSVColorBlackGun</Attribute> 
        <Attribute Type="Check">NotFractal</Attribute>
        <Attribute Type="Check">BlackGunSizeAttribute</Attribute>
    </SimpleObject>

    <SimpleObject Name="HaarBlackGun" ID="4" Mode="Hard" MergingPolicy="Union">              
        <Attribute Type="Detect">HaarGun</Attribute>
        <Attribute Type="Detect">MyBlobAttribute</Attribute> 
    </SimpleObject>  

</SimpleObjectBase>


<RelationLib>    

    
    
</RelationLib>


<ComplexObjectBase>
    
    
</ComplexObjectBase>
gun_detection.launch
<launch>
    <arg name="output" default="screen"/>
    <arg name="objectBasePath" default="$(find my_object_recognition_pkg)/config/object_base_example/Simple_Gun.xml"/>
    
    <node name="extended_object_detection" pkg="extended_object_detection" type="extended_object_detection_node" output="screen">
        
        <param name="objectBasePath" value="$(arg objectBasePath)"/>
        <param name="videoProcessUpdateRate" value="5"/>
        <param name="screenOutput" value="false"/>
        <param name="publishImage" value="true"/>
        <param name="publishMarkers" value="true"/>
        <param name="subscribeDepth" value="false"/>        
        <param name="maxContourPoints" value="-1"/>        
        
        <rosparam param="selectedOnStartSimple">[3]</rosparam>
        <rosparam param="selectedOnStartComplex">[-1]</rosparam>
        
    </node>        
    
</launch>

我们仅设置ID=3来稍微清理一下。

roslaunch my_object_recognition_pkg gun_detection.launch

您应该看到,现在桌子边框不再被检测到。当然,限制检测尺寸也有其缺点,因为如果机器人太近,枪将停止检测它。您需要了解机器人的正常工作条件才能做出这些决定。

练习 3.3.2

  • 为甜甜圈创建一个 HSV 检测器。
  • 将修改添加到 Simple_Gun.xml 和 gun_detector.launch 以检测枪和甜甜圈。
Parts to Add to Simple_Gun.xml
    <Attribute Name="HSVColorPinkDonut" Type="HSVColor" Hmin="68" Hmax="179" Smin="79" Smax="173" Vmin="142" Vmax="255"/>
    <Attribute Name="DonutSizeAttribute" Type="Size" MinAreaPc="0.00" MaxAreaPc="100"/>
    
    ...
    
    
    <SimpleObject Name="PinkDonut" ID="4">              
        <Attribute Type="Detect">HSVColorPinkDonut</Attribute> 
        <Attribute Type="Check">NotFractal</Attribute>
        <Attribute Type="Check">DonutSizeAttribute</Attribute>
    </SimpleObject>
Parts to Change in the gun_detection.launch
<rosparam param="selectedOnStartSimple">[3,4]</rosparam>

简单对象:HaarBlackGun

这里,它使用 HaarGun 属性,我们还会寻找斑点。如果 BOTH 检测到某些东西(HARD 模式),我们会将两个边界框合并为一个。添加此斑点检测是为了避免 Haar Cascade 检测到任何地方的“枪”,例如桌子侧面、桌腿、地平线或非常小的黑色伪影。

Haar in a Nutshell

基本的 Haar 操作是:

  • 我们获取一张图像并提取所有基本特征(之前图像中显示的黑白图案)。
  • 我们以群集或群组的形式执行此操作,以便更快地处理大图像。
  • 然后,我们使用 Adaboost 训练来选择能够提供更好结果(检测我们想要的内容)的特征。
  • 它使用级联分类器(本质上是机器学习)来完成繁重的工作。

要了解 Haar 的来源,请查看这篇论文:Paper Haar。

Use Haar

下载已由 Saksham00799 训练并创建的 Haar 分类器,在本例中用于检测枪支:

roscd my_object_recognition_pkg/config/object_base_example
git clone https://github.com/Saksham00799/opencv-gun-detection
mv opencv-gun-detection gun_haar

修改 Simple_Gun.xml 以查找 Haar 文件:

Simple_Gun.xml
<?xml version="1.0" ?>

<AttributeLib>
    <Attribute Name="HistColorPortalGun" Type="HistColor" Histogram="histograms/PortalGun.yaml"/>
    <Attribute Name="PotalGunSize" Type="Size" MinAreaPc="0.00" MaxAreaPc="100"/>
    <Attribute Name="NotFractal" Type="Size" MinAreaPc="0.5" MaxAreaPc="100"/>

    <Attribute Name="HistColorBanana" Type="HistColor" Histogram="histograms/Banana.yaml"/>
    <Attribute Name="BananaSize" Type="Size" MinAreaPc="0.05" MaxAreaPc="100"/>


    <Attribute Name="HSVColorBlackGun" Type="HSVColor" Hmin="0" Hmax="0" Smin="0" Smax="0" Vmin="22" Vmax="61"/>
    <Attribute Name="BlackGunSizeAttribute" Type="Size" MinAreaPc="0.01" MaxAreaPc="20"/>


    <Attribute Name="HSVColorPinkDonut" Type="HSVColor" Hmin="68" Hmax="179" Smin="79" Smax="173" Vmin="142" Vmax="255"/>
    <Attribute Name="DonutSizeAttribute" Type="Size" MinAreaPc="0.00" MaxAreaPc="100"/>
    
    <Attribute Name="HaarGun" Type="HaarCascade" Cascade="gun_haar/classifier/cascade.xml"/>
    <Attribute Name="MyBlobAttribute" Type="Blob" minThreshold="54" maxThreshold="125" blobColor="0" minArea="1500" minCircularity="0.03" minConvexity="0.64" minInertiaRatio="0.00"/>

</AttributeLib>

<SimpleObjectBase>  
      
    <SimpleObject Name="PortalGun" ID="1">              
        <Attribute Type="Detect">HistColorPortalGun</Attribute>  
        <Attribute Type="Check">PotalGunSize</Attribute>  
        <Attribute Type="Check">NotFractal</Attribute> 
    </SimpleObject>

    <SimpleObject Name="Banana" ID="2">              
        <Attribute Type="Detect">HistColorBanana</Attribute>  
        <Attribute Type="Check">BananaSize</Attribute>  
         
    </SimpleObject>    

    <SimpleObject Name="BlackGun" ID="3">              
        <Attribute Type="Detect">HSVColorBlackGun</Attribute> 
        <Attribute Type="Check">NotFractal</Attribute>
        <Attribute Type="Check">BlackGunSizeAttribute</Attribute>
    </SimpleObject>

    <SimpleObject Name="PinkDonut" ID="4">              
        <Attribute Type="Detect">HSVColorPinkDonut</Attribute> 
        <Attribute Type="Check">NotFractal</Attribute>
        <Attribute Type="Check">DonutSizeAttribute</Attribute>
    </SimpleObject>

    <SimpleObject Name="HaarBlackGun" ID="5" Mode="Hard" MergingPolicy="Union">              
        <Attribute Type="Detect">HaarGun</Attribute>
        <Attribute Type="Detect">MyBlobAttribute</Attribute> 
    </SimpleObject>  

</SimpleObjectBase>


<RelationLib>    

    
    
</RelationLib>


<ComplexObjectBase>
    
    
</ComplexObjectBase>
gun_detection.launch
<launch>
    <arg name="output" default="screen"/>
    <arg name="objectBasePath" default="$(find my_object_recognition_pkg)/config/object_base_example/Simple_Gun.xml"/>
    
    <node name="extended_object_detection" pkg="extended_object_detection" type="extended_object_detection_node" output="screen">
        
        <param name="objectBasePath" value="$(arg objectBasePath)"/>
        <param name="videoProcessUpdateRate" value="5"/>
        <param name="screenOutput" value="false"/>
        <param name="publishImage" value="true"/>
        <param name="publishMarkers" value="true"/>
        <param name="subscribeDepth" value="false"/>        
        <param name="maxContourPoints" value="-1"/>        
        
        <rosparam param="selectedOnStartSimple">[5]</rosparam>
        <rosparam param="selectedOnStartComplex">[-1]</rosparam>
        
    </node>        
    

启动检测器并查看其性能:

roslaunch my_object_recognition_pkg gun_detection.launch

这是没有属性的:

<Attribute Type="Detect">MyBlobAttribute</Attribute> 

正如你所见,Haar 探测器在甜甜圈、香蕉上,甚至桌子侧面都看到了很多可能的枪。

这就是我们添加 MyBlobAttribute 属性的原因。这将检测限制为仅检测大块黑白斑点。

练习 3.3.3

  • 下载 Haar 瓶分类器,看看它是否适用于 monster_can 饮料。
  • 您可以从 https://github.com/jemgunay/bottle-classifier.git 下载。您还可以在本课程的解决方案 Git 中找到 lint 版本。在完整的 Git 中,您可以检测杰克丹尼、伏特加、红牛和其他饮料。
roscd my_object_recognition_pkg/config/object_base_example
git clone https://github.com/jemgunay/bottle-classifier.git
  • 另外,请注意,当您尽可能靠近并且 PR2 机器人的躯干最大程度降低时,分类器的效果最佳。使用控制器 GUI 降低躯干并稍微向下倾斜头部以获得最佳性能。

Simple_Gun.xml 的新增内容
    <Attribute Name="HaarBottle" Type="HaarCascade" Cascade="bottle-classifier/classifier/classifier_monster/classifier/cascade.xml"/>

    ...
    
    
    <SimpleObject Name="HaarBottle" ID="6" Mode="Hard" MergingPolicy="Union">              
        <Attribute Type="Detect">HaarBottle</Attribute>
    </SimpleObject>    
编辑 gun_detection.launch
<rosparam param="selectedOnStartSimple">[5,6]</rosparam>

请注意,在这种情况下,我们不使用 blob。这是因为它不是进行检测所必需的,并且没有误报。如果一切顺利,您应该会得到类似于下图的结果:

复杂对象:

但在项目中,我们会使用复杂对象。它本质上是结合简单物体来检测更复杂的物体,例如,持枪的人。但那是最终项目。

请参阅下面的示例,了解如何完成此操作:

ArmedPerson.xml
<?xml version="1.0" ?>

<AttributeLib>
    <Attribute Name="HaarGun" Type="HaarCascade" Cascade="gun_haar/classifier/cascade.xml"/>
    <Attribute Name="MyBlobAttribute" Type="Blob" minThreshold="54" maxThreshold="125" blobColor="0" minArea="1500" minCircularity="0.03" minConvexity="0.64" minInertiaRatio="0.00"/>

    <Attribute Name="CnnPerson" Type="Dnn" framework="tensorflow" weights="ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb" config="ssd_mobilenet_v1_coco_2017_11_17/config.pbtxt" labels="ssd_mobilenet_v1_coco_2017_11_17/mscoco_label_map.pbtxt" inputWidth="300" inputHeight="300" Probability="0.5" obj_id="1"/> 
    

</AttributeLib>

<SimpleObjectBase>  
      
    <SimpleObject Name="HaarBlackGun" ID="3" Mode="Hard" MergingPolicy="Union">              
        <Attribute Type="Detect">HaarGun</Attribute>
        <Attribute Type="Detect">MyBlobAttribute</Attribute> 
    </SimpleObject>  

    <SimpleObject Name="CnnPerson" ID="67">              
        <Attribute Type="Detect">CnnPerson</Attribute>        
    </SimpleObject>    

</SimpleObjectBase>


<RelationLib>    

        <RelationShip Type="SpaceIn" Name="in"/>
    
</RelationLib>


<ComplexObjectBase>
    
    <ComplexObject ID="10" Name="ArmedPerson">
        <SimpleObject Class="CnnPerson" InnerName="Person"/>
        <SimpleObject Class="HaarBlackGun" InnerName="Gun"/>
        
        <Relation Obj1="Gun" Obj2="Person" Relationship="in"/>        
        
    </ComplexObject>
    
</ComplexObjectBase>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2150470.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【STL】pair 与 map:基础、操作与应用

C 标准库中提供了许多用于处理数据结构的容器和工具。pair 和 map 是两个非常有用的工具&#xff0c;广泛应用于存储和处理关联数据。在本文中&#xff0c;我们将详细介绍 pair 与 map 的相关操作&#xff0c;并结合代码实例为读者提供清晰的理解。 pair&#xff1a;成对数据的…

基于SpringBoot+Vue的家政预约平台系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…

powerbi-L8-导入数据时候的动态列

背景&#xff1a; 在数据导入之后刷新的过程中出现了无法刷新的异常报错&#xff0c; 检查后发现是由于原始数据的列的名字变化导致了power BI在处理数据类型的时候 需求 处理方法是什么&#xff0c; &#xff1f; 方法 动态获取表格的列&#xff1a; 获取数据的时候&#xff…

身份证识别接口的应用场景和作用

引言 在信息化与数字化高速发展的今天&#xff0c;身份证作为个人身份的重要证明文件&#xff0c;在各行各业的应用越来越广泛。传统的身份证信息录入和审核过程通常需要人工操作&#xff0c;不仅效率低下&#xff0c;而且容易出现错误。为了解决这些问题&#xff0c;身份证识别…

iftop流量监控工具

一、iftop简介 iftop可以用来监控网卡的实时流量&#xff08;可以指定网段&#xff09;、反向解析IP、显示端口信息等&#xff0c;详细的将会在后面的使用参数中说明。 二、安装iftop 1、编译安装 如果采用编译安装可以到iftop官网下载最新的源码包。 1.1 CentOS上安装所需…

学习之使用IDEA集成GIT

一、环境准备 1.1 配置git忽略文件 git.ignore 文件模版内容如下: # Compiled class file *.Class#Log file *.log# BlueJ file *.ctxt# Mobile Tools for Java (J2Me) *.mtj.tmp/# Package File *.jar *.war *.nar *.ear *.zip *.tar.gz *.rar.classpath .project .settings…

基于SSM+Vue+MySQL的酒店管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着旅游业的蓬勃发展&#xff0c;酒店业作为旅游产业链中的重要一环&#xff0c;面临着日益增长的客户需求和激烈的市场竞争。传统的人工酒店管理模式已难以满足高效、精准、个性化的服务要求。因此&#xff0c;开发一套基于SS…

powerBi -L4-分组求和

有如下的表格&#xff1a;我们想统计 不同商品的销售次数&#xff0c;根据商品ID进行分类&#xff0c;统计不同ID出现的次数 1.新建列&#xff1a; 2.输入如下的公式 分组统计序列 COUNTROWS(FILTER(数据源,[商品类别]EARLIER(数据源[商品类别])&&[索引]<EARLIE…

算法学习1

知识点 一.时间复杂度二.排序1.选择排序2.冒泡排序 三.异或交换 一.时间复杂度 列如&#xff1a; //长度为n的整型数组 int arr[n];//循环1 for(int i 0 ;i < n; i) {for(int j i;j < n;j){cout << arr[i] << endl;cout << arr[j] << endl;}…

(c语言+数据结构链表)项目:贪吃蛇

目录 1.项目背景 2.游戏效果演⽰ 3. ⽬标 4. 技术要点 5. Win32 API介绍 5.1 Win32 API 5.2 控制台程序 5.3 控制台屏幕上的坐标COORD 5.4 GetStdHandle 5.5 GetConsoleCursorInfo 5.5.1 CONSOLE_CURSOR_INFO 5.6 SetConsoleCursorInfo 5.7 SetConsoleCursorPositi…

统计项目代码行数工具—cloc

目录 引言一、cloc简介二、cloc安装三、cloc使用四、参考博客 引言 项目开发完成&#xff0c;想要查看自己项目的代码行数&#xff0c;强烈推荐一款非常好用的命令行工具-cloc。 一、cloc简介 只需要通过命令行的方式运行cloc&#xff0c;就可以得知指定文件代码行数、注释函…

java--章面向对象编程(高级部分)

类变量和类方法 类变量 类变量内存布局 什么是类变量 类变量也叫 静态变量/静态属性&#xff0c;是该类的所有对象共享的变量&#xff0c;任何一个该类的对象去访问它时&#xff0c;取到的都是相同的值&#xff0c;同样任何一个该类的对象去修改它时&#xff0c;修改的也是同…

基于flask+vue框架的传染病防控酒店信息系统zvt93(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;患者,服务人员,病房类型,病房信息,病房分配,需求箱,商品分类,商品信息,购买商品,分配反馈,健康上报,患者信息,患者分配 开题报告内容 基于flaskvue框架的传染病防控酒店信息系统开题报告 一、项目背景 在全球公共卫生事件频发的背景下…

排序-----选择排序

首先介绍几种排序的分类&#xff1a; 选择排序是每次都遍历&#xff0c;标记出最小的元素&#xff0c;然后把它放在前面。 本文介绍优化后的版本&#xff1a;每次遍历标记出最小的和最大的元素&#xff0c;分别放到前面和后面。&#xff08;注意这里是找到对应的下标&#xff0…

【Python报错已解决】To update, run: python.exe -m pip install --upgrade pip

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

如何使用ssm实现基于Javaweb的网上花店系统的设计与实现

TOC ssm653基于Javaweb的网上花店系统的设计与实现jsp 研究背景 自计算机发展以来给人们的生活带来了改变。第一代计算机为1946年美国设计&#xff0c;最开始用于复杂的科学计算&#xff0c;占地面积、开机时间要求都非常高&#xff0c;经过数十几的改变计算机技术才发展到今…

docker部署个人网页导航

1&#xff09;效果展示 2&#xff09;步骤 2.1&#xff09;往期部署docker自行查找 2.2&#xff09;CV命令 mkdir ~/onenav&&cd ~/onenav vi docker-compose.yml粘贴内容 version: 3 services:onenav:container_name: onenav #容器名称ports:- "3080:80"…

oracle avg、count、max、min、sum、having、any、all

组函数 having的使用 any的使用 all的使用

交换机VLAN配置

搭建拓扑图 思路&#xff1a; 先配置Access接口属性&#xff0c;包括SW1的e0/0/2&#xff0c;SW2的e0/0/3。配置Trunk端口属性&#xff0c;包括SW1的e0/0/1&#xff0c;SW2的e0/0/1&#xff0c;SW3的e0/0/2、e0/0/3。由于实验要求&#xff0c;同VLAN能够互通---->则允许SW1…

redis分布式锁(看门枸机制)

分布式锁确保在同一时间只有一个节点能获得对共享资源的独占访问权限&#xff0c;从而解决并发访问问题。 Redisson锁(简称看门狗) 它可以实现锁的延长&#xff0c;确保某个线程执行完才能让其他线程进行抢锁操作 引入看门狗机制后 如何使用&#xff1f; 1、引入依赖包 <…