Python新手求助:按图片文件名后缀分类至新文件夹及报错解决
解决AttributeError: 'numpy.ndarray' object has no attribute 'endswith'问题
首先咱们得先揪出报错的根源:你当前代码里的all_images列表存的是用cv2.imread读取后的numpy像素数组,而不是图片的文件名字符串。endswith()是字符串专属的方法,自然没法用在numpy数组上,这就是报错的原因啦。
结合你的需求——根据文件名结尾把三个文件夹里的图片分类到新文件夹,其实完全不需要先把图片加载到内存里,直接操作文件(复制/移动)更高效,还能彻底避开这个错误。
修正后的完整代码
import os from shutil import copyfile # 定义要处理的源文件夹列表 source_folders = [ 'C:/Users/shiva/OneDrive/Desktop/WORK/Bildverarbeitung_Reaktion/Pictures/I3te_Reaktion', 'C:/Users/shiva/OneDrive/Desktop/WORK/Bildverarbeitung_Reaktion/Pictures/4te_Reaktion', 'C:/Users/shiva/OneDrive/Desktop/WORK/Bildverarbeitung_Reaktion/Pictures/5te_Reaktion', ] # 自定义分类规则:键是目标文件夹名,值是要匹配的文件名标识(支持多个) category_rules = { '1550_R_images': ['1550_R_', '.jpeg', '.jpg'], # 匹配含1550_R_的jpeg/jpg文件 '1500_images': ['1500_'], # 匹配含1500_的文件 'unclassified_images': [] # 兜底文件夹,放不匹配规则的文件 } # 自动创建所有目标文件夹(不存在则创建,已存在不会报错) base_output_dir = 'C:/Users/shiva/OneDrive/Desktop/WORK/Bildverarbeitung_Reaktion/Classified_Images' for category in category_rules.keys(): target_dir = os.path.join(base_output_dir, category) os.makedirs(target_dir, exist_ok=True) # 遍历每个源文件夹,处理文件 for folder in source_folders: for filename in os.listdir(folder): file_full_path = os.path.join(folder, filename) # 跳过子文件夹,只处理文件 if not os.path.isfile(file_full_path): continue # 检查文件是否匹配分类规则 matched = False for category, markers in category_rules.items(): if not markers: # 跳过兜底规则,最后统一处理 continue # 判断文件名是否包含任一指定标识 if any(filename.endswith(marker) or marker in filename for marker in markers): target_path = os.path.join(base_output_dir, category, filename) copyfile(file_full_path, target_path) matched = True break # 没匹配到任何规则的文件,放入兜底文件夹 if not matched: target_path = os.path.join(base_output_dir, 'unclassified_images', filename) copyfile(file_full_path, target_path) print("图片分类完成!")
关键改动说明
- 放弃不必要的图片加载:直接操作文件路径和文件名,既避免了numpy数组的类型错误,又节省内存资源。
- 全程保留文件名信息:所有判断操作都针对字符串类型的文件名,
endswith()方法就能正常工作了。 - 灵活的分类规则:用字典定义分类逻辑,后续你想新增分类、调整匹配标识,直接修改字典就行,非常方便。
- 自动创建目标文件夹:用
os.makedirs(..., exist_ok=True)确保目标文件夹存在,不用手动提前创建。 - 兜底处理机制:新增了
unclassified_images文件夹,防止有不符合规则的文件被遗漏。
如果你确实需要加载图片再保存(比如要做预处理)
要是你的需求是先加载图片做处理,再按文件名分类保存,那得修改加载函数,同时保存文件名和图片数据:
import cv2 import os def load_images_with_filenames(folder): image_info_list = [] for filename in os.listdir(folder): img_path = os.path.join(folder, filename) img = cv2.imread(img_path) if img is not None: # 保存(文件名, 图片数组, 原文件路径) image_info_list.append( (filename, img, img_path) ) return image_info_list # 源文件夹列表 source_folders = [ 'C:/Users/shiva/OneDrive/Desktop/WORK/Bildverarbeitung_Reaktion/Pictures/I3te_Reaktion', 'C:/Users/shiva/OneDrive/Desktop/WORK/Bildverarbeitung_Reaktion/Pictures/4te_Reaktion', 'C:/Users/shiva/OneDrive/Desktop/WORK/Bildverarbeitung_Reaktion/Pictures/5te_Reaktion', ] # 加载所有带文件名的图片数据 all_image_info = [] for folder in source_folders: all_image_info.extend(load_images_with_filenames(folder)) # 创建输出文件夹 output_dir = 'C:/Users/shiva/OneDrive/Desktop/WORK/Bildverarbeitung_Reaktion/Classified_Images' os.makedirs(output_dir, exist_ok=True) # 按文件名规则分类保存 for filename, img, _ in all_image_info: if any(filename.endswith(x) for x in ['1550_R_1.jpeg', '1550_N', '.jpeg','.jpg']): target_save_path = os.path.join(output_dir, filename) cv2.imwrite(target_save_path, img)
这样就能正确调用filename.endswith()了,因为filename是实打实的字符串类型。
内容的提问来源于stack exchange,提问作者SHIVANI DEEPAK CHOUDHARY
相关产品推荐
相关产品推荐

