Opencv与Pillow图片操作差异对深度学习的影响
目前在使用Pytorch训练的深度学习模型算法,大部分由于pillow与torchvision中transforms的优异兼容都会采用Image.open from pillow的方式进行图像数据的读取和crop or resize。
这种方案在纯学术环境下不会暴露其问题,但是用到工业部署环境下就会暴露其致命的问题。由于目前C++工业部署大部分使用的还是opencv框架进行图像数据的处理,但是我们发现opencv读取图像进行resize操作时,其模型的预测精度比pillow前处理版本将下降10%到60%,这巨大的gap不由得引起我们的关注。为什么会造成这种情况。
于是我们对同一种图像分别用两个框架进行读取、resize这两个操作判断其像素间的差异。

import cv2
from PIL import Image
import numpy as np
# pillow读取并转换为int8格式数组
pil_img = Image.open("test.jpg").convert("RGB")
pil_arr = np.uint8(np.array(pil_img))
# opencv读取并转换为int8格式数组
cv_img = cv2.imread("test.jpg")
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
cv_arr = np.uint8(np.array(cv_img))
# 计算其读取误差
mean_error = np.mean(np.absolute(pil_arr - cv_arr))

读取平均像素误差
在这里我们就发现这两种框架在读取上就会造成误差,但是opencv和pillow读取有误差已经算是一个常识了,并且在未归一化的前提下只有0.0003像素值的平均误差已经很低了,应该不是造成巨大gap的原因。

归一化后的读取误差可以忽略不计
为了进一步的验证不是读取造成的模型推理精度误差,我们使用opencv读取的图片转换为pillow格式后,用pillow前处理然后推理得到的结果和pillow本身读取推理的结果是一致的。
接下来我们进一步对resize操作进行验证,两个框架均使用同一种resize算法:
# pillow resize
pil_img = pil_img.resize((300, 300), Image.BICUBIC)
pil_arr = np.uint8(np.array(pil_img))
# opencv读取并转换为int8格式数组
cv_img = cv2.resize(cv_img, (300, 300), cv2.INTER_CUBIC)
cv_arr = np.uint8(np.array(cv_img))
# 计算其resize误差
mean_error = np.mean(np.absolute(pil_arr - cv_arr))

resize平均像素误差
77的平均像素误差!要知道像素值的范围也只有0到255,将近三分之一的误差,说明两者在同一种resize的实现逻辑一定有巨大差异,这种误差将在使用opencv部署pillow训练模型的时候造成巨大的精度gap。
后续对此情况进行调研,发现这个问题在2017年的时候,就已经有人在pillow的官方仓库下提出。
pillow框架在resize算法实现上和opencv、matlab均有巨大差异,但是pillow并不认为这是他们的问题,所以也一直没有修改。

从开发者的角度上来说,为了工业部署时对精度的良好把控,建议在训练时不要使用pillow框架和torchvision自带的前处理方案,保证训练和部署对数据处理的一致性,避免这种由框架不同导致的巨大gap。
Opencv与Pillow图片操作差异对深度学习的影响的更多相关文章
- 深度学习 + OpenCV,Python实现实时视频目标检测
使用 OpenCV 和 Python 对实时视频流进行深度学习目标检测是非常简单的,我们只需要组合一些合适的代码,接入实时视频,随后加入原有的目标检测功能. 在本文中我们将学习如何扩展原有的目标检测项 ...
- 给深度学习入门者的Python快速教程 - 番外篇之Python-OpenCV
这次博客园的排版彻底残了..高清版请移步: https://zhuanlan.zhihu.com/p/24425116 本篇是前面两篇教程: 给深度学习入门者的Python快速教程 - 基础篇 给深度 ...
- MXNet设计笔记之:深度学习的编程模式比较
市面上流行着各式各样的深度学习库,它们风格各异.那么这些函数库的风格在系统优化和用户体验方面又有哪些优势和缺陷呢?本文旨在于比较它们在编程模式方面的差异,讨论这些模式的基本优劣势,以及我们从中可以学到 ...
- 深度学习框架PyTorch一书的学习-第五章-常用工具模块
https://github.com/chenyuntc/pytorch-book/blob/v1.0/chapter5-常用工具/chapter5.ipynb 希望大家直接到上面的网址去查看代码,下 ...
- 深度学习基础系列(十一)| Keras中图像增强技术详解
在深度学习中,数据短缺是我们经常面临的一个问题,虽然现在有不少公开数据集,但跟大公司掌握的海量数据集相比,数量上仍然偏少,而某些特定领域的数据采集更是非常困难.根据之前的学习可知,数据量少带来的最直接 ...
- 28款GitHub最流行的开源机器学习项目,推荐GitHub上10 个开源深度学习框架
20 个顶尖的 Python 机器学习开源项目 机器学习 2015-06-08 22:44:30 发布 您的评价: 0.0 收藏 1收藏 我们在Github上的贡献者和提交者之中检查了用Python语 ...
- 玩深度学习选哪块英伟达 GPU?有性价比排名还不够!
本文來源地址:https://www.leiphone.com/news/201705/uo3MgYrFxgdyTRGR.html 与“传统” AI 算法相比,深度学习(DL)的计算性能要求,可以说完 ...
- faceswap深度学习AI实现视频换脸详解
给大家介绍最近超级火的黑科技应用deepfake,这是一个实现图片和视频换脸的app.前段时间神奇女侠加尔盖朵的脸被换到了爱情动作片上,233333.我们这里将会从github项目faceswap开始 ...
- TensorFlow系列专题(三):深度学习简介
一.深度学习的发展历程 深度学习的起源阶段 深度学习的发展阶段 深度学习的爆发阶段 二.深度学习的应用 自然语言处理 语音识别与合成 图像领域 三.参考文献 一.深度学习的发展历程 作为机器学习最 ...
- 推荐GitHub上10 个开源深度学习框架
推荐GitHub上10 个开源深度学习框架 日前,Google 开源了 TensorFlow(GitHub),此举在深度学习领域影响巨大,因为 Google 在人工智能领域的研发成绩斐然,有着雄厚 ...
随机推荐
- 克鲁斯焊机GL 270引弧困难维修
克鲁斯焊机维修: 对于客户而言,其受益之处在于所有的机械手系统部件,从机械手控制.工件.定位器.传感器到电源和焊枪,都是由一家供应商开发和制造的.而诸如熔化极惰性气体/活性气体保护双丝焊接技术.等离子 ...
- 解决easyexcel合并单元格数组求和重复问题
背景 EasyExcel(根据条件动态合并单元格的重复数据))_Violet-CSDN博客_easyexcel动态合并单元格现有的订单导出是使用的easyExcel完成的.对于相同单元格的合并是自定义 ...
- OpenLayers 绘制带箭头的LineString
<!--******************************************************************** * Copyright 2000 - 2022 ...
- docker - [03] docker原理
题记 一.docker是怎么工作的 docker是一个CS(Client - Server)结构的系统,docker的守护进程运行在主机上,通过Socket从客户端访问. docker Server接 ...
- MyCat分库分表-安装
准备3台虚拟机CentOS7,一台MyCat,两台MySQL 一.安装MySQL 打开MySQL官网mysql.com根据提示安装 1.yum仓库 https://dev.mysql.com/down ...
- ITSS 运维2.0 实践
最近公司在评审itss 2.0,参与了一部分工作,对工作过程中的问题梳理如下: 大的背景:评审itss 2.0会有评审 为什么公司会申请各种资质 首次申请资质后,公司可以申请一笔费用(x万元)! 申请 ...
- Windows编程----结束进程
进程有启动就有终止,通过CreateProcess函数可以启动一个新的子进程,但是如何终结子进程呢?主要有四种方法: 通过主线程的入口函数(main函数.WinMain函数)的return关键字终止进 ...
- React从webpack迁移到rsbuild 纪实
Why 随着团队项目规模越来越大之后,继从babel-loader迁移到esbuild之后发现打包.热重载性能随着时间迭代之后又慢慢开始成为性能瓶颈,所以决定用新的打包工具去解决这个问题.esbuil ...
- 如何用js精确计算一行文字的宽度
之前有做过一个业务,需要在文本框输入文字的时候动态计算一行文字的宽度.并由此知道当前输入的这段文字会有几行. 如何计算? 每个文字的个数*宽度?理论上可行,但是有一个问题是不同类型的文字对应的宽度是不 ...
- gorm中使用乐观锁
乐观锁简介 乐观锁(又称乐观并发控制)是一种常见的数据库并发控制策略. 乐观并发控制多数用于数据竞争(data race)不大.冲突较少的环境中,这种环境中,偶尔回滚事务的成本会低于读取数据时锁定数据 ...