如何将generator对象转为numpy数组?优化图像像素随机洗牌
问题解决办法
首先得说清楚,你的rand_shuffle_faster有两个问题:
- 用了
yield,直接把函数变成生成器了,而且yield后面的代码(重塑形状和return)根本跑不到——因为yield会暂停函数,直接返回生成器对象。 - 逻辑和原函数完全不一样:原函数是打乱所有像素的位置(把(N,3)的数组行随机重排),但你改写的函数是打乱每个像素的RGB通道顺序(对列做随机排列),这俩是完全不同的操作。
一、先把逻辑改回原需求(同时提速)
如果你的目标还是和原函数一样打乱像素位置,正确的优化写法根本不需要yield,直接用随机索引重排就行,效率还能保持:
import numpy as np import time def rand_shuffle_faster(img): # 转成(N,3)的形状,-1表示自动计算维度 rndImg = img.reshape(-1, img.shape[2]) # 生成随机索引,用索引重排行(比shuffle更灵活) idx = np.random.permutation(rndImg.shape[0]) rndImg = rndImg[idx] # 转回到原图像形状 return rndImg.reshape(img.shape)
这个函数直接返回numpy数组,速度和原函数差不多,甚至可能更快——因为np.random.shuffle是原地修改数组,而索引重排的方式在某些场景下开销更低。
二、硬要处理现有生成器的话(不推荐,因为逻辑不对)
如果只是想把你现在这个生成器转成numpy数组,用next()取出生成器里的元素就行:
# 假设img是你的输入图像数组 gen = rand_shuffle_faster(img) # 取出生成器里的数组 result = next(gen) # 别忘了手动转回到原图像形状,因为你原函数里yield之后的reshape根本没执行 result = result.reshape(img.shape)
但再次提醒:这个结果和原函数输出完全不同,原函数是把像素位置打乱,这个是把每个像素的RGB通道顺序打乱,别搞混了。
三、再提个提速小技巧
如果还想更快,可以用numpy新的随机数接口np.random.Generator,比旧接口速度快不少:
def rand_shuffle_faster(img): # 初始化新的随机数生成器 rng = np.random.default_rng() rndImg = img.reshape(-1, img.shape[2]) idx = rng.permutation(rndImg.shape[0]) return rndImg[idx].reshape(img.shape)
内容的提问来源于stack exchange,提问作者zzzw3838
相关产品推荐
相关产品推荐

