点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

本文转自|新机器视觉

封面图片:Photo by Daniel Stone on Unsplash


今早在GitHub上收到一则issue,发信人为Suaro。

Suaro希望使用OpenCV来实现模型加载与推演,但是没有成功,因此开了issue寻求我的帮助。

现场围观该Issue:

https://github.com/yinguobing/facial-landmark-detection-hrnet/issues/3

说实话这个功能并没有在我最初的考虑范围内。该项目所遵守的开源协议意味着我没有义务去解决这个问题。但是,Suaro提issue的方式在我看来是非常值得赞许与推广的。所以,我不仅帮TA解决了issue,还要以此为样本,与大家分享下一些提issue时的注意事项。

首先,我们先解决OpenCV加载模型的问题。

使用OpenCV加载模型

OpenCV在3.0的版本时引入了一个dnn模块,实现了一些基本的神经网络模型layer。在最新的4.5版本中,dnn模块使用函数 readNet 实现模型加载。不过根据官方解释,OpenCV不支持TensorFlow所推荐的模型保存格式 saved_model 。所以在加载模型之前,模型需要首先被冻结。

冻结网络

在之前的文章“TensorFlow如何冻结网络模型”中介绍过了冻结网络的具体含义以及原理。但是在TensorFlow2中网络冻结似乎被弃用了,文中提到的冻结脚本也无法使用。幸运的是,网络冻结的原理仍然有效,而且OpenCV作者提供了一小段示例样本展示了冻结网络的方法如下:

import tensorflow as tf
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2
# Load the model from saved_model.
loaded = tf.saved_model.load('my_model')
infer = loaded.signatures['serving_default']
f = tf.function(infer).get_concrete_function(input_1=tf.TensorSpec(shape=[None, 256, 256, 3], dtype=tf.float32))
f2 = convert_variables_to_constants_v2(f)
graph_def = f2.graph.as_graph_def()
# Export frozen graph
with tf.io.gfile.GFile('frozen_graph.pb', 'wb') as f:f.write(graph_def.SerializeToString())

冻结TensorFlow2模型的示例代码,作者:Dmitry Kurtaev

在这段代码中,模型的推演功能被包裹在 tf.function 中,构建了静态图。然后通过 convert_variables_to_constant_v2 将变量转换为常量,并将最终获得的 graph_def 写入单独的protobuf文件。

加载并推演

网络冻结完成后,并可以使用OpenCV加载推演了。示例代码如下:

import numpy as np
import cv2 as cvnet = cv.dnn.readNet('frozen_graph.pb')
inp = np.random.standard_normal([1, 3, 256, 256]).astype(np.float32)
net.setInput(inp)
out = net.forward()
print(out.shape)

OpenCV加载模型的示例代码,作者:Dmitry Kurtaev

Issue顺利解决。  注意TensorFlow版本为2.3.1。OpenCV版本4.5.0。

接下来我们来谈谈如何提issue。

Issue是什么

Issue在中文环境下多译为“问题”,而且是那种可能造成反复纠缠、难以解决的问题例如社会问题(social issue)。电视剧“神盾局特工”中的“反派”局长也曾用这个词来调侃Daisy。

图源:Pintrest

实际上,这个词在现代制造业中也经常会遇到。在我工作的第一家公司中,每个项目在启动前都会组织不同维度与形式的技术研讨,核心就是可能会遇到的“技术issue”。而且项目一旦进入实质性质的试生产流片阶段,大家最害怕出现的也是issue。它通常意味着加班、业绩压力以及可能的推倒重来。

软件行业中,issue这个词常被用来指代计算机程序使用过程中出现的异常表现。因此源代码托管平台GitHub专门为每一个项目提供了一个专门的讨论空间,供代码的使用者提出自己遇到的issue使用。这个区域在UI界面上紧挨着源代码,其重要性可见一斑。

图源:作者GitHub页面截图

造成Issue的原因

程序的异常行为背后可能存在多种原因,有可能是代码中存在的错误,也有可能是使用者的不当操作造成。例如一台微波炉无法加热食物,可能是磁控管故障,也有可能是没插电源。面对“无法加热”这个现象,找到其背后的原因是解决issue的关键。这时候,提issue的方式在某种程度上直接决定了问题解决的速度。根据我的观察,一个优秀的issue提出者能够做到以下几点。

尝试解决问题

如果你家的微波炉不工作了,大部分人的第一反应可能会去检查电源线是不是没有插上。这就是在尝试解决问题。理论上越是成熟的项目代码,发生故障的概率越低。一旦异常事件发生了,首先要尝试排除最可能发生的状况。毕竟因为松动的电源线叫厂家的维修人员上门服务,除了费用不说,主要是耽误自己的午餐。

尝试解决问题的手段因每个人的能力不同而不同。在保证安全的前提下尽力即可。例如本次提issue的小伙伴就详细的描述了TA已经尝试过的方案,而且以列表的形式一一列出,这无疑显示了TA的诚意,是加分项。

逐条列出已经尝试过的方案

反过来,如果issue提出者上来就说“XXX不能用,该怎么办呀”,这样多多少少显得有些伸手党,不过也没什么大不了,只要TA能做到——

准确描述现象

这是最常见的现象,不仅仅是issue区域,在生活中也随处可见。当问题出现时,无法使用语言传递准确的有价值信息。同样是微波炉的例子,以下是两种不同的表述:

A: 我家的微波炉坏了,咋办呀?

B: 我家的微波炉不工作了,大火力加热两分钟,指示灯不亮,微波炉不响,食物不热。电源插好了,可能是什么原因呀?

准确描述现象的最大好处在于这样做可以尽可能的排除各种导致故障的可能性。最为厂家售后人员,如果你听到的是第一种回答,你多半会要求用户检查电源线是否插好。而第二种回答显然已经排除了这种可能性,甚至可以初步估计出故障的严重程度已经超过了普通用户的解决能力。这无疑有利于问题尽快解决。

代码issue与之类似,当问题出现时,在issue中要尽可能的描述出具体的现象。一个糟糕的描述可能是:

A: 我的代码奔溃了,是什么原因呀?

而一个优秀的描述则是:

B: 我在执行 python3 train.py --batch_size=32 的时候训练中断了,并且显示错误信息 ValueError ...

代码的错误信息就像是微波炉上的指示灯,它可以提供非常有用的信息帮助排除错误发生的原因。解决代码的错误需要“抓现行”,也就是要让程序在你眼前奔溃给你看。这也是为什么几乎所有的代码作者要求提issue的时候附上导致错误出现的具体指令或者示例代码。

这一点Suaro就做得很好。TA在issue中附上了完整的错误信息:

在issue中附上具体的错误信息

一般来说,做到这种程度解决该issue就有希望了。如果是代码问题,多半会修复。如果该issue无法复现,那有可能不是代码问题,此时代码作者多半会要求你——

提供必要信息

实际上这是最基础的要求,但往往是最先被忽略的部分。继续拿广受欢迎的微波炉举例。作为厂家的售后人员,当你要求客户提供微波炉的型号代码后,你有可能会发现用户买的其实根本就不是微波炉,而是洗碗机!

这一问题在软件行业更加突出。一是因为同一个软件可能存在多版本并存的现象。例如OpenCV就有2.x, 3.x和4.x这三个主版本分支。TensorFlow也有1和2两个主版本。除此以外,现今软件更迭速度前所未有的迅速,nightly(每日更新)也不罕见。如果把git commit算进去那更是多如牛毛。所以issue可能是由于版本不兼容造成的。

所以,我强烈建议在提issue时一定要附上自己所使用的环境信息。实际上,GitHub已经内置了issue模板,将必要的信息嵌入进去,用户提issue就像是在做选择题一样。

TensorFlow提供的issue模板

Suaro在issue中并没有附上这部分信息。这种情况下我会默认TA使用的环境信息与我在README文件中的一致。当然,反过来考虑,当代码作者的环境与README不同时,也需要在issue回复中明示。

我在issue回复时标明了版本信息

交流沟通的能力

写了这么多关于issue的内容,聪明的你应该已经看出来了。Issue只是表面形式,内里的核心是沟通与交流。有诚意的、有效率的沟通与交流是每个人都应该掌握的能力。工作中它有助于项目推进,生意中可以避免误解与争端,生活中可以让你交到真心朋友。虽然目前的大环境对于真诚交流的人不那么友好,但是,对于每一个真诚的人,总会有另一份真诚不负期望。

 End 

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲

在「小白学视觉」公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

使用OpenCV加载TensorFlow2模型相关推荐

  1. c++ opencv 加载 caffe 模型 ---- 笔记

    1.Q 报错: OpenCV(3.4.2) Error: Assertion failed (ngroups > 0 && inpCn % ngroups == 0 && ...

  2. OpenCV加载Caffe框架模型

    OpenCV加载Caffe框架模型 加载Caffe框架模型 简介 源代码 解释 加载Caffe框架模型 简介 在本教程中,您将学习如何使用Caffe模型将opencv_dnn模块用于图像分类. 我们将 ...

  3. C# OpenCV人脸检测(三) DNN加载FaceDetectorYN模型做人脸检测

    点击下方卡片,关注"OpenCV与AI深度学习"公众号 视觉/图像重磅干货,第一时间送达 本文作者Color Space,文章未经作者允许禁止转载! 本文将介绍C# OpenCV人 ...

  4. OpenCvSharp人脸检测(二) DNN加载Caffe模型做人脸检测

    更多视觉图像处理相关内容,可关注[OpenCV与AI深度学习]公众号获取! 本文作者Color Space,文章未经作者允许禁止转载! 本文将介绍OpenCvSharp人脸检测(二) DNN加载Caf ...

  5. 在C++中加载TorchScript模型

    在C++中加载TorchScript模型 本教程已更新为可与PyTorch 1.2一起使用 顾名思义,PyTorch的主要接口是Python编程语言.尽管Python是合适于许多需要动态性和易于迭代的 ...

  6. xBIM 实战01 在浏览器中加载IFC模型文件

    系列目录    [已更新最新开发文章,点击查看详细]  一.创建Web项目 打开VS,新建Web项目,选择 .NET Framework 4.5  选择一个空的项目 新建完成后,项目结构如下: 二.添 ...

  7. python使用openCV加载图像、并将BGR格式转换成HSV格式、定义HSV格式中需要分离颜色的掩码(掩模)区间(mask)、并使用mask信息进行颜色分离、BGR格式的图像转化为RGB、并可视化

    python使用openCV加载图像.并将BGR格式转换成HSV格式.定义HSV格式中需要分离颜色的掩码(掩模)区间(mask).并使用mask信息进行颜色分离.将BGR格式的图像转化为RGB.可视化 ...

  8. Python时间序列模型推理预测实战:时序推理数据预处理(特征生成、lstm输入结构组织)、模型加载、模型预测结果保存、条件判断模型循环运行

    Python时间序列模型推理预测实战:时序推理数据预处理(特征生成.lstm输入结构组织).模型加载.模型预测结果保存.条件判断模型循环运行 目录

  9. threejs加载obj模型_Vulkan编程指南(章节31-载入模型)

    章节31 载入模型 介绍 本章节我们将会渲染一个带有纹理的三维模型. 库 我们使用tinyobjloader库来从OBJ文件加载顶点数据.tinyobjloader库是一个简单易用的单文件OBJ加载器 ...

最新文章

  1. 驻极体,PN结以及电子管相关问题
  2. Python基本语法_函数_返回值
  3. r 多元有序logistic回归_R语言多元Logistic逻辑回归 应用案例
  4. Neutron 分布式虚拟路由(Neutron Distributed Virtual Routing)
  5. controller调用controller的方法_你想过 Controller 这些方法里的参数是如何工作的吗?...
  6. jmeter聚个报告怎么看qps_【jmeter】jmeter测试网站QPS
  7. N点虚拟主机管理系统(For Windows2003/2008)功能及介绍
  8. http://101.132.165.115/
  9. [20170825]不启动监听远程能连接数据库吗2
  10. Java学习日报 — 问题记录 — 2021/12/14
  11. 策略为王编译错误2:error C1189: #error : MFC does not support
  12. 集成CCFlow工作流与GPM的办公系统驰骋CCOA介绍(三)
  13. 第二十四周项目3-动态链表体验
  14. 【Android-混合开发】mPaas-多版本接入篇
  15. firebug下载及安装
  16. 使用XINCheck文档查重软件对本地文档查重
  17. 如何在unity上放置3d图片
  18. word 2019 深黑色背景如何改成白色(已解决)
  19. 关于Raft的一些问题解答
  20. 2021最新阿里云部署k8s集群(篇1 购买服务器)

热门文章

  1. 2019最新实战!给程序员的7节深度学习必修课,最好还会Python!
  2. 如何让摄像头变成“暗夜之眼”?英特尔开发了一套基于FCN的成像系统
  3. 技术 | 苹果最新博文剑指汉字手写识别!专家回应:并没有技术含量
  4. List 如何根据对象的属性去重?Java 8 轻松搞定!
  5. Java工具类之:包装类
  6. 任务的插入时间复杂度优化到 O(1),Timing Wheel时间轮是怎么做到的?
  7. 一个丧心病狂的Github项目:东北话编程,大写的服!
  8. 数据分析之Pandas分组操作总结
  9. 经验总结!我们是如何在编程面试中挂掉的
  10. GitHub 的AI代码生成神器,其四成代码有漏洞,你还敢用吗