坐标转换,iou计算,权重加载,图片显示

一、坐标转换

1、分析

2、实现

# =====================================坐标值转化函数==========================================================
# 定义函数:将中心点、高、宽坐标 转化为[x0, y0, x1, y1]坐标形式
# 将anchor的中心点坐标表示形式转化为左上右下坐标表示形式
def detections_boxes(detections):''':param detections: YOLO检测层的输出 形状 (1, 10647, 5+num_anchor):return:将anchor的中心点坐标表示形式转化为左上右下坐标表示形式的所有anchor 形状 (1, 10647, 5+num_anchor)'''# 将detections (1, 10647, 5+num_class) 切分为(1, 10647, 1)、(1, 10647, 1)、(1, 10647, 1)、(1, 10647, 1)、(1, 10647, num_class+1)center_x, center_y, width, height, attrs = tf.split(detections, [1, 1, 1, 1, -1], axis=-1)w2 = width / 2                  # 二分之1宽h2 = height / 2                 # 二分之1高x0 = center_x - w2              # anchor左上角 x 值y0 = center_y - h2              # anchor左上角 y 值x1 = center_x + w2              # anchor右下角 x 值y1 = center_y + h2              # anchor右下角 y 值# 将坐标值放到一起 一列是一个anchor的左上右下坐标值boxes = tf.concat([x0, y0, x1, y1], axis=-1)# 再组合回去 detections 形状 (1, 10647, 5+num_anchor)detections = tf.concat([boxes, attrs], axis=-1)return detections

二、IOU计算函数

1、分析

2、实现

# =====================================IOU计算函数==========================================================
#定义函数计算两个框的内部重叠情况(IOU)box1,box2为左上、右下的坐标[x0, y0, x1, x2]
# 计算两个anchor的IOU值
def _iou(box1, box2):''':param box1: 第一个anchor的左上右下坐标,形如[x0, y0, x1, y1]:param box2: 第二个anchor的左上右下坐标,形如[x0, y0, x1, y1]:return: 两个anchor的IOU值'''# 获取具体坐标值b1_x0, b1_y0, b1_x1, b1_y1 = box1b2_x0, b2_y0, b2_x1, b2_y1 = box2# 计算两个anchor重叠部分的坐标# 前两行的较大的值的组合是属于两个anchor重叠部分的右上角的坐标# 后两行的较小的值的组合是属于两个anchor重叠部分的左下角的坐标int_x0 = max(b1_x0, b2_x0)int_y0 = max(b1_y0, b2_y0)int_x1 = min(b1_x1, b2_x1)int_y1 = min(b1_y1, b2_y1)# 计算anchor重叠的面积int_area = (int_x1 - int_x0) * (int_y1 - int_y0)# 分别计算两个anchor的面积b1_area = (b1_x1 - b1_x0) * (b1_y1 - b1_y0)b2_area = (b2_x1 - b2_x0) * (b2_y1 - b2_y0)# 计算两个anchor的IOU值,两个anchor的交集面积除以两个anchor并集的面积#分母加个1e-05,避免除数为 0iou = int_area / (b1_area + b2_area - int_area + 1e-05)return iou

三、非极大值抑制函数

1、分析

2、实现

# ====================================================== 使用非极大值抑制(NMS)方法,对结果去重===================================================
def non_max_suppression(predictions_with_boxes, confidence_threshold, iou_threshold=0.4):''':param predictions_with_boxes: YOLO检测层的输出经过detections_boxes处理之后。 形如 [1, 10647, 5+num_anchor]:param confidence_threshold: 置信度阈值:param iou_threshold: iou阈值:return:同一类别中,相距比较远的anchor。'''# predictions_with_boxes[:, :, 4] 是获取到predictions_with_boxes中的confidence值,形状类似为 [1,10647]# predictions_with_boxes[:, :, 4] > confidence_threshold 判断所有anchor的confidence值是否大于confidence_threshold,返回true或者false 形状类似为 [1,10647]# np.expand_dims((predictions_with_boxes[:, :, 4] > confidence_threshold), -1) 将形状[1,10647] 在最后一个维度增加一个维度 形状变成[1,10647,1]# conf_mask = [[[False],[ True],...,[ True]]] 形状[1,10647,1]conf_mask = np.expand_dims((predictions_with_boxes[:, :, 4] > confidence_threshold), -1)# 利用conf_mask值将predictions_with_boxes中小于confidence_threshold的值的confidence变成0(实际上一行数据全变成0了)  原理 True*数值 = 原数值 False*数值 = 0# 满足置信度条件的anchor的预测值不变,不满足置信度条件的anchor的预测值全变成0# predictions_with_boxes的形状为[1,10647,5+c]# predictions 的形状为[1,10647,5+c]   只是不满足置信度条件的anchor的预测值全变成0predictions = predictions_with_boxes * conf_mask  # 矩阵对应值相乘result = {}  # 定义键值对备用for i, image_pred in enumerate(predictions):  # 遍历置信度处理后的prediction 形状为 [1,10647,5+c] 其中5是左上坐标x0 y0 右下坐标x1 y1 置信度confidence c是分类数shape = image_pred.shape                  # 获取prediction中每一个元素的形状print("shape1",shape)                     # 形状[10647,5+c]non_zero_idxs = np.nonzero(image_pred)    # 返回非0元素下标 这是所有维度的组合坐标  我们只需要第一个维度非0值的坐标unique_idxs = list(set(non_zero_idxs[0])) # 得到第一个维度非0值的坐标image_pred = image_pred[unique_idxs]      # 获取非0元素下标的预测值 形状[满足置信度条件的anchor个数,5+c]print("shape2",image_pred.shape)          # 形状[满足置信度条件的anchor个数,5+c]image_pred = image_pred.reshape(-1, shape[-1]) # 形状[满足置信度条件的anchor个数,5+c]bbox_attrs = image_pred[:, :5]            # 满足置信度条件的预测值的前5个预测值:位置和置信度预测值  形状[满足置信度条件的anchor个数,5]classes = image_pred[:, 5:]               # 满足置信度条件的预测值的前5个以后预测值:分类预测值      形状[满足置信度条件的anchor个数,c]classes = np.argmax(classes, axis=-1)     # 获取满足置信度条件的分类预测值的预测编号               形状[满足置信度条件的anchor个数,] 1维unique_classes = list(set(classes.reshape(-1)))  # 去重 获得该图片中的分类种类                   形状[该图片中的分类种类数,]1维for cls in unique_classes:    # 遍历该图片中的每一种类别# 判断classes中每个元素是否等于cls,元素等于是True不等是Falsecls_mask = classes == cls # 判断class中属于当前分类 cls类有哪些元素,True代表属于,False代表不属于  返回cls_mask 内容类似于[False  True False ... True False]# np.nonzero(cls_mask) 返回cls_mask中的非0的元素的下标# 根据下标找到同一类的所有anchor。形状[满足置信度条件的属于同一类别的anchor个数,5] 5 左上右下坐标+置信度cls_boxes = bbox_attrs[np.nonzero(cls_mask)]  # cls_boxes形状[满足置信度条件的属于同一类别的anchor个数,5]cls_boxes = cls_boxes[cls_boxes[:, -1].argsort()[::-1]] # 将同一类别的anchor按照置信度的大小排序。由大到小 形状[满足置信度条件的属于同一类别的anchor个数,5]cls_scores = cls_boxes[:, -1]           # 获取同一类别的anchor的置信度[满足置信度条件的属于同一类别的anchor个数,1] 同一类anchor置信度排序后的置信度cls_boxes = cls_boxes[:, :-1]           # 获取同一类别的anchor的置信度[满足置信度条件的属于同一类别的anchor个数,4]同一类anchor置信度排序后的anchor左上右下坐标while len(cls_boxes) > 0:               # 终止条件cls_boxes中没有元素了box = cls_boxes[0]                  # 由于cls_boxes存放的是同一类anchor置信度排序后的anchor左上右下坐标,所以cls_boxes[0]代表的是置信度最大的anchorscore = cls_scores[0]               # 获取最大置信度anchor的置信度值if not cls in result:               # 如果该分类不在键值对result中,则生成以该分类为键,以列表为值的键值对result[cls] = []result[cls].append((box, score))    # 将最大置信度anchor的坐标值,和置信度值添加到以该分类为键,以列表为值的列表中cls_boxes = cls_boxes[1:]           # 用列表存放除了最大置信度anchor之外的所有anchorious = np.array([_iou(box, x) for x in cls_boxes])  # 由最大置信度anchor依次与除了最大置信度anchor之外的所有anchor一个个的做IOU计算,计算结果存放到ious中,计算顺序是按照置信度大小的顺序iou_mask = ious < iou_threshold                     # 找到上一步计算的iou值列表中那些元素小于IOU阈值cls_boxes = cls_boxes[np.nonzero(iou_mask)]         # 找到iou列表中小于等于iou阈值的所有元素的下标,并根据下标找到对应的anchor,其顺序依然是按照置信度大小由大到小排列的cls_scores = cls_scores[np.nonzero(iou_mask)]       # 找到iou列表中小于等于iou阈值的所有元素的下标,并根据下标找到对应的anchor,其顺序依然是按照置信度大小由大到小排列的# 接着找最大最大置信度anchor,与余下的anchor接着做iou计算重复while的内容,最终保留同一类别中,相距比较远的anchor。return result

四、结果显示

即将检测结果显示在图片上

1、分析

2、实现

# 将检测结果显示在图片上
def draw_boxes(boxes, img, cls_names, detection_size):''':param boxes: 非极大值抑制后的anchor框 形如{0: [(array([16., 30., 35., 45.]), 0.5)], 2: [(array([ 5.,  8., 15., 14.]), 0.7)], 3: [(array([43., 53., 65., 65.]), 0.6), (array([15., 18., 25., 24.]), 0.6)], 4: [(array([27., 25., 37., 28.]), 0.5)]}:param img:  输入到网络的原图片:param cls_names: 分类编号和分类名称对应的字典:param detection_size: 输入到网络的原图片统一调整后的大小 这里是416:return: 在原图上画好框标好分类的原图片'''draw = ImageDraw.Draw(img)  # 创建一个可以在给定图像(img)上绘图的对象for cls, bboxs in boxes.items(): # 遍历键值对的键和值  键cls表示分类  值bboxs表示坐标+置信度 形状[2],即[(4个坐标值),(1个置信度)]color = tuple(np.random.randint(0, 256, 3)) # 产生代表随机颜色随机数for box, score in bboxs:    # 遍历坐标和置信度box = convert_to_original_size(box, np.array(detection_size), np.array(img.size))  # 从416*416大小图片上还原到原始图片大小draw.rectangle(box, outline=color)  # 依据坐标点和随机颜色画出相应的anchordraw.text(box[:2], '{} {:.2f}%'.format(cls_names[cls], score * 100), fill=color) # 在框的左上角写上分类名称和置信度print('{} {:.2f}%'.format(cls_names[cls], score * 100),box[:2])def convert_to_original_size(box, size, original_size): # 从416*416大小图片上还原到原始图片大小''':param box: 基于416*416图片上的anchor坐标 形如[16., 30., 35., 45.] 左上右下坐标:param size: 预测时所有图片统一后的大小 这里是416:param original_size: 没有统一大小时的原图片的大小:return: 返回基于416*416图片上的anchor坐标还原到没有统一大小时的原图片的大小上的坐标,即等比例缩放'''ratio = original_size / size    # 缩放比例box = box.reshape(2, 2) * ratio # 根据缩放比例进行缩放坐标return list(box.reshape(-1))    # 将缩放后的坐标变成 一行数据 即维度为1的列表

五、权重加载

1、实现

def load_weights(var_list, weights_file):''':param var_list: 变量名称列表:param weights_file: 二进制基于coco训练的基于darknet53的yolov3权重:return: 权重op'''# 以读二进制的方式打开文件# np.fromfile(frame, dtype=float, count=‐1, sep='')#     frame : 文件、字符串#     dtype : 读取的数据类型#     count : 读入元素个数,‐1表示读入整个文件 5表示读取前5个int32#     sep : 数据分割字符串,如果是空串,写入文件为二进制with open(weights_file, "rb") as fp:# 读取前5个int32,不要,前5个int32是标题信息_ = np.fromfile(fp, dtype=np.int32, count=5)  # 跳过前5个int32# 接着读取最后的所有float32,存入weights列表中weights = np.fromfile(fp, dtype=np.float32)ptr = 0i = 0 # 计数变量assign_ops = []while i < len(var_list) - 1:    # 遍历变量列表var1 = var_list[i]          # 从变量列表中获取第一个变量var2 = var_list[i + 1]      # 从变量列表中获取第二个变量# 到卷积项if 'Conv' in var1.name.split('/')[-2]: # 按'/'分割var1.name,然后返回倒数第二个元素,并判断'Conv'是否在返回的元素中# 找到BN参数项if 'BatchNorm' in var2.name.split('/')[-2]:# 按'/'分割var1.name,然后返回倒数第二个元素,并判断'BatchNorm'是否在返回的元素中# 加载批量归一化参数gamma, beta, mean, var = var_list[i + 1:i + 5] # 从变量列表中获取BN参数batch_norm_vars = [beta, gamma, mean, var]      # 将BN参数放到一个列表中for var in batch_norm_vars:shape = var.shape.as_list()num_params = np.prod(shape)var_weights = weights[ptr:ptr + num_params].reshape(shape)ptr += num_paramsassign_ops.append(tf.assign(var, var_weights, validate_shape=True))i += 4#已经加载了4个变量,指针移动4elif 'Conv' in var2.name.split('/')[-2]:bias = var2bias_shape = bias.shape.as_list()bias_params = np.prod(bias_shape)bias_weights = weights[ptr:ptr + bias_params].reshape(bias_shape)ptr += bias_paramsassign_ops.append(tf.assign(bias, bias_weights, validate_shape=True))i += 1#移动指针shape = var1.shape.as_list()num_params = np.prod(shape)#加载权重var_weights = weights[ptr:ptr + num_params].reshape((shape[3], shape[2], shape[0], shape[1]))var_weights = np.transpose(var_weights, (2, 3, 1, 0))ptr += num_paramsassign_ops.append(tf.assign(var1, var_weights, validate_shape=True))i += 1return assign_ops

yolov3前向传播(三)-- 坐标转换,iou计算,权重加载,图片显示相关推荐

  1. 学以致用三十四-----python2.0加载图片

    想用做一个静态图片为背景的页面.结果遇到了一些阻碍.其主要原因还是路径没有找对.网上也参考了不少方法,也许是因为版本不同,处理的方法也不同,因此按照网上的处理方式,也没有得到解决. 为此困惑了一天.结 ...

  2. 前后端传图片用base64好吗_Base64是什么?前端用Base64加载图片到底好不好?

    相信无论是前端还是后端开发工程师,对于Base64都不会感到陌生,在开发中我们经常会将一些小图片以Base64的形式存储和加载.然而知其然也要知其所以然,Base64究竟是什么,我们为什么要使用Bas ...

  3. Android简易实战教程--第三十二话《使用Lrucache和NetworkImageView加载图片》

    转载本专栏每一篇博客请注明转载出处地址,尊重原创.此博客转载链接地址:小杨的博客    http://blog.csdn.net/qq_32059827/article/details/5279131 ...

  4. android开发学习之路——连连看之加载图片(三)

    正如前面AbstractBoard类的代码中看到的,当程序需要创建N个Piece对象时,程序会直接调用ImageUtil的getPlayImages()方法去获取图片,该方法将会随机从res\ dra ...

  5. 【C++的OpenCV】第三课-OpenCV图像加载和显示

    我们开始学习OpenCV 一.OpenCV加载图片和显示图片 1.1 imread()函数的介绍 1.2 cv::namedWindow()函数的介绍 1.4 imshow()函数介绍 1.5 Mat ...

  6. yolov3前向传播(二)-- yolov3相关模块的解析与实现(一)

    yolov3检测块的解析与实现 在yolo v3模型中,检测部分的模型是由yolo检测块.yolo检测层以及上采样函数组成. yolo检测块负责进一步提取特征: 检测层负责将最终特征转化为bbox a ...

  7. yolov3前向传播(二)-- yolov3相关模块的解析与实现(二)

    yolov3相关模块的解析与实现(二) 接上一篇 三.上采样函数 作用:用于将特征图扩展到想要的尺寸大小,和其他特征叠加到一起使用. 上采样的方法为近邻差值法 上采样函数的实现 # 定义上采样函数 d ...

  8. ignite mysql_apache ignite系列(三):数据处理(数据加载,数据并置,数据查询)

    ​使用ignite的一个常见思路就是将现有的关系型数据库中的数据导入到ignite中,然后直接使用ignite中的数据,相当于将ignite作为一个缓存服务,当然ignite的功能远不止于此,下面以将 ...

  9. 页面加载图片前用空态图代替真正图片

    这里简单说一下,用空太图来代替原始的图片.一般情况了,在图片加载前有 好几种方式: 比如: 1-图片懒加载, 2-图片预加载, 3-背景图代替, 4-空态图代替. 这里讲解一下空态图的方式: **CS ...

最新文章

  1. 全面访问JavaScript的最佳资源
  2. 以太网交换机与路由—Vecloud微云
  3. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) A. Bear and Game 水题
  4. 对linux内核学习的一点感受,对linux内核学习的一点感受
  5. photoshop图像滤镜——素描算法(含matlab与C代码)
  6. php mysql书城_php在线书城 thinkphp源码(含数据库脚本)
  7. Notepad++中用正则表达式匹配中文
  8. 微软更新服务器win7,[技巧]绕过微软限制:让基于新处理器的Win7/8.1系统继续接收更新...
  9. 重构:改善既有代码的设计(评注版) 评注者序
  10. 2011年度最佳代码“不管你们信不信,我反正信了”
  11. 树:二叉树的内存拷贝和内存释放
  12. 基于JAVA+Servlet+JSP+MYSQL的人力资源管理系统
  13. python处理excel表格-Python利用pandas处理Excel数据的应用
  14. oracle11g 卸载步骤
  15. 认真与随便,结果有天壤之别
  16. 190815每日一句
  17. C# Winform 自动更新程序实例
  18. 永恒之蓝--Windows server 2003R2
  19. 百度地图API获取公交路线及站点数据
  20. phpStrom连接MySQL数据库

热门文章

  1. pytorch_pix2pix之argparse
  2. Java 绘制艺术图案
  3. kite:Python 代码自动补全神器
  4. antd table动态表头_react动态配置antd table的columns
  5. git clone 拉取github上面的代码报错:fatal: Authentication failed for xxx解决
  6. 关于打开sdk下载不了的最优秀解决方式
  7. 适配iOS10以及Xcode8
  8. 连接Oracle9i,因字符集造成乱码的解决方法
  9. nginx apache mysql php 常用编译参数
  10. 关于sliverlight4 打印功能