torch实现yolov3(1)

torch实现yolov3(2)

torch实现yolov3(3)

torch实现yolov3(4)

前面4篇已经实现了network的forward,并且将network的output已经转换成了易于操作的detection prediction格式.

本篇把前面四篇实现的功能组织起来,实现端到端的推理过程.

整体流程如下

  1. 读取图片,对图片前处理,把图片调整到模型的input size及输入顺序(rgb c x h x w).
  2. 加载模型,读取模型权重文件.
  3. 将第一步读到的矩阵送给模型.进行forward运算.得到prediction
  4. 后处理,我们得到的box坐标是相对于调整后的图片的.要处理成原图上的坐标.

detector.py 实现完整的端到端的图片检测. 用法python detect.py --images dog-cycle-car.png --det det

from __future__ import division
import time
import torch
import torch.nn as nn
from torch.autograd import Variable
import numpy as np
import cv2
from util import *
import argparse
import os
import os.path as osp
from darknet import Darknet
import pickle as pkl
import pandas as pd
import random def arg_parse():
"""
Parse arguements to the detect module """ parser = argparse.ArgumentParser(description='YOLO v3 Detection Module') parser.add_argument("--images", dest = 'images', help =
"Image / Directory containing images to perform detection upon",
default = "imgs", type = str)
parser.add_argument("--det", dest = 'det', help =
"Image / Directory to store detections to",
default = "det", type = str)
parser.add_argument("--bs", dest = "bs", help = "Batch size", default = 1)
parser.add_argument("--confidence", dest = "confidence", help = "Object Confidence to filter predictions", default = 0.5)
parser.add_argument("--nms_thresh", dest = "nms_thresh", help = "NMS Threshhold", default = 0.4)
parser.add_argument("--cfg", dest = 'cfgfile', help =
"Config file",
default = "cfg/yolov3.cfg", type = str)
parser.add_argument("--weights", dest = 'weightsfile', help =
"weightsfile",
default = "yolov3.weights", type = str)
parser.add_argument("--reso", dest = 'reso', help =
"Input resolution of the network. Increase to increase accuracy. Decrease to increase speed",
default = "416", type = str) return parser.parse_args() args = arg_parse()
images = args.images
batch_size = int(args.bs)
confidence = float(args.confidence)
nms_thesh = float(args.nms_thresh)
start = 0
CUDA = torch.cuda.is_available() num_classes = 80
classes = load_classes("data/coco.names") #Set up the neural network
print("Loading network.....")
model = Darknet(args.cfgfile)
model.load_weights(args.weightsfile)
print("Network successfully loaded") model.net_info["height"] = args.reso
inp_dim = int(model.net_info["height"])
assert inp_dim % 32 == 0
assert inp_dim > 32 #If there's a GPU availible, put the model on GPU
if CUDA:
model.cuda() #Set the model in evaluation mode
model.eval() read_dir = time.time()
#Detection phase
try:
imlist = [osp.join(osp.realpath('.'), images, img) for img in os.listdir(images)]
except NotADirectoryError:
imlist = []
imlist.append(osp.join(osp.realpath('.'), images))
except FileNotFoundError:
print ("No file or directory with the name {}".format(images))
exit() if not os.path.exists(args.det):
os.makedirs(args.det) load_batch = time.time()
loaded_ims = [cv2.imread(x) for x in imlist] im_batches = list(map(prep_image, loaded_ims, [inp_dim for x in range(len(imlist))]))
im_dim_list = [(x.shape[1], x.shape[0]) for x in loaded_ims]
im_dim_list = torch.FloatTensor(im_dim_list).repeat(1,2) leftover = 0
if (len(im_dim_list) % batch_size):
leftover = 1 if batch_size != 1:
num_batches = len(imlist) // batch_size + leftover
im_batches = [torch.cat((im_batches[i*batch_size : min((i + 1)*batch_size,
len(im_batches))])) for i in range(num_batches)] write = 0 if CUDA:
im_dim_list = im_dim_list.cuda() start_det_loop = time.time()
for i, batch in enumerate(im_batches):
#load the image
start = time.time()
if CUDA:
batch = batch.cuda()
with torch.no_grad():
prediction = model(Variable(batch), CUDA) #类调用,相当于调用类的__call__()函数 prediction = write_results(prediction, confidence, num_classes, nms_conf = nms_thesh) end = time.time() if type(prediction) == int: for im_num, image in enumerate(imlist[i*batch_size: min((i + 1)*batch_size, len(imlist))]):
im_id = i*batch_size + im_num
print("{0:20s} predicted in {1:6.3f} seconds".format(image.split("/")[-1], (end - start)/batch_size))
print("{0:20s} {1:s}".format("Objects Detected:", ""))
print("----------------------------------------------------------")
continue prediction[:,0] += i*batch_size #transform the atribute from index in batch to index in imlist if not write: #If we have't initialised output
output = prediction
write = 1
else:
output = torch.cat((output,prediction)) for im_num, image in enumerate(imlist[i*batch_size: min((i + 1)*batch_size, len(imlist))]):
im_id = i*batch_size + im_num
objs = [classes[int(x[-1])] for x in output if int(x[0]) == im_id]
print("{0:20s} predicted in {1:6.3f} seconds".format(image.split("/")[-1], (end - start)/batch_size))
print("{0:20s} {1:s}".format("Objects Detected:", " ".join(objs)))
print("----------------------------------------------------------") if CUDA:
torch.cuda.synchronize()
try:
output
except NameError:
print ("No detections were made")
exit() im_dim_list = torch.index_select(im_dim_list, 0, output[:,0].long()) scaling_factor = torch.min(416/im_dim_list,1)[0].view(-1,1) output[:,[1,3]] -= (inp_dim - scaling_factor*im_dim_list[:,0].view(-1,1))/2
output[:,[2,4]] -= (inp_dim - scaling_factor*im_dim_list[:,1].view(-1,1))/2 output[:,1:5] /= scaling_factor for i in range(output.shape[0]):
output[i, [1,3]] = torch.clamp(output[i, [1,3]], 0.0, im_dim_list[i,0])
output[i, [2,4]] = torch.clamp(output[i, [2,4]], 0.0, im_dim_list[i,1]) output_recast = time.time()
class_load = time.time()
colors = pkl.load(open("pallete", "rb")) draw = time.time() def write(x, results):
c1 = tuple(x[1:3].int())
c2 = tuple(x[3:5].int())
img = results[int(x[0])]
cls = int(x[-1])
color = random.choice(colors)
label = "{0}".format(classes[cls])
cv2.rectangle(img, c1, c2,color, 1)
t_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_PLAIN, 1 , 1)[0]
c2 = c1[0] + t_size[0] + 3, c1[1] + t_size[1] + 4
cv2.rectangle(img, c1, c2,color, -1)
cv2.putText(img, label, (c1[0], c1[1] + t_size[1] + 4), cv2.FONT_HERSHEY_PLAIN, 1, [225,255,255], 1);
return img list(map(lambda x: write(x, loaded_ims), output)) det_names = pd.Series(imlist).apply(lambda x: "{}/det_{}".format(args.det,x.split("/")[-1])) list(map(cv2.imwrite, det_names, loaded_ims)) end = time.time() print("SUMMARY")
print("----------------------------------------------------------")
print("{:25s}: {}".format("Task", "Time Taken (in seconds)"))
print()
print("{:25s}: {:2.3f}".format("Reading addresses", load_batch - read_dir))
print("{:25s}: {:2.3f}".format("Loading batch", start_det_loop - load_batch))
print("{:25s}: {:2.3f}".format("Detection (" + str(len(imlist)) + " images)", output_recast - start_det_loop))
print("{:25s}: {:2.3f}".format("Output Processing", class_load - output_recast))
print("{:25s}: {:2.3f}".format("Drawing Boxes", end - draw))
print("{:25s}: {:2.3f}".format("Average time_per_img", (end - load_batch)/len(imlist)))
print("----------------------------------------------------------") torch.cuda.empty_cache()

第一段没啥好说的,我们希望可以通过命令行传参,所以用ArgParse模块来实现参数解析.

第二段 模型加载

#Set up the neural network
print("Loading network.....")
model = Darknet(args.cfgfile)
model.load_weights(args.weightsfile)
print("Network successfully loaded")

第三段 图像预处理

对任意一个图片,要先做预处理,把尺寸处理到model的input size.

read_dir = time.time()
#Detection phase
try:
imlist = [osp.join(osp.realpath('.'), images, img) for img in os.listdir(images)]
except NotADirectoryError:
imlist = []
imlist.append(osp.join(osp.realpath('.'), images))
except FileNotFoundError:
print ("No file or directory with the name {}".format(images))
exit() if not os.path.exists(args.det):
os.makedirs(args.det) load_batch = time.time()
loaded_ims = [cv2.imread(x) for x in imlist] im_batches = list(map(prep_image, loaded_ims, [inp_dim for x in range(len(imlist))]))
im_dim_list = [(x.shape[1], x.shape[0]) for x in loaded_ims]
im_dim_list = torch.FloatTensor(im_dim_list).repeat(1,2) leftover = 0
if (len(im_dim_list) % batch_size):
leftover = 1 if batch_size != 1:
num_batches = len(imlist) // batch_size + leftover
im_batches = [torch.cat((im_batches[i*batch_size : min((i + 1)*batch_size,
len(im_batches))])) for i in range(num_batches)]

从某个目录读入n多个图片.假设模型每个batch处理5个图片.图片为320 x 320 x 3. 则每次输入模型的矩阵为(320*5) x 320 x 3.即

im_batches = [torch.cat((im_batches[i*batch_size : min((i +  1)*batch_size,
len(im_batches))])) for i in range(num_batches)]

所做的事情.

图片的前处理所用到的一些工具函数如下.

def letterbox_image(img, inp_dim):
'''resize image with unchanged aspect ratio using padding'''
img_w, img_h = img.shape[1], img.shape[0]
w, h = inp_dim
new_w = int(img_w * min(w/img_w, h/img_h))
new_h = int(img_h * min(w/img_w, h/img_h))
resized_image = cv2.resize(img, (new_w,new_h), interpolation = cv2.INTER_CUBIC) canvas = np.full((inp_dim[1], inp_dim[0], 3), 128) canvas[(h-new_h)//2:(h-new_h)//2 + new_h,(w-new_w)//2:(w-new_w)//2 + new_w, :] = resized_image return canvas

保证原有图片的宽高比,其余位置灰度值填充.

cv读进来的bgr格式,我们转成rgb的.然后transpose 把h x w x c的转成c x h x w的.

def prep_image(img, inp_dim):
"""
Prepare image for inputting to the neural network. Returns a Variable
""" img = cv2.resize(img, (inp_dim, inp_dim
img = img[:,:,::-1].transpose((2,0,1)).copy()
img = torch.from_numpy(img).float().div(255.0).unsqueeze(0)
return img

参考https://www.cnblogs.com/sdu20112013/p/11216322.html

4.将矩阵喂给模型,进行forward

for i, batch in enumerate(im_batches):
#load the image
start = time.time()
if CUDA:
batch = batch.cuda()
with torch.no_grad():
prediction = model(Variable(batch), CUDA) #类调用,相当于调用类的__call__()函数 prediction = write_results(prediction, confidence, num_classes, nms_conf = nms_thesh) end = time.time() if type(prediction) == int: for im_num, image in enumerate(imlist[i*batch_size: min((i + 1)*batch_size, len(imlist))]):
im_id = i*batch_size + im_num
print("{0:20s} predicted in {1:6.3f} seconds".format(image.split("/")[-1], (end - start)/batch_size))
print("{0:20s} {1:s}".format("Objects Detected:", ""))
print("----------------------------------------------------------")
continue prediction[:,0] += i*batch_size #transform the atribute from index in batch to index in imlist if not write: #If we have't initialised output
output = prediction
write = 1
else:
output = torch.cat((output,prediction)) for im_num, image in enumerate(imlist[i*batch_size: min((i + 1)*batch_size, len(imlist))]):
im_id = i*batch_size + im_num
objs = [classes[int(x[-1])] for x in output if int(x[0]) == im_id]
print("{0:20s} predicted in {1:6.3f} seconds".format(image.split("/")[-1], (end - start)/batch_size))
print("{0:20s} {1:s}".format("Objects Detected:", " ".join(objs)))
print("----------------------------------------------------------")

其中重点就是

prediction = model(Variable(batch), CUDA) #类调用,相当于调用类的__call__()函数,

prediction = write_results(prediction, confidence, num_classes, nms_conf = nms_thesh)

涉及到一个python语法,类实例调用.其实就相当于调用__call__().基类nn.module的__call__()里调用了forward().所以这一句实际上就相当于调用model.forward(batch).

5.后处理

im_dim_list = torch.index_select(im_dim_list, 0, output[:,0].long())

scaling_factor = torch.min(416/im_dim_list,1)[0].view(-1,1)

output[:,[1,3]] -= (inp_dim - scaling_factor*im_dim_list[:,0].view(-1,1))/2
output[:,[2,4]] -= (inp_dim - scaling_factor*im_dim_list[:,1].view(-1,1))/2 output[:,1:5] /= scaling_factor for i in range(output.shape[0]):
output[i, [1,3]] = torch.clamp(output[i, [1,3]], 0.0, im_dim_list[i,0])
output[i, [2,4]] = torch.clamp(output[i, [2,4]], 0.0, im_dim_list[i,1])

output中的box坐标是相对于模型的输入图片的,将其映射到相对于原始图片的位置.

图片绘制,涉及python基础语法参考https://www.cnblogs.com/sdu20112013/p/11216584.html

list(map(lambda x: write(x, loaded_ims), output))

det_names = pd.Series(imlist).apply(lambda x: "{}/det_{}".format(args.det,x.split("/")[-1]))

list(map(cv2.imwrite, det_names, loaded_ims))

pytorch实现yolov3(5) 实现端到端的目标检测的更多相关文章

  1. Win10 + YOLOv3 环境配置,编译,实现目标检测----How to compile YOLOv3 on Windows

    其他比较好的参考链接: 环境配置: 环境配置的最终图片列表:https://blog.csdn.net/shanglianlm/article/details/80322718 视频讲解YOLOv1: ...

  2. 目标检测之车辆行人(darknet版yolov3)

    序言      自动驾驶是目前非常有前景的行业,而视觉感知作为自动驾驶中的“眼睛”,有着非常重要的地位和作用.为了能有效地识别到行驶在路上的动态目标,如汽车.行人等,我们需要提前对这些目标的进行训练, ...

  3. GPU端到端目标检测YOLOV3全过程(下)

    GPU端到端目标检测YOLOV3全过程(下) Ubuntu18.04系统下最新版GPU环境配置 安装显卡驱动 安装Cuda 10.0 安装cuDNN 1.安装显卡驱动 (1)这里采用的是PPA源的安装 ...

  4. GPU端到端目标检测YOLOV3全过程(上)

    GPU端到端目标检测YOLOV3全过程(上) Basic Parameters: Video: mp4, webM, avi Picture: jpg, png, gif, bmp Text: doc ...

  5. 从PyTorch到ONNX的端到端AlexNet

    从PyTorch到ONNX的端到端AlexNet 这是一个简单的脚本,可将Torchvision中定义的经过预训练的AlexNet导出到ONNX中.运行一轮推理Inference,然后将生成的跟踪模型 ...

  6. GPU端到端目标检测YOLOV3全过程(中)

    GPU端到端目标检测YOLOV3全过程(中)   计算机视觉初级部分知识体系                       总结了一下自己在计算机视觉初级部分的知识框架,整理如下.  个人所学并不全面( ...

  7. 【OCR技术系列之八】端到端不定长文本识别CRNN代码实现

    CRNN是OCR领域非常经典且被广泛使用的识别算法,其理论基础可以参考我上一篇文章,本文将着重讲解CRNN代码实现过程以及识别效果. 数据处理 利用图像处理技术我们手工大批量生成文字图像,一共360万 ...

  8. TVM:一个端到端的用于开发深度学习负载以适应多种硬件平台的IR栈

    TVM:一个端到端的用于开发深度学习负载以适应多种硬件平台的IR栈  本文对TVM的论文进行了翻译整理 深度学习如今无处不在且必不可少.这次创新部分得益于可扩展的深度学习系统,比如 TensorFlo ...

  9. 用TVM在硬件平台上部署深度学习工作负载的端到端 IR 堆栈

    用TVM在硬件平台上部署深度学习工作负载的端到端 IR 堆栈 深度学习已变得无处不在,不可或缺.这场革命的一部分是由可扩展的深度学习系统推动的,如滕索弗洛.MXNet.咖啡和皮托奇.大多数现有系统针对 ...

随机推荐

  1. 零元学Expression Blend 4 - Chapter 45 ListBox里的物件不能换行吗?

    原文:零元学Expression Blend 4 - Chapter 45 ListBox里的物件不能换行吗? ListBox里的排列不是垂直就是水平,觉得这样的排列很枯燥乏味吗? 想要它变聪明吗? ...

  2. JS 浮点加减乘除运算

    //浮点数加法运算 function FloatAdd(arg1,arg2){ var r1,r2,m; try{r1=arg1.toString().split(".")[1]. ...

  3. WPF与WinForm的抉择

    微软曾经对WPF(代号Avalon)抱很大的期望——新一代的华丽用户界面平台,一统Web应用和桌面应用,Flash杀手,尽管微软口头上不承认.几年下来,WPF确实实现了当初的预期的大部分功能,但离称霸 ...

  4. 全量导入数据 导致solr内存溢出 崩溃问题解决

    在 data-config.xml 文件中 增加一个参数即可: batchSize="-1"    

  5. 一、Linux常用命令

    1.ls 作用:列出文件信息,默认为当前目录下 语法: -a:列出所有的文件,包括以.开头的隐藏文件 -d:列出目录本身,并不包含目录中的文件 -h:和-l一起使用,文件大小人类易读 -l:长输出(“ ...

  6. 解决vuejs 创建数据后设置对象的属性实现不了双向绑定问题

    抛出踩坑:vue创建后的数据,自定义设置对象的属性,实现不了双向绑定 当业务场景,需要在请求接口数据新增自定义的属性 let foodList = [ {title: '回锅肉', price: 99 ...

  7. 设计模式之单例模式的几种写法——java

    对于设计模式的使用场景和好处,之前有介绍一篇,今天主要是单例模式的编写方式,直接看代码吧 单例模式之饿汉模式,不会懒加载.线程安全 /** * @Author wangtao * @Descripti ...

  8. 自定义vue全局组件use使用、vuex的使用

    自定义vue全局组件use使用(解释vue.use()的原理)我们在前面学习到是用别人的组件:Vue.use(VueRouter).Vue.use(Mint)等等.其实使用的这些都是全剧组件,这里我们 ...

  9. Java项目接入sso单点登录

    最近在落地cat(java开发的一款开源监控系统)接入公司的内部项目,其中有项需求是接入公司的sso单点登录系统.研究了公司之前java项目接入sso系统,大部分是采用spring框架,然后依赖spr ...

  10. Hadoop 学习之路(八)—— 基于ZooKeeper搭建Hadoop高可用集群

    一.高可用简介 Hadoop 高可用 (High Availability) 分为 HDFS 高可用和 YARN 高可用,两者的实现基本类似,但 HDFS NameNode 对数据存储及其一致性的要求 ...