我用过
numba
装饰功能(删除
_sgn
并使用
np.sign
,删除了
try..except
-需要吗?):
import math
import time
import cv2
import numpy
from numba import njit
_epsilon = 0.0000000001
@njit
def _pixel_coordinates_to_unit(coordinate, max_value):
return coordinate / max_value * 2 - 1
@njit
def _one_coordinates_to_pixels(coordinate, max_value):
return (coordinate + 1) / 2 * max_value
@njit
def _stretch_square_to_disc(x, y):
if (abs(x) < _epsilon) or (abs(y) < _epsilon):
return x, y
x2 = x * x
y2 = y * y
hypotenuse_squared = x * x + y * y
reciprocal_hypotenuse = 1.0 / np.sqrt(hypotenuse_squared)
multiplier = 1.0
if x2 > y2:
multiplier = np.sign(x) * x * reciprocal_hypotenuse
else:
multiplier = np.sign(y) * y * reciprocal_hypotenuse
return x * multiplier, y * multiplier
@njit
def _transform(inp):
result = numpy.zeros_like(inp)
for x, row in enumerate(inp):
unit_x = _pixel_coordinates_to_unit(x, len(inp))
for y, _ in enumerate(row):
unit_y = _pixel_coordinates_to_unit(y, len(row))
uv = _stretch_square_to_disc(unit_x, unit_y)
if uv is None:
continue
u, v = uv
u = _one_coordinates_to_pixels(u, len(inp))
v = _one_coordinates_to_pixels(v, len(row))
result[x][y] = inp[math.floor(u)][math.floor(v)]
return result
# -- load and test
img = cv2.imread("circle.png")
# warm jit
# this is needed to let numba do the JIT optimizations
# if you run the the function "cold", the running time will be larger
# you can use compile-ahead-of-time
# https://numba.pydata.org/numba-doc/dev/user/pycc.html
squareImage = _transform(img[0:224, 0:224])
elapsed = time.perf_counter_ns()
squareImage = _transform(img[0:224, 0:224])
print(str((time.perf_counter_ns() - elapsed) / 1000) + " us to squareImage")
cv2.imwrite("shashed.png", squareImage)
在我的电脑(AMD 5700X)上,它打印:
528.596 us to squareImage
# without using numba:
# 47928.774 us to squareImage
使用的图像:
circle.png
结果