批量提取文件夹图像轮廓后无法保存图片,报错ValueError求助
问题根源
你遇到的ValueError是因为**plt.contour()返回的是ContourSet对象**,而不是可以直接保存的图像数值数组——scipy.misc.imsave(这个函数其实已经被官方弃用)需要的是符合形状要求的像素数组,自然会触发形状不匹配的报错。
修正方案
我们需要先把轮廓绘制到matplotlib的画布上,再通过画布保存图像,或者将画布内容转换为数组后保存。下面是两种可行的修正代码:
方案一:直接用matplotlib保存画布(最简单)
这个方法直接利用matplotlib的savefig保存绘制好轮廓的画布,不需要额外转换数组:
import matplotlib.pyplot as plt import os from os.path import join from PIL import Image import numpy as np # 补充你缺失的numpy导入 i = 0 directory_in_str = 'C:\\directory' directory_output = 'C:\\output_directory' # 提前创建输出文件夹,避免保存时出错 if not os.path.exists(directory_output): os.makedirs(directory_output) for file in os.listdir(directory_in_str): print(file) # 读取图像并转为灰度数组 im = np.array(Image.open(join(directory_in_str, file)).convert('L')) # 创建与原图像尺寸匹配的画布(dpi=100是为了保证尺寸精度) fig, ax = plt.subplots(figsize=(im.shape[1]/100, im.shape[0]/100), dpi=100) # 绘制轮廓 ax.contour(im, levels=[100], colors='black', origin='image') # 隐藏坐标轴、去掉边距,让保存的图片只保留轮廓 ax.axis('off') plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0) plt.margins(0, 0) # 保存图片 save_path = join(directory_output, f'image{i}.jpg') plt.savefig(save_path, bbox_inches='tight', pad_inches=0) plt.close(fig) # 关闭画布释放内存,避免内存泄漏 i += 1 print('done')
方案二:转换为数组后用PIL保存
如果你需要拿到图像数组做后续处理,可以先把画布内容转为数组,再用PIL保存:
import matplotlib.pyplot as plt import os from os.path import join from PIL import Image import numpy as np i = 0 directory_in_str = 'C:\\directory' directory_output = 'C:\\output_directory' if not os.path.exists(directory_output): os.makedirs(directory_output) for file in os.listdir(directory_in_str): print(file) im = np.array(Image.open(join(directory_in_str, file)).convert('L')) fig, ax = plt.subplots(figsize=(im.shape[1]/100, im.shape[0]/100), dpi=100) ax.contour(im, levels=[100], colors='black', origin='image') ax.axis('off') plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0) plt.margins(0, 0) # 将画布内容转为RGB数组 fig.canvas.draw() data = np.frombuffer(fig.canvas.tostring_rgb(), dtype=np.uint8) data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,)) # 用PIL保存数组为图片 img = Image.fromarray(data) img.save(join(directory_output, f'image{i}.jpg')) plt.close(fig) i += 1 print('done')
额外注意点
- 补充了
numpy的导入:你之前代码里的array()其实是numpy.array(),必须导入numpy才能正常使用。 - 新增了输出文件夹的判断:如果目标文件夹不存在,先创建它,避免保存时抛出路径不存在的错误。
- 弃用了
scipy.misc.imsave:这个函数已经被官方标记为弃用,用matplotlib或PIL的保存方法更稳定可靠。 - 调整了画布布局:隐藏坐标轴、去掉边距是为了让保存的图片只包含轮廓,没有多余的边框和轴元素。
内容的提问来源于stack exchange,提问作者Simon Kiely
相关产品推荐
相关产品推荐

