python - 从 np.float64 到 np.uint8 的快速转换(带有缩放和裁剪)
问题描述
我正在尝试找到在 python 中扩展和转换数据类型的最快方法。这是一种方法,但是它很慢:
# image is a large np.float64 image with values in an arbitrary range
timeit.timeit(lambda: np.clip(image*255, 0, 255).astype(np.uint8), number=100)
=> 4.746736011002213 seconds
我注意到 opencv 具有convertScaleAbs函数,它几乎可以做正确的事情,但abs
在顶部添加了一个不必要的函数。这要快得多,但会使所有负值变为正而不是零:
timeit.timeit(lambda: cv2.convertScaleAbs(image, alpha=255, beta=0), number=100)
=> 0.7875663779996103 seconds
的convertTo功能cv::Mat
也可以,但这似乎在python
陆地上不存在。
关于如何加快速度的任何其他想法?
解决方案
您的数组在乘法期间和 期间都被复制clip()
,如果您可以就地执行它,它会加快一点。
import numpy as np
import timeit
side = 10000
source = np.random.random(side * side).reshape((side, side)) * 2 ** 16
def clip_1(image):
return np.clip(image * 255, 0, 255).astype(np.uint8)
def clip_2(image):
image *= 255
return np.clip(image, 0, 255, out=image).astype(np.uint8)
print('clip 1:', timeit.timeit(lambda: clip_1(source), number=10)) # 23.395304517
print('clip 2:', timeit.timeit(lambda: clip_2(source), number=10)) # 13.009874021000002
或者尝试使用 cv2 并在事后恢复符号:
clipped = cv2.convertScaleAbs(image, alpha=0, beta=255)
clipped *= np.sign(image)
推荐阅读
- sql-server - 无法使用 Sqoop 将 SQL Server 视图中的所有记录导入 HDFS
- mysql - 如何获取 MySQL 中两列范围之间的记录?
- c# - 如何刷新DataGridView中只有一个单元格的背景颜色
- swift - 如何模拟 DataTaskPublisher?
- angular - 如何制作拦截器单元测试
- python - 线性回归 - 不正确的输出
- nunit - 通过 TeamCity 中的 Console Runner 使用 NUnit 3 时未找到 ServiceStack 许可证
- javascript - Jquery ajax FormData 始终为空
- python - Python 3:列表和字典。如何创建一个字典来告诉我每个项目来自哪个列表?
- android - Android 10 (api 29) 如何启用 HDR 和夜间模式