darknet-yolov3中python接口中image传输w和h的过程
首先,python接口darknet.py中detect函数如下:
def detect(net, meta, image, thresh=.5, hier_thresh=.5, nms=.45):im = load_image(image, 0, 0)num = c_int(0)pnum = pointer(num)predict_image(net, im)dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, None, 0, pnum)num = pnum[0]if (nms): do_nms_obj(dets, num, meta.classes, nms);res = []for j in range(num):for i in range(meta.classes):if dets[j].prob[i] > 0:b = dets[j].bboxres.append((meta.names[i], dets[j].prob[i], (b.x, b.y, b.w, b.h)))res = sorted(res, key=lambda x: -x[1])free_image(im)free_detections(dets, num)return res
首先image传入后通过load_image()函数读取,load_image()函数导入见darknet.py中的lib,如下:
load_image = lib.load_image_color
load_image.argtypes = [c_char_p, c_int, c_int]
load_image.restype = IMAGE
具体通过编译好的libdarknet.so传入,首先市容load_image_color()函数,还函数位于src/image.c中,具体如下:
image load_image_color(char *filename, int w, int h)
{return load_image(filename, w, h, 3);
}
可以发现load_image_color()传入三个参数,除了image name外还有int w和int h,而在detect()中可以发现只传入了load_image(image, 0, 0),那么这个w=0和h=0该怎么算呢?继续往下看,发现调用了image.c中的load_image()函数,而该函数如下:
image load_image(char *filename, int w, int h, int c)
{
#ifdef OPENCVimage out = load_image_cv(filename, c);
#elseimage out = load_image_stb(filename, c);
#endifif((h && w) && (h != out.h || w != out.w)){image resized = resize_image(out, w, h);free_image(out);out = resized;}return out;
}
发现使用了opencv中的load_image_cv读取图像,而传入进来的h和w其实是在下面使用resize_image()操作对图片做了resize操作。至此发现darknet.py中的detect()使用的load_image(image, 0, 0)意思是只读入图片而不对其进行resize操作。那么load_image_cv读取到的图像返回三个值,即真实的image、image.w和image.h,这里即为out,然后返回至detect()中的im。紧接着,im传递给predict_image(net, im)函数进行预测,那么predic_image()我们下次再进行解读。那么真实的im.w和im.h(即图像的原始宽和高)被传递给dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, None, 0, pnum)函数,那么我们看一下此处的w和h到底起什么作用。get_network_boxes()函数在src/network.c中,函数如下:
detection *get_network_boxes(network *net, int w, int h, float thresh, float hier, int *map, int relative, int *num)
{detection *dets = make_network_boxes(net, thresh, num);fill_network_boxes(net, w, h, thresh, hier, map, relative, dets);return dets;
}
那么我们看到fill_network_boxes()使用了该函数,我们看明白了,在检测过程中并没有用到此处的w和h,那么这个原始图像的w和h干嘛用了呢?继续喊fill_network_boxes()函数,如下:
void fill_network_boxes(network *net, int w, int h, float thresh, float hier, int *map, int relative, detection *dets)
{int j;for(j = 0; j < net->n; ++j){layer l = net->layers[j];if(l.type == YOLO){ //yolov3int count = get_yolo_detections(l, w, h, net->w, net->h, thresh, map, relative, dets);dets += count;}if(l.type == REGION){ //yolov2get_region_detections(l, w, h, net->w, net->h, thresh, map, hier, relative, dets);dets += l.w*l.h*l.n;}if(l.type == DETECTION){ //yolov1get_detection_detections(l, w, h, thresh, dets);dets += l.w*l.h*l.n;}}
}
在yolov3中使用了get_yolo_detections()函数,并传入w和h,另外可以发现同时传入的还有net的w和h,net即是我们的yolov3网络,可以发现cfg中定义的w和h被一并传入至get_yolo_detections()中,继续看该函数(位于src/yolo_layer.c中):
int get_yolo_detections(layer l, int w, int h, int netw, int neth, float thresh, int *map, int relative, detection *dets)
{int i,j,n;float *predictions = l.output;if (l.batch == 2) avg_flipped_yolo(l);int count = 0;for (i = 0; i < l.w*l.h; ++i){int row = i / l.w;int col = i % l.w;for(n = 0; n < l.n; ++n){int obj_index = entry_index(l, 0, n*l.w*l.h + i, 4);float objectness = predictions[obj_index];if(objectness <= thresh) continue;int box_index = entry_index(l, 0, n*l.w*l.h + i, 0);dets[count].bbox = get_yolo_box(predictions, l.biases, l.mask[n], box_index, col, row, l.w, l.h, netw, neth, l.w*l.h);dets[count].objectness = objectness;dets[count].classes = l.classes;for(j = 0; j < l.classes; ++j){int class_index = entry_index(l, 0, n*l.w*l.h + i, 4 + 1 + j);float prob = objectness*predictions[class_index];dets[count].prob[j] = (prob > thresh) ? prob : 0;}++count;}}correct_yolo_boxes(dets, count, w, h, netw, neth, relative);return count;
}
可以发现我们的原始图像传入的w和h只被correct_yolo_boxes()函数使用,correct是准确的意思,顾名思义,该函数得到准确的yolo检测框,详细看该函数:
void correct_yolo_boxes(detection *dets, int n, int w, int h, int netw, int neth, int relative)
{int i;int new_w=0;int new_h=0;if (((float)netw/w) < ((float)neth/h)) {new_w = netw;new_h = (h * netw)/w;} else {new_h = neth;new_w = (w * neth)/h;}for (i = 0; i < n; ++i){box b = dets[i].bbox;b.x = (b.x - (netw - new_w)/2./netw) / ((float)new_w/netw); b.y = (b.y - (neth - new_h)/2./neth) / ((float)new_h/neth); b.w *= (float)netw/new_w;b.h *= (float)neth/new_h;if(!relative){b.x *= w;b.w *= w;b.y *= h;b.h *= h;}dets[i].bbox = b;}
}
可以看出,最终原始图像的w和h的作用是和cfg传入的net-w和h一起经过计算将预测出的原始boxes映射回对应于原图的boxes坐标。即比如net中测试图像的resize大小为608x608,则预测的初始boxes的坐标对应的是608x608的,而原图比如为1920x1080的,那么就需要原图的w和h传入进行映射计算得到最终的boxes坐标。所以,检测时进行的image resize操作应当位于未讲解的predic_image()函数中。
darknet-yolov3中python接口中image传输w和h的过程相关推荐
- darknet 框架中.cfg文件的参数详解,以yolov3为例
参考:darknet中cfg文件里参数的理解_zerojava0的博客-CSDN博客 参考:[Darknet源码 ]cfg文件参数详解_橘子都吃不起!的博客-CSDN博客 1.基础参数解释 batch ...
- YOLOV3中Darknet中cfg文件说明和理解
darknet 是由 C 和 CUDA 开发的,不需要配置其他深度学习的框架(如,tensorflow.caffe 等),支持 CPU 和 GPU 运算,而且安装过程非常简单. 1.cfg文件说明理解 ...
- AlexeyAB DarkNet YOLOv3框架解析与应用实践(二)
AlexeyAB DarkNet YOLOv3框架解析与应用实践(二) 版本3有什么新功能? YOLOv3使用了一些技巧来改进训练和提高性能,包括:多尺度预测.更好的主干分类器等等.全部细节都在我们的 ...
- alexeyab darknet 编译_【目标检测实战】Darknet—yolov3模型训练(VOC数据集)
原文发表在:语雀文档 0.前言 本文为Darknet框架下,利用官方VOC数据集的yolov3模型训练,训练环境为:Ubuntu18.04下的GPU训练,cuda版本10.0:cudnn版本7.6.5 ...
- 小白教程:Ubuntu下使用Darknet/YOLOV3训练自己的数据集
小白教程:Ubuntu下使用Darknet/YOLOV3训练自己的数据集 YOLOV3官网教程:https://pjreddie.com/darknet/yolo/ 使用预训练模型进行检测 git c ...
- AlexeyAB DarkNet YOLOv3框架解析与应用实践(六)
AlexeyAB DarkNet YOLOv3框架解析与应用实践(六) Tiny Darknet 听过很多人谈论SqueezeNet. SqueezeNet很酷,但它只是优化参数计数.当大多数高质量的 ...
- AlexeyAB DarkNet YOLOv3框架解析与应用实践(五)
AlexeyAB DarkNet YOLOv3框架解析与应用实践(五) RNNs in Darknet 递归神经网络是表示随时间变化的数据的强大模型.为了更好地介绍RNNs,我强烈推荐Andrej K ...
- AlexeyAB DarkNet YOLOv3框架解析与应用实践(四)
AlexeyAB DarkNet YOLOv3框架解析与应用实践(四) Nightmare 从前,在一所大学的大楼里,西蒙尼亚.维达第和齐瑟曼有一个很好的主意,几乎和你现在坐的大楼完全不同.他们想,嘿 ...
- AlexeyAB DarkNet YOLOv3框架解析与应用实践(三)
AlexeyAB DarkNet YOLOv3框架解析与应用实践(三) ImageNet分类 您可以使用Darknet为1000级ImageNet挑战赛分类图像.如果你还没有安装Darknet,你应该 ...
最新文章
- oracle 无备份恢复数据文件
- oracle biee
- centos7 mysql 5.5.27_centos7上安装mysql-5.7.27
- chrome inspect 远程调测:Chrome on Android之一 普通调试
- SyncBird Pro的PhoneCare功能如何使用
- mediaplay抓图
- TTC - Building a Better Vocabulary
- Linux完全卸载mysql数据库
- C语言自学——lesson4
- 波特率和比特率之间的关系
- 1.用 perf report 分析四个for进程
- 20200415 计算机的基础之host配置
- 苏宁易购为京东量身打造北京攻略
- Graph Representation Learning via Graphical Mutual Information Maximization
- 苹果手机没有备份怎么恢复照片?
- Java程序入门教程 | Java
- Python环境配置与数据处理
- 人工智能数学基础--导数3:隐函数求导、对数求导法、参数方程求导法
- js-day01-02
- 代码模块化和可读性的tradeoff
热门文章
- 使用python tkinter做window窗体界面程序,以及python多线程处理解决tk界面卡死
- 如何利用最少的钱,快速打开淘宝流量入口?
- mac安装chromedriver驱动详细步骤
- Java调用海康威视接口并抓取Jpeg图片到内存
- 光伏产业的机会 -- 光伏储能并网
- MIMO-OFDM无线通信技术及MATLAB实现PDF及其代码
- Vue和Vue-Element-Admin(七):把管理系统发布阿里云(公网)
- 2023,我们要走的路还有很长~
- 今天向大家介绍一个快应用开发辅助IDE插件——Troll For Ux
- 微信小程序调用腾讯地图,获取当前位置得到数据有偏差以及不同软件,不同坐标之间的转换Gcoord