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


前言

对象检测是指检测出图像中的所有对象,并识别对象的类型。使用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()

在这里插入图片描述

二、基于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()

在这里插入图片描述

效果比第一个好一些。


总结

相关文件在这里相关文件

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

粒子白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值