神经网络训练数据生成器报NoneType与float除法不支持的TypeError
报错原因与修复方案
直接触发报错的原因:cv2.imread() 读取文件失败时会返回None,无效的None值被添加到批次列表后,转换得到的numpy数组为object类型,无法直接与浮点数做除法运算,因此触发TypeError。
引发图片读取失败的常见原因及对应修复点:
- 过滤非图片文件:
os.listdir()会返回目录下所有子项,包括文件夹、非图片格式文件、隐藏文件,需要先筛选后缀为jpg、png等合法图片格式的文件再参与后续逻辑 - 校验输入输出文件配对关系:
i_list和o_list是分别调用os.listdir()得到的,两个列表的排序规则默认不一定完全一致,直接用相同下标m取值会出现配对错误,建议先对两个列表按文件名排序,或者校验输入输出文件名完全一致后再配对 - 增加读取有效性校验:读取图片后先判断是否为
None,过滤无效数据,示例逻辑如下:input_image = cv2.imread(path_to_in_img) output_image = cv2.imread(path_to_out_img) if input_image is None or output_image is None: print(f"读取失败,跳过文件:{path_to_in_img} | {path_to_out_img}") continue - 修复拼写错误:代码中
outputput_val2image_array多输入了一个t,会导致后续返回时变量未定义 - 调整归一化逻辑位置:当前归一化逻辑写在for循环内部,每添加一张图片就重复做一次归一化,属于冗余操作,可以移到for循环外部,整个批次组装完成后再统一处理
yield生成器内部数据查看方法
使用yield实现的生成器可以查看内部数据,常用两种方案:
- 迭代取值:生成器是可迭代对象,可以用
next()函数单次获取一个批次,或者用for循环遍历所有批次,拿到返回的批次数据后即可直接查看内容,比如打印数组形状、可视化图片等 - 嵌入调试日志:在yield语句之前添加打印逻辑,输出当前的文件路径、批次大小、数组形状等中间信息,不需要修改生成器核心逻辑就能获取内部运行状态
修改后的yield版本生成器示例:
import os import numpy as np import cv2 def generator(idir, odir, batch_size, shuffle): # 先筛选并配对输入输出文件 i_list = sorted([f for f in os.listdir(idir) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]) o_list = sorted([f for f in os.listdir(odir) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]) # 校验文件数量一致 assert len(i_list) == len(o_list), "输入输出目录文件数量不匹配" sample_count = len(i_list) batch_index = 0 while True: # 训练用生成器需要循环生成批次 input_image_batch = [] output_image_batch = [] for i in range(batch_index * batch_size, (batch_index + 1) * batch_size): j = i % sample_count if shuffle: m = np.random.randint(low=0, high=sample_count) else: m = j path_to_in_img = os.path.join(idir, i_list[m]) path_to_out_img = os.path.join(odir, o_list[m]) # 校验文件名一致(可选) assert os.path.basename(path_to_in_img) == os.path.basename(path_to_out_img), "文件配对错误" input_image = cv2.imread(path_to_in_img) output_image = cv2.imread(path_to_out_img) if input_image is None or output_image is None: print(f"跳过无效文件:{path_to_in_img}") continue input_image = cv2.resize(input_image, (3200, 3200)) output_image = cv2.resize(output_image, (3200, 3200)) input_image_batch.append(input_image) output_image_batch.append(output_image) # 批次组装完成后统一处理 input_val1image_array = np.array(input_image_batch) / 255.0 output_val2image_array = np.array(output_image_batch) / 255.0 batch_index += 1 yield input_val1image_array, output_val2image_array # 查看生成器数据示例 idir = r"D:\\validation" odir = r"D:\\UAV\\validation" train_gen = generator(idir, odir, 5, True) # 取第一个批次查看 batch_x, batch_y = next(train_gen) print(batch_x.shape, batch_y.shape)
内容的提问来源于stack exchange,提问作者user123
相关产品推荐
相关产品推荐

