opencv调用yolo3

# coding:utf-8

import cv2
import argparseimport numpy as np

parser = argparse.ArgumentParser(description='manual to this script')
parser.add_argument("--videoOrImage", default=0)
args = parser.parse_args()

'''初始化参数'''
confThreshold = 0.25  # 置信度,忽略掉低于置信度阈值参数的所有框
nmsThreshold = 0.4  # 非极大抑制参数,对其余框执行非极大值抑制,这会消除多余的重叠边界框
inpWidth = 416
inpHeight = 416

modelConfiguration = r"C:\Users\Administrator\Desktop\darknet\cfg\yolov3.cfg";
modelWeights = r'C:\Users\Administrator\Desktop\darknet_weights\yolov3.weights';
classesFile = r"C:\Users\Administrator\Desktop\darknet\data\coco.names";
classes = None
'''
t是windows平台特有的所谓text mode(文本模式),区别在于会自动识别windows平台的换行符。类Unix平台的换行符是\n,
而windows平台用的是\r\n两个ASCII字符来表示换行,python内部采用的是\n来表示换行符。rt模式下,python在读取文本时会自动把\r\n转换成\n.
'''
with open(classesFile, 'rt') as f:
    classes = f.read().rstrip('\n').split('\n')

COLORS = np.random.randint(0, 255, size=(len(classes), 3), dtype='uint8')  # 颜色

#加载 网络配置与训练的权重文件 构建网络
net = cv2.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
cap = cv2.VideoCapture(args.videoOrImage)
cv2.namedWindow("win", cv2.WINDOW_NORMAL)
while cv2.waitKey(1) < 0:
    res, frame = cap.read()
    if not res:
        break

    '''
    从输入图像或视频流中读取帧后,将通过 blobFromImage 函数将其转换为神经网络的输入blob。在此过程中,
    它使用比例因子1/255 将图像像素值缩放到0到1的目标范围。它还将图像的大小缩放为给定的大小(416,416)而不进行裁剪。
    请注意,我们不在此处执行任何均值减法,因此将[0,0,0]传递给函数的mean参数,并将swapRB参数保持为其默认值1。
    '''
    blob = cv2.dnn.blobFromImage(frame, 1/255.0, (inpWidth, inpHeight), [0, 0, 0], swapRB=1, crop=False)

    '''
    然后输出blob作为输入传递到网络,并运行前向传递以获得预测边界框列表作为网络的输出。这些框经过后处理步骤,以滤除具有低置信度分数的那些框。
    '''
    net.setInput(blob)
    '''
    OpenCV 的 Net 类中的 forward 函数需要知道它的结束层。 想要遍历整个网络就需要识别网络的最后一层。 
    我们通过使用函数getUnconnectedOutLayers()来实现,该函数给出了未连接的输出层名称,这些输出层基本上是网络的最后一层。 
    然后我们运行网络的前向传递以从输出层获得输出
    '''
    layersNames = net.getLayerNames()  # ['conv_0', 'bn_0', 'relu_0', 'conv_1', 'bn_1', .......]
    '''
    net.getUnconnectedOutLayers():得到未连接层得序号 例如:[[200], [227]]
    i[0]-1  取out中的数字  [200][0]=200  layersNames(199)= 'yolo_82'
    '''
    outs = net.forward([layersNames[i[0] - 1] for i in net.getUnconnectedOutLayers()])  # net.forward(['conv_0', 'bn_0'])得到了所有输出结果的输出

    '''
    网络 outs 每个输出都由一组 类数目+5 个元素的向量表示。前4个元素代表center_x,center_y,width和height。 
    第五个元素表示边界框包围对象的置信度。其余元素是与每个类相关的置信度(即对象类型)。 该框被分配到与该框的最高分相对应的那一类。
    '''
    frameHeight = frame.shape[0]
    frameWidth = frame.shape[1]

    classIds = []
    confidences = []
    boxes = []

    for out in outs:
        for detection in out:  # detection的前五元素(中心坐标点以及长宽)[center_x,center_y,width,height,边界框包围对象的置信度,。。。。。。]
            scores = detection[5:]  # 所有元素的置信度
            classId = np.argmax(scores, axis=0)  # 取出最大置信度所对应的索引
            confidence = scores[classId]  # g根据索引取出最大的置信度
            if confidence > confThreshold:  # 判断当前的置信度是否大于设定的阈值
                center_x = int(detection[0] * frameWidth)
                center_y = int(detection[1] * frameHeight)
                width = int(detection[2] * frameWidth)
                height = int(detection[3] * frameHeight)
                left = int(center_x - width / 2)
                top = int(center_y - height / 2)
                classIds.append(classId)  # 将最大置信度的索引也就是类别的索引加入集合
                confidences.append(float(confidence))  # 将置信度加入集合
                boxes.append([left, top, width, height])  # 将坐标左上和长宽加入box

    '''
    对其置信度等于或大于阈值的框进行非极大值抑制。 这将会减少重叠框的数量。
    '''
    indices = cv2.dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold)

    for i in indices:
        i = i[0]
        box = boxes[i]
        left = box[0]
        top = box[1]
        width = box[2]
        height = box[3]
        color = [int(c) for c in COLORS[classIds[i]]]
        cv2.rectangle(frame, (left, top), (left + width, top + height), color, 2)
        text = "{}".format(classes[classIds[i]])
        cv2.putText(frame, text, (left, top - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
    cv2.imshow("win", frame)

 

posted @ 2019-09-08 14:32  AnswerThe  阅读(5029)  评论(0编辑  收藏  举报