我有一个非常大的数组,需要迭代。数组是一个大的tiff图像,而不是一个颜色值,我想添加一个4-4位的2d模式。我的代码现在看起来是这样的。它需要很长时间才能完成。tiff是一个数组(x,y,4)。X和y很大。value是一个包含与我正在搜索的值相匹配的模式的列表,并提供给我索引。模式是由4-4个模式组成的数组。谢谢
for iy, ix in np.ndindex(tiff[:, :, 0].shape):
tiff[iy, ix, 0] = np.random.choice(np.argwhere(Values == tiff[iy, ix, 0])[:, 0], 1, replace=False)
tiff[iy, ix, 1] = np.random.choice(np.argwhere(Values == tiff[iy, ix, 1])[:, 0], 1, replace=False)
tiff[iy, ix, 2] = np.random.choice(np.argwhere(Values == tiff[iy, ix, 2])[:, 0], 1, replace=False)
tiff[iy, ix, 3] = np.random.choice(np.argwhere(Values == tiff[iy, ix, 3])[:, 0], 1, replace=False)
Rippedimage[iy * 8 : (iy + 1) * 8 - 4, ix * 8 : (ix + 1) * 8 - 4] = Array_Pattern_4_4[tiff[iy, ix, 0]]
Rippedimage[iy * 8 : (iy + 1) * 8 - 4, ix * 8 + 4 : (ix + 1) * 8] = Array_Pattern_4_4[tiff[iy, ix, 1]]
Rippedimage[iy * 8 + 4 : (iy + 1) * 8, ix * 8 : (ix + 1) * 8 - 4] = Array_Pattern_4_4[tiff[iy, ix, 2]]
Rippedimage[iy * 8 + 4 : (iy + 1) * 8, ix * 8 + 4 : (ix + 1) * 8] = Array_Pattern_4_4[tiff[iy, ix, 3]]发布于 2022-01-17 08:57:59
老实说,要知道您真正想要的是什么有点困难,但是下面是一些代码:
在我的Macbook上,抖动920x920图像大约需要17毫秒:
image generation 4.377
pattern generation 6.06
dither generation 16.915import time
from contextlib import contextmanager
import numpy as np
from PIL import Image
def generate_patterns(
*,
pattern_size: int = 8,
pattern_options_per_shade: int = 8,
shades: int = 256,
):
patterns = []
for shade in range(shades):
shade_patterns = [
np.random.random((pattern_size, pattern_size)) < (shade / shades)
for i in range(pattern_options_per_shade)
]
patterns.append(shade_patterns)
return np.array(patterns)
def dither(image, patterns):
(
shades,
pattern_options_per_shade,
pattern_width,
pattern_height,
) = patterns.shape
assert shades == 256 # TODO
# image sampled at pattern_sizes
resampled = (
image[::pattern_width, ::pattern_height].round().astype(np.uint8)
)
# mask of pattern option per pattern_size block
pat_mask = np.random.randint(
0, pattern_options_per_shade, size=resampled.shape
)
dithered = np.zeros_like(image)
for (iy, ix), c in np.ndenumerate(resampled):
pattern = patterns[c, pat_mask[iy, ix]]
dithered[
iy * pattern_height : (iy + 1) * pattern_height,
ix * pattern_width : (ix + 1) * pattern_width,
] = pattern
return dithered * 255
@contextmanager
def stopwatch(title):
t0 = time.perf_counter()
yield
t1 = time.perf_counter()
print(title, round((t1 - t0) * 1000, 3))
def main():
with stopwatch("image generation"):
img_size = 920
image = (
np.linspace(0, 255, img_size)
.repeat(img_size)
.reshape((img_size, img_size))
)
image[200:280, 200:280] = 0
with stopwatch("pattern generation"):
patterns = generate_patterns()
with stopwatch("dither generation"):
dithered = dither(image, patterns)
import matplotlib.pyplot as plt
plt.figure(dpi=450)
plt.imshow(dithered, interpolation="none")
plt.show()
if __name__ == "__main__":
main()输出图像看起来像(例如)

编辑
将源图像向上缩放到抖动版本的版本:
image generation 3.886
pattern generation 5.581
dither generation 1361.194def dither_embiggen(image, patterns):
shades, pattern_options_per_shade, pattern_width, pattern_height = patterns.shape
assert shades == 256 # TODO
# mask of pattern option per source pixel
pat_mask = np.random.randint(0, pattern_options_per_shade, size=image.shape)
dithered = np.zeros((image.shape[0] * pattern_height, image.shape[1] * pattern_width))
for (iy, ix), c in np.ndenumerate(image.round().astype(np.uint8)):
pattern = patterns[c, pat_mask[iy, ix]]
dithered[iy * pattern_height:(iy + 1) * pattern_height, ix * pattern_width:(ix + 1) * pattern_width] = pattern
return (dithered * 255)编辑2
此版本将抖动行直接作为原始二进制文件写入磁盘。读者应该知道每一行有多少像素。基于一个小的经验测试,这看起来很管用.
import time
from contextlib import contextmanager
import numpy as np
def generate_patterns(
*,
pattern_size: int = 8,
pattern_options_per_shade: int = 16,
shades: int = 256,
):
patterns = []
for shade in range(shades):
shade_patterns = [
np.packbits(
np.random.random((pattern_size, pattern_size))
< (shade / shades),
axis=0,
)[0]
for i in range(pattern_options_per_shade)
]
patterns.append(shade_patterns)
return np.array(patterns)
def dither_to_disk(bio, image, patterns):
assert image.dtype == np.uint8
shades, pattern_options_per_shade, pattern_height = patterns.shape
pat_mask = np.random.randint(0, pattern_options_per_shade, size=image.shape)
for y in range(image.shape[0]):
patterns[image[y, :], pat_mask[y, :]].tofile(bio)
@contextmanager
def stopwatch(title):
t0 = time.perf_counter()
yield
t1 = time.perf_counter()
print(title, round((t1 - t0) * 1000, 3))
def main():
with stopwatch("image generation"):
img_width = 25_000
img_height = 5_000
image = (
np.linspace(0, 255, img_height)
.repeat(img_width)
.reshape((img_height, img_width))
)
image[200:280, 200:280] = 0
image = image.round().astype(np.uint8)
with stopwatch("pattern generation"):
patterns = generate_patterns()
with stopwatch(f"dither_to_disk {image.shape}"):
with open("x.bin", "wb") as f:
dither_to_disk(f, image, patterns)
if __name__ == "__main__":
main()https://stackoverflow.com/questions/70737620
复制相似问题