一、SSD用于图片物体的定位与检测
SSD原理介绍这一篇博客对我的帮助比较大,很详细的介绍了SSD原理,送给大家做了解
1、下载SSD框架源码
1.1:闲话不多说——下载SSD源码,解压后打开文件,将checkpoints
文件夹下的压缩包也解压出来,再在pycharm上建立工程,大体如下图所示:
1.2:打开demo
文件夹,这里就是用于外测的图片集
2、SSD做目标检测
在notebooks
文件夹下,建立demo_test.py
文件,在demo_test.py
文件内写入如下代码后,直接运行demo_test.py
(以下代码也是notebooks
文件夹ssd_tests.ipynb
内的代码,可以用notebook读取;我只是做了一些小改动)
# -\*- coding:utf-8 -\*-
# -\*- author:zzZ\_CMing CSDN address:https://blog.csdn.net/zzZ\_CMing
# -\*- 2018/07/14; 15:19
# -\*- python3.5
"""
address: https://blog.csdn.net/qq\_35608277/article/details/78660469
本文代码来自于github中微软官方仓库
"""
import os
import cv2
import math
import random
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib.cm as mpcm
import matplotlib.image as mpimg
from notebooks import visualization
from nets import ssd_vgg_300, ssd_common, np_methods
from preprocessing import ssd_vgg_preprocessing
import sys
# 当引用模块和运行的脚本不在同一个目录下,需在脚本开头添加如下代码:
sys.path.append('./SSD-Tensorflow/')
slim = tf.contrib.slim
# TensorFlow session
gpu_options = tf.GPUOptions(allow_growth=True)
config = tf.ConfigProto(log_device_placement=False, gpu_options=gpu_options)
isess = tf.InteractiveSession(config=config)
l_VOC_CLASS = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle',
'bus', 'car', 'cat', 'chair', 'cow',
'diningTable', 'dog', 'horse', 'motorbike', 'person',
'pottedPlant', 'sheep', 'sofa', 'train', 'TV']
# 定义数据格式,设置占位符
net_shape = (300, 300)
# 预处理,以Tensorflow backend, 将输入图片大小改成 300x300,作为下一步输入
img_input = tf.placeholder(tf.uint8, shape=(None, None, 3))
# 输入图像的通道排列形式,'NHWC'表示 [batch\_size,height,width,channel]
data_format = 'NHWC'
# 数据预处理,将img\_input输入的图像resize为300大小,labels\_pre,bboxes\_pre,bbox\_img待解析
image_pre, labels_pre, bboxes_pre, bbox_img = ssd_vgg_preprocessing.preprocess_for_eval(
img_input, None, None, net_shape, data_format,
resize=ssd_vgg_preprocessing.Resize.WARP_RESIZE)
# 拓展为4维变量用于输入
image_4d = tf.expand_dims(image_pre, 0)
# 定义SSD模型
# 是否复用,目前我们没有在训练所以为None
reuse = True if 'ssd\_net' in locals() else None
# 调出基于VGG神经网络的SSD模型对象,注意这是一个自定义类对象
ssd_net = ssd_vgg_300.SSDNet()
# 得到预测类和预测坐标的Tensor对象,这两个就是神经网络模型的计算流程
with slim.arg_scope(ssd_net.arg_scope(data_format=data_format)):
predictions, localisations, _, _ = ssd_net.net(image_4d, is_training=False, reuse=reuse)
# 导入官方给出的 SSD 模型参数
ckpt_filename = '../checkpoints/ssd\_300\_vgg.ckpt'
# ckpt\_filename = '../checkpoints/VGG\_VOC0712\_SSD\_300x300\_ft\_iter\_120000.ckpt'
isess.run(tf.global_variables_initializer())
saver = tf.train.Saver()
saver.restore(isess, ckpt_filename)
# 在网络模型结构中,提取搜索网格的位置
# 根据模型超参数,得到每个特征层(这里用了6个特征层,分别是4,7,8,9,10,11)的anchors\_boxes
ssd_anchors = ssd_net.anchors(net_shape)
"""
每层的anchors\_boxes包含4个arrayList,前两个List分别是该特征层下x,y坐标轴对于原图(300x300)大小的映射
第三,四个List为anchor\_box的长度和宽度,同样是经过归一化映射的,根据每个特征层box数量的不同,这两个List元素
个数会变化。其中,长宽的值根据超参数anchor\_sizes和anchor\_ratios制定。
"""
# 加载辅助作图函数
def colors\_subselect(colors, num_classes=21):
dt = len(colors) // num_classes
sub_colors = []
for i in range(num_classes):
color = colors[i \* dt]
if isinstance(color[0], float):
sub_colors.append([int(c \* 255) for c in color])
else:
sub_colors.append([c for c in color])
return sub_colors
def bboxes\_draw\_on\_img(img, classes, scores, bboxes, colors, thickness=2):
shape = img.shape
for i in range(bboxes.shape[0]):
bbox = bboxes[i]
color = colors[classes[i]]
# Draw bounding box...
p1 = (int(bbox[0] \* shape[0]), int(bbox[1] \* shape[1]))
p2 = (int(bbox[2] \* shape[0]), int(bbox[3] \* shape[1]))
cv2.rectangle(img, p1[::-1], p2[::-1], color, thickness)
# Draw text...
s = '%s/%.3f' % (l_VOC_CLASS[int(classes[i]) - 1], scores[i])
p1 = (p1[0] - 5, p1[1])
# cv2.putText(img, s, p1[::-1], cv2.FONT\_HERSHEY\_DUPLEX, 1.5, color, 3)
colors_plasma = colors_subselect(mpcm.plasma.colors, num_classes=21)
# 主流程函数
def process\_image(img, case, select_threshold=0.15, nms_threshold=.1, net_shape=(300, 300)):
# select\_threshold:box阈值——每个像素的box分类预测数据的得分会与box阈值比较,高于一个box阈值则认为这个box成功框到了一个对象
# nms\_threshold:重合度阈值——同一对象的两个框的重合度高于该阈值,则运行下面去重函数
# 执行SSD模型,得到4维输入变量,分类预测,坐标预测,rbbox\_img参数为最大检测范围,本文固定为[0,0,1,1]即全图
rimg, rpredictions, rlocalisations, rbbox_img = isess.run([image_4d, predictions,
localisations, bbox_img], feed_dict={img_input: img})
# ssd\_bboxes\_select()函数根据每个特征层的分类预测分数,归一化后的映射坐标,
# ancohor\_box的大小,通过设定一个阈值计算得到每个特征层检测到的对象以及其分类和坐标
rclasses, rscores, rbboxes = np_methods.ssd_bboxes_select(rpredictions, rlocalisations, ssd_anchors,
select_threshold=select_threshold,
img_shape=net_shape,
num_classes=21, decode=True)
"""
这个函数做的事情比较多,这里说的细致一些:
首先是输入,输入的数据为每个特征层(一共6个,见上文)的:
rpredictions: 分类预测数据,
rlocalisations: 坐标预测数据,
ssd\_anchors: anchors\_box数据
其中:
分类预测数据为当前特征层中每个像素的每个box的分类预测
坐标预测数据为当前特征层中每个像素的每个box的坐标预测
anchors\_box数据为当前特征层中每个像素的每个box的修正数据
函数根据坐标预测数据和anchors\_box数据,计算得到每个像素的每个box的中心和长宽,这个中心坐标和长宽会根据一个算法进行些许的修正,
从而得到一个更加准确的box坐标;修正的算法会在后文中详细解释,如果只是为了理解算法流程也可以不必深究这个,因为这个修正算法属于经验算
法,并没有太多逻辑可循。
修正完box和中心后,函数会计算每个像素的每个box的分类预测数据的得分,当这个分数高于一个阈值(这里是0.5)则认为这个box成功
框到了一个对象,然后将这个box的坐标数据,所属分类和分类得分导出,从而得到:
rclasses:所属分类
rscores:分类得分
rbboxes:坐标
最后要注意的是,同一个目标可能会在不同的特征层都被检测到,并且他们的box坐标会有些许不同,这里并没有去掉重复的目标,而是在下文
中专门用了一个函数来去重
"""
# 检测有没有超出检测边缘
rbboxes = np_methods.bboxes_clip(rbbox_img, rbboxes)
rclasses, rscores, rbboxes = np_methods.bboxes_sort(rclasses, rscores, rbboxes, top_k=400)
# 去重,将重复检测到的目标去掉
rclasses, rscores, rbboxes = np_methods.bboxes_nms(rclasses, rscores, rbboxes, nms_threshold=nms_threshold)
# 将box的坐标重新映射到原图上(上文所有的坐标都进行了归一化,所以要逆操作一次)
rbboxes = np_methods.bboxes_resize(rbbox_img, rbboxes)
if case == 1:
bboxes_draw_on_img(img, rclasses, rscores, rbboxes, colors_plasma, thickness=8)
return img
else:
return rclasses, rscores, rbboxes
"""
# 只做目标定位,不做预测分析
case = 1
img = cv2.imread("../demo/person.jpg")
img = cv2.cvtColor(img, cv2.COLOR\_BGR2RGB)
plt.imshow(process\_image(img, case))
plt.show()
"""
# 做目标定位,同时做预测分析
case = 2
path = '../demo/person.jpg'
# 读取图片
img = mpimg.imread(path)
# 执行主流程函数
rclasses, rscores, rbboxes = process_image(img, case)
# visualization.bboxes\_draw\_on\_img(img, rclasses, rscores, rbboxes, visualization.colors\_plasma)
# 显示分类结果图
visualization.plt_bboxes(img, rclasses, rscores, rbboxes), rscores, rbboxes
3、SSD目标检测结果
会得到如下图示,如图已经成功的把物体标注出来,每个标记框中前一个数是标签项,后一个是预测的准确率;
# 标签项与其对应的标签内容
dict = {1:'aeroplane', 2:'bicycle', 3:'bird', 4:'boat', 5:'bottle',
6:'bus', 7:'car', 8:'cat', 9:'chair', 10:'cow',
11:'diningTable', 12:'dog', 13:'horse', 14:'motorbike', 15:'person',
16:'pottedPlant', 17:'sheep', 18:'sofa', 19:'train', 20:'TV'}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Linux运维工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Linux运维知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加VX:vip1024b (备注Linux运维获取)
最后的话
最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!
资料预览
给大家整理的视频资料:
给大家整理的电子书资料:
如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
序员的圈子,让我们一起学习成长!**](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算