精华内容
下载资源
问答
  • python目标检测

    2017-10-20 20:54:56
    基于python目标检测代码,新手可以来学习一下
  • 目标检测与YOLO算法(用Python实现目标检测

    千次阅读 多人点赞 2020-07-27 23:54:36
    最近在听Andrew Ng讲解目标检测的视频,包括目标定位,特征点检测,卷积的滑动窗口的实现,Bounding Box预测,交并比,非极大值抑制,AnchorBoxes,YOLO算法以及候选区域,并通过查阅相关的资料,对以上内容有了初步...

           最近在听Andrew Ng讲解目标检测的视频,包括目标定位,特征点检测,卷积的滑动窗口的实现,Bounding Box预测,交并比,非极大值抑制,AnchorBoxes,YOLO算法以及候选区域,并通过查阅相关的资料,对以上内容有了初步的理解,趁热打铁,总结如下。

    一、目标定位(Object Localization)

    图片分类:图片分类问题已经不陌生了,例如,输入一张图片到多层卷积神经网络,它会输出一个特征向量,并反馈给softmax单元来预测图片的类型。

    定位分类问题:不仅要用算法判断出图中是否有一辆汽车,而且还要标注汽车的位置,一般用边框(Bounding Box)来标注。通常只有一个较大的对象位于图片的中间位置,我们要对它进识别和定位。

    对象检测问题:图片可以含有多个对象 ,甚至单张图片会有多个不同的分类对象。因此图像分类的思路可以帮助我们学习对象定位,而对象定位的思路又可以帮助我们学习对象检测。 

    目标分类(Object Classification)
    目标定位(Object Localization)
    目标检测(Object Detection)

     

     举个栗子(example):

           如果你正在构建汽车自动驾驶系统,那么对象可以包括以下几类:行人、汽车、摩托车和背景,背景就是图片中没有行人、汽车、摩托车三类对象,输出结果便会是背景对象,这四个对象就是softmax函数可能输出的结果,这就是目标分类的过程。但是如果你还想定位图片中的位置,该怎么做呢?我们可以让神经网络多输出几个单元,输出一个边界框。具体说就是让神经网络再多输出 4 个数字,标记b_{x}b_{y}b_{h}b_{w}这四个数字是被检测对象的边界框的参数化表示。

            

            图片的左上角是(0,0),右下角是(1,1),要确定边界框的具体位置,需要指定红色方框的中心点,这个点表示为 (b_{x} ,b_{y}),边界框的高度为b_{h},宽度为b_{w}。因此训练集不仅包含神经网络要预测的对象分类标签,还要包含表示边界框的这四个数字,接着采用监督学习算法,输出一个分类标签,还有四个参数值,从而给出检测对象的边框位置。此例中, b_{x}的理想值是 0.5,b_{y}大约是 0.7,b_{h}约为 0.3,b_{w}约为 0.4。

    目标标签y的定义如下:

           它是一个向量,第一个组件p_{c}表示是否含有对象,如果对象属于前三类(行人,汽车,摩托车),则 p_{c} = 1,如果是背景,则图片中没有要检测的对象,则p_{c} = 0,我们可以这样理解p_{c},它表示被检测对象属于某一分类的概率,背景分类除外。c_{1}c_{2}c_{3}表示对象属于1-3类的哪一类,是行人,汽车,还是摩托车。神经网络中的损失函数,其参数为类别y和网络输出\hat{y},如果采用平方误差策略,则:损失值等于每个元素相应差值的平方和。当y_{1} = 1时,平方误差策略可以减少这 8 个元素预测值和实际输出结果之间差值的平方。当y_{1}时,y矩阵中的后 7 个元素都不用考虑,只需要考虑神经网络评估y1y1(即pcpc)的准确度。

    实际应用中,你可以对c_{1}c_{2}c_{3}和 softmax 激活函数应用对数损失函数,并输出其中一个元素值,通常做法是对边界框坐标应用平方差或类似方法,对p_{c}应用逻辑回归函数,甚至采用平方预测误差也是可以的。

     二、特征点检测

           上面,我们讲了如何利用神经网络进行对象定位,即通过输出四个参数值b_{x}b_{y}b_{h}b_{w}给出图片中对象的边界框。更概括地说,神经网络可以通过输出图片上特征点的(x,y)坐标来实现对目标特征的识别,我们看几个例子。

            假设你正在构建一个人脸识别应用,出于某种原因,你希望算法可以给出眼角的具体位置。眼角坐标为(x,y),你可以让神经网络的最后一层多输出两个数字l_{x}l_{y},作为眼角的坐标值。如果你想知道两只眼睛的四个眼角的具体位置,那么从左到右,依次用四个特征点来表示这四个眼角。对神经网络稍做些修改,输出第一个特征点(l_{1x},l_{1y})第二个特征点(l_{2x},l_{2y}),依此类推,这四个脸部特征点的位置就可以通过神经网络输出了。 

           也许除了这四个特征点,你还想得到更多的特征点输出值,这些(图中眼眶上的红色特征点)都是眼睛的特征点,你还可以根据嘴部的关键点输出值来确定嘴的形状,从而判断人物是在微笑还是皱眉,也可以提取鼻子周围的关键特征点。为了便于说明,你可以设定特征点的个数,假设脸部有 64 个特征点,有些点甚至可以帮助你定义脸部轮廓或下颌轮廓。选定特征点个数,并生成包含这些特征点的标签训练集,然后利用神经网络输出脸部关键特征点的位置。 

           具体做法是,准备一个卷积网络和一些特征集,将人脸图片输入卷积网络,输出1或0,1表示有人脸,0表示没有人脸,然后输出(l_{1x},l_{1y}) ……直到(l_{64x},l_{64y})。这里我用l代表一个特征,这里有 129个输出单元,其中1表示图片中有人脸,因为有 64个特征,64×2=128,所以最终输出 128+1=129 个单元,由此实现对图片的人脸检测和定位。这只是一个识别脸部表情的基本构造模块,如果你玩过 Snapchat 或其它娱乐类应用,你应该对 AR(增强现实)过滤器多少有些了解, Snapchat 过滤器实现了在脸上画皇冠和其他一些特殊效果。检测脸部特征也是计算机图形效果的一个关键构造模块,比如实现脸部扭曲,头戴皇冠等等。当然为了构建这样的网络,你需要准备一个标签训练集,也就是图片和标签的集合,这些点都是人为辛苦标注的。

            最后一个例子,如果你对人体姿态检测感兴趣,你还可以定义一些关键特征点,如胸部的中点,左肩,左肘,腰等等。然后通过神经网络标注人物姿态的关键特征点,再输出这些标注过的特征点,就相当于输出了人物的姿态动作。当然,要实现这个功能,你需要设定这些关键特征点,从胸部中心点(l_{1x},l_{1y})一直往下,直到(l_{32x},l_{32y})。

    三、目标检测(多个目标)

           学过了对象定位和特征点检测,我们来构建一个对象检测算法。我们将学习如何通过卷积网络进行对象检测,采用的是基于滑动窗口的目标检测算法。

           假如你想构建一个汽车检测算法,步骤是,首先创建一个标签训练集,也就是x和y表示适当剪切的汽车图片样本,这张图片(编号 1)x是一个正样本. ,因为它是一辆汽车图片,这几张图片(编号 2、 3)也有汽车,但这两张(编号 4、 5)没有汽车。出于我们对这个训练集的期望,你一开始可以使用适当剪切的图片,就是整张图片几乎都被汽车占据,你可以照张照片,然后剪切,剪掉汽车以外的部分,使汽车居于中间位置,并基本占据整张图片。有了这个标签训练集,你就可以开始训练卷积网络了,输入这些适当剪切过的图片(编号 6),卷积网络输出y, 0 或 1 表示图片中有汽车或没有汽车。训练完这个卷积网络,就可以用它来实现滑动窗口目标检测,具体步骤如下: 

            假设这是一张测试图片,首先选定一个特定大小的窗口,比如图片下方这个窗口,将这个红色小方块输入卷积神经网络,卷积网络开始进行预测,即判断红色方框内有没有汽车。 

            滑动窗口目标检测算法接下来会继续处理第二个图像,即红色方框稍向右滑动之后的区域,并输入给卷积网络,因此输入给卷积网络的只有红色方框内的区域,再次运行卷积网络,然后处理第三个图像,依次重复操作,直到这个窗口滑过图像的每一个角落,这就是所谓的图像滑动窗口操作。

    注意:滑动窗口目标检测算法也有很明显的缺点,就是计算成本,因为你在图片中剪切出太多小方块,卷积网络要一个个地处理。如果你选用的步幅很大,显然会减少输入卷积网络的窗口个数,但是粗糙间隔尺寸可能会影响性能。反之,如果采用小粒度或小步幅,传递给卷积网络的小窗口会特别多,这意味着超高的计算成本。 

            在上述我们已经说过滑动窗口目标检测算法也有很明显的缺点,如何解决这个算法的缺点呢?在卷积层上应用滑动窗口目标检测算法可以明显的提高这个算法的效率。为了构造滑动窗口的卷积应用,首先要知道如何把神经网络的全连接层转化为卷积层。下图可以直观的解释全连接层向卷积层转化的过程。

            第一部分(上面那部分)是全连接层的过程,第二部分(下面那部分)是全连接层向卷积层的转化 。下面举一个例子,解释一下在卷积层上应用滑动窗口检测的算法过程,如下图所示。

             在上图中假设图像大小为16×16×3,窗口的大小为14×14×3,假设步长为2,那么窗口要经过4次才能遍历整个图像,也就是在卷积层里进行4次运算,这样也会使算法的效率很低。我们的解决办法是,直接将整个图像经过卷积层、池化层这样1次操作,在上图中可以看出,最后输出的2×2×4的结果便是经过4次的结果,例如2×2×4图像的左上角区域,对应着图像的左上角的滑动窗口。

     四、Bounding Box预测

             在上述的在卷积层应用窗口检测算法虽然效率很高,但是其输出的边框的精准度不是很高(如下图展示,不能很精准的输出汽车的边框),如何才能使输出的边框精准度变高呢?用YOLO算法(You Only Look Once)便可解决这个问题。

             YOLO 算法做的就是,将图像分成n×n的网格(下图是分成3×3的网格),取两个对象的中点,然后将这个对象分配给包含对象中点的格子。所以左边的汽车就分配到绿色框标记的格子上,右边的汽车就分配到黄色框标记的格子上。即使中心格子同时有两辆车的一部分,我们就假装中心格子没有任何我们感兴趣的对象。 

    五、交并比

             如评价目标检测算法的好坏呢?这里便可引入交并比。

             在上图中假设红色区域是真实的汽车边框,蓝色区域是应用目标检测算法所检测的边框,那么交并比(LoU)就可以如上图所表示,即黄色区域 /绿色区域 。如果LoU>=0.5就可以认定所检测输出的边框合格,这里的0.5称为阀门(人工定义的),也可以是0.6, 0.7等等。

    六、非极大值抑制

             到目前为止我们学习到的目标检测算法仍然存在一个问题,就是当我们使用目标检测算法时,我们对同一个对象可能检验多次,如同下面这个图所示,同一对象可能检测出多次。

              我们分步介绍一下非极大值抑制是怎么起效的,因为你要在 361 个格子上都运行一次图像检测和定位算法,那么可能很多格子都会举手说我的Pc ,我这个格子里有车的概率很高,而不是 361 个格子中仅有两个格子会报告它们检测出一个对象。所以当你运行算法的时候,最后可能会对同一个对象做出多次检测,所以非极大值抑制做的就是清理这些检测结果。这样一辆车只检测一次,而不是每辆车都触发多次检测。非极大值抑制可以确保我们对一个对象只检验一次,非极大值抑制算法的具体细节如下图所示。

     非极大值抑制算法步骤:

    1、将所有的输出的p_{c}进行排序,选出最高的p_{c}及其对应输出框。

    2、遍历其余的输出框,如果和当前最高p_{c}的输出框的重叠面积(IOU)大于一定阈值,我们就将框删除。

    3、从未处理的输出框中继续选一个最高p_{c}的,重复上述过程。

    七、Anchor Boxes 

              到目前为止我们所熟悉的目标检测算法每个格子只能检测出一个对象,如果想让一个格子检测出多个对象,那么便可引出Anchor Boxes这个概念,举个栗子:

            对于上面那个图像,我们将它分割为3×3,那么可以清楚的看到,人的中点和车的中点落到了同一个格子里,如果按照上述的目标检测算法,便不知道要输出哪个结果,怎么解决这个问题呢?

            此时我们可以预先定义两个不同形状的Anchor Box ,并把预测结果与这两个Anchor Box相关联,此时的y可以定义如下:

     前8个的结果可以与Anchor Box1相关联,后8个的结果可以与Anchor Box2相关联。下图是无Anchor Box和有Anchor Box的对比过程。

    八、YOLO算法 

            由上面所学习到的知识组装起来构成YOLO对象检测算法。

            假设我们要在图片中检测三种目标:行人、汽车和摩托车,同时使用两种不同的Anchor box。

          (1)训练集:

    • 输入X:同样大小的完整图片;
    • 目标Y:使用
    • 对不同格子中的小图,定义目标输出向量Y。

          (2)模型预测:

                   输入与训练集中相同大小的图片,同时得到每个格子中不同的输出结果:

          (3)运行非最大值抑制(NMS):

    • 假设使用了2个Anchor box,那么对于每一个网格,我们都会得到预测输出的2个bounding boxes,其中一个比较高;

      还在路上,稍等...

    • 抛弃概率值低的预测bounding boxes;

      还在路上,稍等...

    • 对每个对象(如行人、汽车、摩托车)分别使用NMS算法得到最终的预测边界框。

      还在路上,稍等...

    九、python实现YOLO目标检测

            我们将在这篇博客使用在COCO数据集上预训练好的YOLOv3模型。COCO 数据集包含80类,有people (人),bicycle(自行车),car(汽车)......,详细类别可查看链接:https://github.com/pjreddie/darknet/blob/master/data/coco.names

    # -*- coding: utf-8 -*-
    # 载入所需库
    import cv2
    import numpy as np
    import os
    import time
    
    
    def yolo_detect(pathIn='',
                    pathOut=None,
                    label_path='./cfg/coco.names',
                    config_path='./cfg/yolov3.cfg',
                    weights_path='./cfg/yolov3.weights',
                    confidence_thre=0.5,
                    nms_thre=0.3,
                    jpg_quality=80):
        '''
        pathIn:原始图片的路径
        pathOut:结果图片的路径
        label_path:类别标签文件的路径
        config_path:模型配置文件的路径
        weights_path:模型权重文件的路径
        confidence_thre:0-1,置信度(概率/打分)阈值,即保留概率大于这个值的边界框,默认为0.5
        nms_thre:非极大值抑制的阈值,默认为0.3
        jpg_quality:设定输出图片的质量,范围为0到100,默认为80,越大质量越好
        '''
    
        # 加载类别标签文件
        LABELS = open(label_path).read().strip().split("\n")
        nclass = len(LABELS)
    
        # 为每个类别的边界框随机匹配相应颜色
        np.random.seed(42)
        COLORS = np.random.randint(0, 255, size=(nclass, 3), dtype='uint8')
    
        # 载入图片并获取其维度
        base_path = os.path.basename(pathIn)
        img = cv2.imread(pathIn)
        (H, W) = img.shape[:2]
    
        # 加载模型配置和权重文件
        print('从硬盘加载YOLO......')
        net = cv2.dnn.readNetFromDarknet(config_path, weights_path)
    
        # 获取YOLO输出层的名字
        ln = net.getLayerNames()
        ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
    
        # 将图片构建成一个blob,设置图片尺寸,然后执行一次
        # YOLO前馈网络计算,最终获取边界框和相应概率
        blob = cv2.dnn.blobFromImage(img, 1 / 255.0, (416, 416), swapRB=True, crop=False)
        net.setInput(blob)
        start = time.time()
        layerOutputs = net.forward(ln)
        end = time.time()
    
        # 显示预测所花费时间
        print('YOLO模型花费 {:.2f} 秒来预测一张图片'.format(end - start))
    
        # 初始化边界框,置信度(概率)以及类别
        boxes = []
        confidences = []
        classIDs = []
    
        # 迭代每个输出层,总共三个
        for output in layerOutputs:
            # 迭代每个检测
            for detection in output:
                # 提取类别ID和置信度
                scores = detection[5:]
                classID = np.argmax(scores)
                confidence = scores[classID]
    
                # 只保留置信度大于某值的边界框
                if confidence > confidence_thre:
                    # 将边界框的坐标还原至与原图片相匹配,记住YOLO返回的是
                    # 边界框的中心坐标以及边界框的宽度和高度
                    box = detection[0:4] * np.array([W, H, W, H])
                    (centerX, centerY, width, height) = box.astype("int")
    
                    # 计算边界框的左上角位置
                    x = int(centerX - (width / 2))
                    y = int(centerY - (height / 2))
    
                    # 更新边界框,置信度(概率)以及类别
                    boxes.append([x, y, int(width), int(height)])
                    confidences.append(float(confidence))
                    classIDs.append(classID)
    
        # 使用非极大值抑制方法抑制弱、重叠边界框
        idxs = cv2.dnn.NMSBoxes(boxes, confidences, confidence_thre, nms_thre)
    
        # 确保至少一个边界框
        if len(idxs) > 0:
            # 迭代每个边界框
            for i in idxs.flatten():
                # 提取边界框的坐标
                (x, y) = (boxes[i][0], boxes[i][1])
                (w, h) = (boxes[i][2], boxes[i][3])
    
                # 绘制边界框以及在左上角添加类别标签和置信度
                color = [int(c) for c in COLORS[classIDs[i]]]
                cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
                text = '{}: {:.3f}'.format(LABELS[classIDs[i]], confidences[i])
                (text_w, text_h), baseline = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2)
                cv2.rectangle(img, (x, y - text_h - baseline), (x + text_w, y), color, -1)
                cv2.putText(img, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2)
    
        # 输出结果图片
        if pathOut is None:
            cv2.imwrite('with_box_' + base_path, img, [int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality])
        else:
            cv2.imwrite(pathOut, img, [int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality])
    
    pathIn = '../image/yolo_test1.jpg'
    pathOut = '../out/yolo_test1.jpg'
    yolo_detect(pathIn,pathOut)

    测试一: 

            原图:

       

            经过YOLO目标检测之后result: 

    测试二: 

            原图:

             经过YOLO目标检测之后result: 

     

    十、 候选区域(region proposals)

            R-CNN(Regions with convolutional networks),会在我们的图片中选出一些目标的候选区域,从而避免了传统滑动窗口在大量无对象区域的无用运算。所以在使用了R-CNN后,我们不会再针对每个滑动窗口运算检测算法,而是只选择一些候选区域的窗口,在少数的窗口上运行卷积网络。

            具体实现:运用图像分割算法,将图片分割成许多不同颜色的色块,然后在这些色块上放置窗口,将窗口中的内容输入网络,从而减小需要处理的窗口数量。

     

     更快的算法:

    (1)R-CNN:给出候选区域,对每个候选区域进行分类识别,输出对象 标签 和 bounding box,从而在确实存在对象的区域得到更精确的边界框,但速度慢;

    (2)Fast R-CNN:给出候选区域,使用滑动窗口的卷积实现去分类所有的候选区域,但得到候选区的聚类步骤仍然非常慢;

    (3)Faster R-CNN:使用卷积网络给出候选区域。

           以上是我对吴恩达讲解目标检测知识的总结,如果有什么理解不到位的地方,还请指点改正 

     

    展开全文
  • 今天小编就为大家分享一篇python:目标检测模型预测准确度计算方式(基于IoU),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • (43条消息)python目标检测数据集xml文件操作_Python_Rock的博客-CSDN博客 https://blog.csdn.net/weixin_38632246/article/details/90710139?depth_1- (43条消息)Python目标检测数据集xml文件操作(统计目标...

    (43条消息)python对目标检测数据集xml文件操作_Python_Rock的博客-CSDN博客
    https://blog.csdn.net/weixin_38632246/article/details/90710139?depth_1-

     

    (43条消息)Python对目标检测数据集xml文件操作(统计目标种类、数量、面积、比例等&修改目标名字)_Python_DLUT_yan的博客-CSDN博客
    https://blog.csdn.net/weixin_43384257/article/details/100581673?depth_1-

    (42条消息)python:批量统计xml中各类目标的数量_Python_gusui7202的博客-CSDN博客
    https://blog.csdn.net/gusui7202/article/details/86583444

    (43条消息)python:批量统计xml中各类目标的数量_Python_gusui7202的博客-CSDN博客
    https://blog.csdn.net/gusui7202/article/details/86583444

     

    (43条消息)目标检测数据集整理_数据库_I am what i am-CSDN博客
    https://blog.csdn.net/liuxiao214/article/details/80552026

     

    (43条消息)将检测的物体转换成xml文件_Python_wxshan3的博客-CSDN博客
    https://blog.csdn.net/wxshan3/article/details/82771524

     

    (43条消息)目标检测:批量删除xml中过小的目标_Python_gusui7202的博客-CSDN博客
    https://blog.csdn.net/gusui7202/article/details/86572692

    (43条消息)Python: 文件夹下xml内容批量替换、删除_Python_gusui7202的博客-CSDN博客
    https://blog.csdn.net/gusui7202/article/details/85194806

    (43条消息)目标检测xml文件转换 行_weixin_38102912的博客-CSDN博客
    https://blog.csdn.net/weixin_38102912/article/details/100671567

     

    展开全文
  • 采用python-flask框架开发,基于B/S方式交互,支持多人同时标注
  • 如果尚未安装python库,你需要安装以下python库:opencv-pythoncvlibmatplotlibtensorflow下面的代码导入所需的python库,从存储中读取图像,对图像执行目标检测,并显示带有边界框和关于检测目标的标签的图像。...

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlbmRvdWFpbmk=,size_16,color_FFFFFF,t_70

    要知道图像中的目标是什么?

    或者你想数一幅图里有多少个苹果?

    在本文中,我将向你展示如何使用Python在不到10行代码中创建自己的目标检测程序。

    如果尚未安装python库,你需要安装以下python库:

    opencv-python

    cvlib

    matplotlib

    tensorflow

    下面的代码导入所需的python库,从存储中读取图像,对图像执行目标检测,并显示带有边界框和关于检测目标的标签的图像。

    import cv2

    import matplotlib.pyplot as plt

    import cvlib as cv

    from cvlib.object_detection import draw_bbox

    im = cv2.imread('apple-256261_640.jpg')

    bbox, label, conf = cv.detect_common_objects(im)

    output_image = draw_bbox(im, bbox, label, conf)

    plt.imshow(output_image)

    plt.show()

    下面是使用上述代码进行目标检测的一些结果。

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlbmRvdWFpbmk=,size_16,color_FFFFFF,t_70

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlbmRvdWFpbmk=,size_16,color_FFFFFF,t_70

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlbmRvdWFpbmk=,size_16,color_FFFFFF,t_70

    到这,你就已经准备完成你的目标检测程序了。

    要了解更多关于cvlib库的信息,可以访问下面的链接。

    cvlib[^1]

    以下是一些进一步的阅读资料,以了解目标检测的工作原理:

    使用深度学习方法的目标检测[^2]

    基本目标检测算法的逐步介绍(第1部分)[^3]

    [^1]: https://www.cvlib.net/[^2]: https://towardsdatascience.com/object-detection-using-deep-learning-approaches-an-end-to-end-theoretical-perspective-4ca27eee8a9a[^3]: https://www.analyticsvidhya.com/blog/2018/10/a-step-by-step-introduction-to-the-basic-object-detection-algorithms-part-1/

    欢迎关注磐创博客资源汇总站:http://docs.panchuang.net/

    欢迎关注PyTorch官方中文教程站:http://pytorch.panchuang.net/

    展开全文
  • Yolo-v3+Python 3.7目标检测 物体识别

    千次阅读 2020-09-04 19:13:16
    Yolo-v3+Python 3.7目标检测前言一、新建工程二、新建.py文件,编写程序1.获取相机2.读入数据总结 前言 运行yolo v3 有很多方法,最简单的一种就是使用opencv与numpy。 此文程序在PyCharm中编译运行。 一、新建...


    前言

    运行yolo v3 有很多方法,最简单的一种就是使用opencv与numpy。
    此文程序在PyCharm中编译运行。
    本文程序和所需yolo文件,coco names, 源代码都可在以下百度云盘链接下载:
    链接:https://pan.baidu.com/s/1575DPtD-Zp2ZADWgGJDT0Q
    提取码:mhad


    一、新建工程

    新建工程"Object_Detection",并在File-Setting-Project:Object_Detection中点击右上角加号,搜索并添加我们需要的library:opencv-python,numpy。
    添加library

    接着,我们需要前往yolo官网下载下图中所需的config和weight文件:YOLOv3-tiny.Cfg与YOLOv3-tiny.weights, YOLOv3.Cfg与YOLOv3.weights(YOLOv3即为320p版本)
    Yolo官网链接如下:https://pjreddie.com/darknet/yolo/
    如果下载速度太慢,可以使用以下百度网盘链接进行下载:
    链接:https://pan.baidu.com/s/1575DPtD-Zp2ZADWgGJDT0Q
    提取码:mhad
    在这里插入图片描述

    二、编写.py程序

    1.获取相机

    引入opencv-python,numpy库:

    import cv2
    import numpy as np
    

    2.读入数据

    为了从相机获取帧,我们将声明一个Video Capture对象,并为其指定摄像机的索引。如果您使用的是笔记本电脑,或者仅连接了一个摄像头,则可以将其保留为0。然后,我们创建一个while循环,以不断获取来自摄像头的最新帧。使用read 方法获取图像,然后使用imshow()函数显示图像 。
    cap = cv2.VideoCapture(0)
     
    while True:
        success, img = cap.read()
     
        cv2.imshow('Image', img)
        cv2.waitKey(1)
    

    运行后可获取摄像头实时画面。
    waitKey()是在一个给定的时间内(单位ms)等待用户按键触发, 如果用户没有按下 键,则接续等待(循环)。

    3.读入Coco Names名单

    加载yolo3模型,由于它是根据coco dataset进行训练的,因此我们将首先收集class names。可以从coco.names文件导入(可在云盘中下载)。当然也可以手动输入所有类名。但由于有80个不同的类,因此最好使用该文件导入。【可以在PyCharm中打开coco.names文件查看这80各不同的类】
    classesFile = "coco.names"
    classNames = []
    with open(classesFile, 'rt') as f:
        classNames = f.read().rstrip('\n').split('\n')
    print(classNames)
    

    4.载入模型

    任何的模型都有两个主要组成部分:一个是结构体系,另一个是权重。对于yolo-V3,这两个组成部分被分为了两个不同的文件。因此,我们将导入包含结构的configuration文件和包含权重的weights文件。 在Yolo官网上,我们可以找到不同的.cfg和.weight文件。在这个项目里面我们可以先试用tiny来实现快速的识别,以适应不同配置的PC。
    modelConfiguration = "yolov3-tiny.cfg"
    modelWeights = "yolov3-tiny.weights
    
    使用readNetFromDarkNet function载入我们的模型。同时将后端设置为openCV,将目标设置为CPU。
    net = cv2.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
    net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
    net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
    

    5.将图像输入到网络

    由于无法将相机拍摄的图像直接发送到网络。它必须采用blob的格式。我们可以使用blobFromImage函数从图像创建4维blob。输入为img, 可选参数分别为: 图像各通道数值的缩放比例,输出图像的空间尺寸, 各通道减去的值,以降低光照的影响, 交换蓝色和红色通道, 图像裁剪,默认为False.。
    	blob = cv2.dnn.blobFromImage(img, 1/255, (320, 320), [0, 0, 0], 1, crop=False)
        net.setInput(blob)
    

    6.获取网络输出

    由于Yolo3体系结构具有3个输出层(如下图所示),我们必须找到它们对应的名称,以获得它们的输出。

    在这里插入图片描述

    获取Layer名称,我们需要使用net.getLayerNames函数。我们可以打印这些名称,可以看到这会返回所有的layer名称。

    但在这里,我们只需要输出层的名称。因此,我们可以使用getUnconnectedOutLayers函数,该函数只返回输出层的索引。现在我们可以简单地使用这些索引从我们的layersNames列表中找到名称。由于我们将0用作第一个元素,因此必须从getUnconnectedOutLayers函数获得的索引中减去1。

    	layerNames = net.getLayerNames()
        print(layerNames)
        outputNames = [layerNames[i[0]-1] for i in net.getUnconnectedOutLayers()]
        print(outputNames)  # Find the output layers [3 different output layers]
    
    现在,我们可以运行前向通过并找到网络的输出。
    	# Set the outputs
        outputs = net.forward(outputNames)
        print(outputs[0].shape)  # Bounding boxes
        print(outputs[1].shape)
        print(outputs[2].shape)
        '''The first 4 values of 85 are: Center X, Center Y, Width, Height
              The 5th value is 'Confidence' that there is an object in the box
              The other 80 values are the prediction probabilities of 80 classes'''
    
    这将返回以下大小的3个数组的列表 [300 x 85] [1200 x 85] [4800 x 85] 这里的300、1200和4800是我们从各个输出层获得的box数量。但是85的值是多少? 定义一个box,我们需要中心位置center-x,center-y和宽、高w,h定义它。这意味着我们只需要4个值(x,y,w,h),所以我们的数组应该是300×4、1200×4和4800×4,那么剩下的81个值是什么? 第5个值是confidence,它告诉我们此框中有一个对象的可能性有多大。其余的80个值分别对应于每个类别的置信度。因此,如果图像中有汽车,则5 + 3 =第8个元素将显示高置信度值,例如0.93(汽车是coco.names列表中的第3个元素)。

    在这里插入图片描述

    7.寻找物体

    由于我们有了包含盒子所有信息的数组,我们就可以过滤掉低confidence的数组,并创建一个包含对象的相关盒子的列表。我们将使用名称findObjects来创建一个子函数。 为了存储相关框的信息,我们将创建3个list。一个包含边界框角点的信息,另一个具有最高confidence的Class ID,最后一个具有最高分类的confidence。
    	boundingBox = []
        classIDs = []
        confidences = []
    
    接着,我们将遍历三个输出层,得到所有的box。这里我们引入det(detection的缩写),做获得每个class的confidence时,我们需要先去掉前5个数值。
    	def findObjects(outputs, img):
        height, width, channel = img.shape
        boundingBox = []
        classIDs = []
        confidences = []
        for outputs in outputs:
            for det in outputs:
                scores = det[5:] # Confidence value of 80 classes
                classID = np.argmax(scores) 
                confidence = scores[classID]
    
    在获得所有的box之后,我们将设置一个阈值。只有当confidence远胜于此阈值时,才有资格作为检测到的对象。然后我们可以得到x,y,w,h的像素值。要获得像素值,我们可以简单地将其分别乘以宽度和高度。注意,我们将使用x,y作为原点,而不是cx,cy作为中心点。最后,我们将这些值append到相应的list中。
    if confidence > threshold:
    	w, h = int(det[2]*width), int(det[3]*height)  #Box Width and Height
    	x, y = int((det[0]*width) - w/2), int(det[1]*height - h/2)  # Center point
    	boundingBox.append([x, y, w, h])
    	classIDs.append(classID)
    	confidences.append(float(confidence))
    
    此时,当我们运行此程序时会发现,会出现有一个以上的盒子指向同一个对象。在这种情况下,尽管实际上我们只有一个对象,但是我们有2次检测。下面是一个示例:

    在这里插入图片描述

    为了避免出现这样的情况,我们将使用 Non Max Suppression(非最大抑制)cv2.dnn.NMSBoxes()。NMS消除了重叠的框。它找到重叠的框,然后根据它们的confidence,将选择confidence最大的框并抑制其他所有非最大框。因此,我们将使用内置的NMSBoxes函数。该函数输入为预测框左上角和右下角的尺寸,它们的confidence置信度,置信度阈值和nmsThreshold。
    indices = cv2.dnn.NMSBoxes(boundingBox, confidences, threshold, nms_threshold=0.2)
    
    这时,我们已经找到了置信度最大的box,接着,我们可以简单地绘制该box的边框,并显示检测到的对象名称和置信度值。
        for i in indices:
            i = i[0]
            box = boundingBox[i]
            x,y,w,h = box[0],box[1],box[2],box[3]
            cv2.rectangle(img, (x,y),(x+w, y+h),(255,0,255),2)
            cv2.putText(img,f'{classNames[classIDs[i]].upper()} {int(confidences[i]*100)}%',
                        (x,y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,0,255),2)
    

    8.运行程序

    当我们完成代码编写后(完整代码见底部),可以分别使用320和tiny来测试程序。可以发现他们都可以准确地检测到物体,并显示名称和置信度,但是320的准确度更高(帧率较低),tiny的速度更快,但可靠性稍低于320。

    在这里插入图片描述

    完整代码

    import cv2
    import numpy as np
    
    cap = cv2.VideoCapture(0)
    
    classesFile = 'coco.names'
    classNames = []
    with open(classesFile, 'rt') as f:
        classNames = f.read().rstrip('\n').split('\n')
    print(classNames)
    print("Class number: ", len(classNames))
    
    # Declare path variable
    modelConfiguration = 'yolov3-tiny.cfg'
    modelWeights = 'yolov3-tiny.weights'
    
    threshold = 0.4
    
    # Load model
    net = cv2.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
    net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
    net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
    
    def findObjects(outputs, img):
        height, width, channel = img.shape
        boundingBox = []
        classIDs = []
        confidences = []
        for outputs in outputs:
            for det in outputs:
                scores = det[5:]
                classID = np.argmax(scores)
                confidence = scores[classID]
    
                if confidence > threshold:
                    w, h = int(det[2]*width), int(det[3]*height)  #Box Width and Height
                    x, y = int((det[0]*width) - w/2), int(det[1]*height - h/2)  # Center point
                    boundingBox.append([x, y, w, h])
                    classIDs.append(classID)
                    confidences.append(float(confidence))
        # print(len(boundingBox))
        indices = cv2.dnn.NMSBoxes(boundingBox, confidences, threshold, nms_threshold=0.2)
        for i in indices:
            i = i[0]
            box = boundingBox[i]
            x,y,w,h = box[0],box[1],box[2],box[3]
            cv2.rectangle(img, (x,y),(x+w, y+h),(255,0,255),2)
            cv2.putText(img,f'{classNames[classIDs[i]].upper()} {int(confidences[i]*100)}%',
                        (x,y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,0,255),2)
    
    
    while True:
        success, img = cap.read()
    
        blob = cv2.dnn.blobFromImage(img, 1/255, (320, 320), [0, 0, 0], 1, crop=False)
        net.setInput(blob)
    
        layerNames = net.getLayerNames()
        #print(layerNames)
        outputNames = [layerNames[i[0]-1] for i in net.getUnconnectedOutLayers()]
        #print(outputNames)  # Find the output layers [3 different output layers]
        # Set the outputs
        outputs = net.forward(outputNames)
        # print(outputs[0].shape)  # Bounding boxes
        # print(outputs[1].shape)
        # print(outputs[2].shape)
        '''The first 4 values of 85 are: Center X, Center Y, Width, Height
              The 5th value is 'Confidence' that there is an object in the box
              The other 80 values are the prediction probabilities of 80 classes'''
    
        findObjects(outputs, img)
        cv2.imshow('image', img)
        cv2.waitKey(1)
    

    总结

    以上是yolo v3的一个基本尝试,速度与识别准确度都尚可。我也还在入门学习,如有错误请指正。

    展开全文
  • 训练完目标检测模型之后,需要评价其性能,在不同的阈值下的准确度是多少,有没有漏检,在这里基于IoU(Intersection over Union)来计算。   希望能提供一些思路,如果觉得有用欢迎赞我表扬我~   IoU的值可以...
  • Python目标检测任务绘制 ROC 和 PR 曲线

    万次阅读 热门讨论 2018-08-05 20:51:07
    需要两个分别记录检测结果和标准答案的 .txt 文件,记录格式与 FDDB 的要求相同,即 ... image name i number of faces in this image =im face i1 face i2 ... face im ... 当检测框为矩形时,...
  • 主要介绍了OpenCV+python实现实时目标检测功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • 本文为 AI 研习社编译的技术...Object detection with Raspberry Pi and Python 作者 |Quantum 翻译 | leogle97、谢玄xx 校对 | 邓普斯•杰弗 审核 | 酱番梨 整理 | Pita 原文链接: https://medium....
  • 10行Python代码实现目标检测,内含文档和安装实现教程,方便大家参考学习
  • windows环境下Python3.7目标检测标注工具labelImg安装 LabelImg下载:https://github.com/tzutalin/labelImg 将下载的文件解压缩到自己指定的目录 打开cmd命令窗口,并进入上面的目录 用anaconda安装好python3.7,...
  • python简单LK稀疏光流法运动目标检测
  • python画yolo目标检测的loss曲线和mAP曲线等
  • 检测骑自行车的人,随运动轨迹框出,适合刚接触运用opencv进行目标跟踪的编程爱好者参考
  • 该.py文件为基于vibe原理的目标检测Python代码。由于第一次写Python,程序运行比较慢,欢迎交流。 运行方式:将该文件和名称为video的avi文件放在同一个文件夹,然后运行即可。当然也可以在程序中修改待检测的视频...
  • 主要介绍了利用ImageAI库只需几行python代码超简实现目标检测功能,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 基于深度学习yolov5的目标检测算法 使用python flask实现web端实时目标检测与识别 web端目标检测与识别
  • 主要为大家详细介绍了Python Opencv任意形状目标检测,并绘制框图,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • python目标检测xml转txt

    千次阅读 2018-12-18 16:15:11
    转换之后的txt格式如下:可以根据 自己需要的格式调整,分别为图片名,坐标还有,类别 import os import sys import xml.etree.ElementTree as ET import glob ... annotations = os.listdir...
  • 主要介绍了python目标检测给图画框,bbox画到图上并保存案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 给出了三种运动目标检测的程序实现
  • 需求:检测出身份证的位置并判断身份证的旋转角度,根据角度和位置校正身份证。 训练样本是各个拍摄角度的身份证,由此可以将一张标注样本旋转三个角度(90,180,270),做数据增广。相应地,xml文件的坐标和label...
  • Python实战应用代码-python_opencv实时视频目标检测
  • 目标物体检测相关资源(论文/代码)大全

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 91,978
精华内容 36,791
关键字:

python简单的目标检测

python 订阅