使用scikit-image批量转换RGB图片为灰度图时遇AttributeError问题
解决AttributeError: 'JpegImageFile' object has no attribute 'ndim'错误
你碰到这个错误的核心问题在于同时混用了PIL和scikit-image的图像处理对象——Image.open()返回的是PIL的JpegImageFile实例,而scikit-image的rgb2gray()函数需要的是numpy数组格式的图像数据,它会尝试读取数组的ndim(维度)属性,PIL对象根本没有这个属性,所以直接报错了。
除此之外,你的代码里还有几个容易踩坑的问题:
- 错误把
os.chdir()的返回值赋值给了list变量:os.chdir()只是切换当前工作目录,返回的是None,根本没法遍历它获取文件;而且list是Python的内置类型名,用它当变量名会覆盖内置函数,绝对要避免。 - 导入的模块引用错误:比如你导入了
skimage.color.rgb2gray,但代码里写的是color.rgb2gray;导入了skimage.io.imread/imsave,却用io.imsave,这些都会导致后续找不到函数的报错。 - 保存灰度图时没指定具体文件名:直接写目录路径
"C:/Users/Images/Greyscale"会导致保存失败,必须要拼接原文件名或者生成新的文件名。 - 其实没必要同时导入PIL和scikit-image的IO模块,用scikit-image自带的
imread和imsave就足够完成这个转换需求了。
下面是修正后的完整代码,我加了注释方便你理解:
import glob from skimage.color import rgb2gray from skimage.io import imread, imsave import os # 定义输入和输出目录路径 input_dir = "C:/Users/Images/RGB" output_dir = "C:/Users/Images/Greyscale" # 确保输出目录存在,如果不存在就创建它 os.makedirs(output_dir, exist_ok=True) # 获取输入目录下所有的JPEG文件(包含.jpg和.jpeg后缀) image_paths = glob.glob(os.path.join(input_dir, "*.jpg")) + glob.glob(os.path.join(input_dir, "*.jpeg")) # 遍历所有图像文件 for img_path in image_paths: # 用scikit-image的imread读取图像,直接得到numpy数组格式的RGB图像 rgb_image = imread(img_path) # 转换为灰度图 gray_image = rgb2gray(rgb_image) # 获取原文件的文件名,拼接输出路径(这里给原文件名加了gray_前缀区分) filename = os.path.basename(img_path) output_path = os.path.join(output_dir, f"gray_{filename}") # 保存灰度图:rgb2gray返回的是0-1范围的float数组,转成0-255的uint8更适合JPEG存储 imsave(output_path, (gray_image * 255).astype("uint8"))
额外补充几个注意点:
- 用
glob.glob直接获取目标文件,比切换工作目录的方式更清晰,也不容易出错。 rgb2gray返回的浮点型数组虽然可以直接用imsave保存,但转成uint8类型后,图像的存储空间会更小,也符合常规图像的存储规范。- 永远不要用Python的内置名称(比如list、str、dict这些)作为自定义变量名,否则会引发各种难以排查的问题。
内容的提问来源于stack exchange,提问作者Simon Kiely
相关产品推荐
相关产品推荐

