首页 > 解决方案 > 从 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陆地上不存在。

关于如何加快速度的任何其他想法?

标签: pythonnumpyopencv

解决方案


您的数组在乘法期间和 期间都被复制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)

推荐阅读