Redian新闻
>
还是那头痛的Resize。。。

还是那头痛的Resize。。。

公众号新闻

点击下方卡片,关注“CVer”公众号

AI/CV重磅干货,第一时间送达

点击进入—>【视觉和Transformer】微信交流群

作者:王小二(源:知乎,已授权)| 编辑:CVer

https://zhuanlan.zhihu.com/p/666296180

一、起因

自己的推理实现在imagenet上eval结果和pytorch的差了0.924个点,看着差距不大但是就非常疑惑。

首先进行两个可能点排查:

  • 在Python端使用pytorch和onnxruntime分别对torch和onnx文件进行推理比较,发现一致

  • 在c++端使用onnxruntime和自己的推理分别进行推理比较,发现一致

这不是很奇怪吗?

A == B and B == C

那 A≠C 吗?你以为是JavaScript吗。。。

那直接找A和C的不同呢?分别喂相同的数据给pytorch和自己的推理代码,发现存在一些细微差别。通过逐步排查发现在前处理的地方得到的数据就不一致了,那么就先重点排查前处理部分。

对于pytorch的训练一般的前处理就是

  • 读图片解码

  • resize

  • 转tensor

  • norm

看着都是比较常规的操作,应该容易对齐才对的。然后逐步排查发现了两个差距点

  1. resize行为不一致

  2. round行为不一致

二、老生常谈的一个问题

来看看让@大缺弦(https://zhuanlan.zhihu.com/p/107761106)大老师都头痛的Resize,主要是说在深度学习中的Resize

还有这位国外老哥,直接用了dangers这个词,这里主要是说一般图像的Resize

https://zuru.tech/blog/the-dangers-behind-image-resizing

不管是深度学习里面,还是一般的图像处理中。大家都被这个Resize支配着。

不过下面两节要谈的是一个更具体的点,pillow和opencv的resize差距。

三、简单搜索分析一下

为什么是pillow呢,因为torchvision默认就用的pillow来做图像的resize操作。

这里我已经怀疑pillow的resize和opencv不一致了,于是去Google了一把,发现果然很多人都遇到过类似的问题,那就说明方向对了。

https//github.com/python-pillow/Pillow/issues/2718

https//github.com/python-pillow/Pillow/issues/4445

https//github.com/python-pillow/Pillow/issues/4476

在pillow的issues中找到从17年就有人提出这个问题了,并且还有人试图pr一份修改,但是一直没有修改,为什么呢?

当然是pillow从之前的pil继承了resize的逻辑,认为他们不需要去模仿opencv的行为,并且选择了和大多数人理解不一样的实现方式。

https//zh.wikipedia.org/zh-cn/%25E5%258F%258C%25E7%25BA%25BF%25E6%2580%25A7%25E6%258F%2592%25E5%2580%25BC

大多数人学的都应该是维基百科提到的,双线性插值是在某个点的周围取相邻4个坐标点的值来计算,只是具体的计算方式有不同次数乘法的实现。

但是Pillow在双线性插值的时候用了一个高级的 two pass resize于是乎取值的逻辑就变了。从上面的issue中摘抄一个真实数据来看看

INPUT:
[[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
[10. 11. 12. 13. 14. 15. 16. 17. 18. 19.]
[20. 21. 22. 23. 24. 25. 26. 27. 28. 29.]
[30. 31. 32. 33. 34. 35. 36. 37. 38. 39.]
[40. 41. 42. 43. 44. 45. 46. 47. 48. 49.]
[50. 51. 52. 53. 54. 55. 56. 57. 58. 59.]
[60. 61. 62. 63. 64. 65. 66. 67. 68. 69.]
[70. 71. 72. 73. 74. 75. 76. 77. 78. 79.]
[80. 81. 82. 83. 84. 85. 86. 87. 88. 89.]
[90. 91. 92. 93. 94. 95. 96. 97. 98. 99.]]
Pillow:
[[ 7.857143 9.642858 11.642858 13.642858 15.428572]
[25.714285 27.5 29.5 31.5 33.285713]
[45.714287 47.5 49.5 51.5 53.285713]
[65.71429 67.5 69.5 71.5 73.28571 ]
[83.57143 85.35714 87.35714 89.35714 91.14285 ]]
OpenCV:
[[ 5.5 7.5 9.5 11.5 13.5]
[25.5 27.5 29.5 31.5 33.5]
[45.5 47.5 49.5 51.5 53.5]
[65.5 67.5 69.5 71.5 73.5]
[85.5 87.5 89.5 91.5 93.5]]

Opencv的结果比较好理解,比如第一个点:5.5 = (0 + 1 + 10 +11) / 4

但是Pillow的结果就比较不常见了。直接看官方的解释

Regarding the first post, Pillow performs two passes over the image - horizontal, and then vertical.

So why is the first value 7.857143?

The coefficients generated by our bilinear function are 0.428571, 0.428571 and 0.142857.

Applying that horizontally,

0 * 0.428571 + 1 * 0.428571 + 2 * 0.142857 = 0.714285
10 * 0.428571 + 11 * 0.428571 + 12 * 0.142857 = 10.714275
20 * 0.428571 + 21 * 0.428571 + 22 * 0.142857 = 20.714265
and then vertically,

0.714285 * 0.428571 + 10.714275 * 0.428571 + 20.714265 * 0.142857 = 7.85712714287
You suggest that Pillow should only consider 0, 1, 10 and 11 to get the first pixel value. Instead, Pillow is also considering 2, 12, 20, 21 and 22. That is different to OpenCV, but I see no reason why it should be thought of as incorrect. 0, 1, 10 and 11 are still all considered equally.


https//github.com/python-pillow/Pillow/blob/b4bf2885f365b23e16772380173e971f89b208bf/src/libImaging/Resample.c%23L655

https//github.com/python-pillow/Pillow/blob/b4bf2885f365b23e16772380173e971f89b208bf/src/libImaging/Resample.c%23L20-L29

具体的核计算在上面的链接中。

一个直观的感受就是在这个示例中,opencv沿用的4点取值,pillow采用的是9点取值。这就导致了他们结果不会完全对等上。

实际上pillow的操作是为了抗锯齿,下面的示例能比较清楚的看出pillow和opencv的差距。

四、如何解决

这里不说Python怎么做,因为你可以非常方便的安装这两个库,并且相互转换。下面只讨论c++部署怎么做。

  • 把pillow的c++代码抠出来

  • 自己手搓一个

  • 找大佬求求看有没有已经实现过了

  • Google碰运气

Google说今天运气不错,有现成的,并且还是基于opencv来做的。

https//github.com/zurutech/pillow-resize

这里要注意一下大佬的宏可能和某些opencv版本不匹配了,需要手动修改一下。其它毛病没有。

五、附加的round差异

大家都知道round有很多种

https//en.wikipedia.org/wiki/Floating-point_arithmetic

在维基百科的浮点说明中,Rounding modes 单元有如下的说明:

  • Alternative rounding options are also available. IEEE 754 specifies the following rounding modes:

  • round to nearest, where ties round to the nearest even digit in the required position (the default and by far the most common mode)

  • round to nearest, where ties round away from zero (optional for binary floating-point and commonly used in decimal)

  • round up (toward +∞; negative results thus round toward zero)

  • round down (toward −∞; negative results thus round away from zero)

  • round toward zero (truncation; it is similar to the common behavior of float-to-integer conversions, which convert −3.9 to −3 and 3.9 to 3)

比较常见的就是向最近临的偶数取整

然而在不同的语言,不同的版本中,同一个数的舍入情况也不一样。比如Python2.7和Python3.5对舍入操作的描述就不一样。在迁移到c++的时候需要小心的关注一下Python端用的那种舍入模式。避免Python和c++的不一致。

CVPR / ICCV 2023论文和代码下载
后台回复:CVPR2023,即可下载CVPR 2023论文和代码开源的论文合集

后台回复:ICCV2023,即可下载ICCV 2023论文和代码开源的论文合集

计算机视觉和Transformer交流群成立


扫描下方二维码,或者添加微信:CVer444,即可添加CVer小助手微信,便可申请加入CVer-计算机视觉或者Transformer 微信交流群。另外其他垂直方向已涵盖:目标检测、图像分割、目标跟踪、人脸检测&识别、OCR、姿态估计、超分辨率、SLAM、医疗影像、Re-ID、GAN、NAS、深度估计、自动驾驶、强化学习、车道线检测、模型剪枝&压缩、去噪、去雾、去雨、风格迁移、遥感图像、行为识别、视频理解、图像融合、图像检索、论文投稿&交流、PyTorch、TensorFlow和Transformer、NeRF等。


一定要备注:研究方向+地点+学校/公司+昵称(如目标检测或者Transformer+上海+上交+卡卡),根据格式备注,可更快被通过且邀请进群

▲扫码或加微信号: CVer444,进交流群


CVer计算机视觉(知识星球)来了!想要了解最新最快最好的CV/DL/AI论文速递、优质实战项目、AI行业前沿、从入门到精通学习教程等资料,欢迎扫描下方二维码,加入CVer计算机视觉(知识星球),已汇集近万人!


扫码加入星球学习


▲点击上方卡片,关注CVer公众号

整理不易,请点赞和在看

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
秋日里的第一顿火锅时隔13年的宅男经典,还是那么胡逼有趣分娩镇痛的这些知识要知道今年感恩节航空公司将迎来创纪录游客,最忙是这天。。。。Nature | 耶鲁大学刘传聚课题组揭示有望减缓骨关节退化和减轻关节疼痛的药物靶点「鸥鹭映室」乳房胀痛的留守少女面对的《石门》,你我一定要推开。胸腔镜术后镇痛的总结分析西雅图看房日记|100万以内的Redmond 市中心的5房独栋学区房天各一方 (7)時代的車輪(古詩詞英譯) 枯樹賦 – 庾信 (段章)Three Reasons Luxury Should Remain ResilientChinese Reality Show Explores ‘Strong Woman, Weak Man’ Marriages"我们国家有黄金、有铀矿,为什么我们还是那么穷?"真牛!贝佐斯现在这身材也太好了,还是那小老头嘛!许久不见,她还是那个魅力十足的“亢奋”女孩China Moves to Standardize Place Names with Pinyin System秋思人人都可能被杀猪盘,你敢说你是那头猪吗?北大团队搞定ChatGPT都头痛的算法优化,普通笔电就能跑食材禁运后,才知道谁在裸泳。。。。顶尖大学公开「耍流氓」!如何理解早申中的REA申请?你适合申请REA吗?谣传易鲸捷的数据库是套牌的Oracle。。。真牛啊!贝佐斯现在这身材是怎么了?!还是那无精打采小老头吗德牧狂吠扰民,女子跟它走进灌木丛,发现了让人心痛的真相八大道街头随处可见的Revel将成为过去梦幻联动!小火龙还是那么可爱!腰酸背痛的有得治了Space Race: Why Young Chinese Are Cutting Ties with Relatives理工男辞职炒股!千万资产梭哈融创归零,七年投资一场大梦!人到中年,他选择重新找工作!这是令人心痛的投资教训!这不是保健品,这是一款能解决炎症,减轻疼痛的,高达4.6倍吸收的钙片How Residents Are Rebuilding Shanghai’s Urban Communities3个月不晒被,百万螨虫陪你睡!难怪总过敏、长痘,秋冬除螨还得靠它。。。。共和党以腐败为由弹劾拜登是个笑话工信部印发《关于推进5G轻量化(RedCap)技术演进和应用创新发展的通知》;面向AIGC的RISC-V内核来了|AIoT情报180刀Razer DeathAdder V3 Pro Ultra-lightweight Ergonomic Wireless
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。