【OpenCV】基于深度学习的对象检测

文章目录

  • 前言
  • 一、基于MobileNet_SSD和Caffe
  • 二、基于Yolo和Darknet
  • 总结


前言

对象检测是指检测出图像中的所有对象,并识别对象的类型。使用OpenCV中的深度学习预训练模型进行对象检测的基本步骤如下。

(1 )从配置文件和预训练模型文件中加载模型。
(2 )创建图像文件的块数据。
(3 )将图像文件的块数据设置为模型的输入。
(4)执行预测。
( 5)处理预测结果。

环境:群辉docker内安装好Anaconda和opencv4.5。运行容器,打开ip:8888,jupyter notebook运行程序。
其实只要正常的Python环境即可。


一、基于MobileNet_SSD和Caffe

import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
%matplotlib notebook
from PIL import ImageFont, ImageDraw, Image
#加载字体,以便显示汉字
fontpath = "STSONG.TTF"     
font = ImageFont.truetype(fontpath,20)         	    #载入字体,设置字号
font2 = {'family': 'STSONG', "size": 22}
matplotlib.rc('font', **font2)                      #设置plt字体
#准备对象名称类别,设置为中文
object_names = ('背景', '飞机', '自行车', '鸟', '船', '瓶子', '公共汽车',  '小汽车','猫', '椅子', '牛',  '餐桌',  '狗',  '马','摩托车','人','盆栽',  '羊', '沙发', '火车',  '监视器')
mode = cv2.dnn.readNetFromCaffe("MobileNetSSD_deploy.txt", "MobileNetSSD_Caffemodel.dat")

image = cv2.imread("obj.jpg")       #打开用于对象检测的图像
 #创建图像的块数据
blob = cv2.dnn.blobFromImage(image, 0.007843, (224,224),(120, 120, 127))      
mode.setInput(blob)                                         #将块数据设置为模型输入
result = mode.forward()                                     #执行预测
ptime, x = mode.getPerfProfile()         	                #获得完成预测时间
title='Prediction Time: %.2f ms' % (ptime * 1000.0 / cv2.getTickFrequency())

for i in range(result.shape[2]):            #处理检测结果
    confidence = result[0, 0, i, 2]         #获得可信度
    if confidence > 0.3:                    #输出可信度大于30%的检测结果  
        a,id,a,x1,y1,x2,y2=result[0, 0, i]  
        name_id = int(id)                   #获得类别名称id  
        blob_size=280
        heightScale = image.shape[0] / blob_size#计算原图像和图像块的高度比例
        widthScale = image.shape[1] / blob_size#计算原图像和图像块的宽度比例
        #计算检测出的对象的左下角和右上角坐标
        x1 = int(x1 * blob_size * widthScale)
        y1 = int(y1 * blob_size * heightScale)
        x2 = int(x2 * blob_size * widthScale)
        y2 = int(y2 * blob_size * heightScale)
        cv2.rectangle(image,(x1,y1),(x2,y2),(0,255,0),2)#绘制标识对象的绿色矩形
        #在图像中输出对象名称和可信度
        if name_id in range(len(object_names)):
            text = object_names[name_id] + "\n{:.1%}".format(confidence)
            img_pil = Image.fromarray(image)
            draw = ImageDraw.Draw(img_pil)
            draw.text((x1+5,y1), text, font = font,fill=(255,0,0))    #绘制文字
            image = np.array(img_pil)
img = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
plt.title(title)
plt.imshow(img)
plt.axis('off')
plt.show()

【OpenCV】基于深度学习的对象检测_第1张图片

二、基于Yolo和Darknet

import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
%matplotlib notebook
from PIL import ImageFont, ImageDraw, Image
#加载字体,以便显示汉字
fontpath = "STSONG.TTF"     
font = ImageFont.truetype(fontpath,20)         	    #载入字体,设置字号
font2 = {'family': 'STSONG', "size": 22}
matplotlib.rc('font', **font2)                      #设置plt字体

#从文件中加载已知的对象名称
f=open("object_names.txt",encoding='utf-8')#文件保存了80个类别的对象名称,每行一个
object_names = [r.strip() for r in f.readlines()]
f.close()
#从文件中加载预训练的Darknet模型
mode = cv2.dnn.readNetFromDarknet("yolov3.cfg", "yolov3.weights")
image = cv2.imread("obj.jpg")  #打开图像文件
imgH,imgW = image.shape[:2]
out_layers = mode.getLayerNames()  #获得输出层
out_layers = [out_layers[i[0] - 1] for i in mode.getUnconnectedOutLayers()]
#创建图像blob数据
blob = cv2.dnn.blobFromImage(image,1/255.0,(416,416),swapRB=True,crop=False)
mode.setInput(blob)                     #将图像blob数据设置为模型输入
layer_results = mode.forward(out_layers)#执行预测,返回每层的预测结果
ptime, _ = mode.getPerfProfile()
tilte_text='Prediction Time:%.2f ms' % (ptime*1000/cv2.getTickFrequency())
result_boxes = []
result_scores = []
result_name_id = []
for layer in layer_results: #遍历所有输出层
    for box in layer:#遍历层的所有输出预测结果,每个结果为一个边框
        #预测结果结构:x, y, w, h, confidence,80个类别的概率
        probs = box[5:]
        class_id = np.argmax(probs)     #找到概率最大的类别id
        prob = probs[class_id]          #找到最大的概率 
        if prob > 0.5:                  #筛选出概率大于50%的
            #计算每个box在原图像中的的绝对坐标
            box = box[0:4] * np.array([imgW, imgH, imgW, imgH])
            (centerX, centerY, width, height) = box.astype("int")
            x = int(centerX - (width / 2))
            y = int(centerY - (height / 2))
            result_boxes.append([x, y, int(width), int(height)])
            result_scores.append(float(prob))
            result_name_id.append(class_id)
#应用非最大值抑制消除重复边界框,获得要绘制的box
draw_boxes = cv2.dnn.NMSBoxes(result_boxes, result_scores, 0.6, 0.3)
if len(draw_boxes) > 0:
    for i in draw_boxes.ravel():
        #获得边框坐标
        (x, y) = (result_boxes[i][0], result_boxes[i][1])
        (w, h) = (result_boxes[i][2], result_boxes[i][3])
        #绘制边框
        cv2.rectangle(image,(x,y), (x+w,y+h),(0,255,0),1)
        #输出类别名称和可信度
        text=object_names[result_name_id[i]] +"\n{:.1%}".format(result_scores[i])
        img_pil = Image.fromarray(image)
        draw = ImageDraw.Draw(img_pil)
        draw.text((x+5,y), text, font = font,fill=(0,0,255))    #绘制文字
        image = np.array(img_pil)
img = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
plt.title(tilte_text)
plt.imshow(img)
plt.axis('off')
plt.show()

【OpenCV】基于深度学习的对象检测_第2张图片

效果比第一个好一些。


总结

相关文件在这里相关文件。

你可能感兴趣的:(OpenCV,python,opencv,yolo,darknet,caffe)