批量旋转数据集图像后保存多数为黑图的原因及解决方法
批量旋转图像保存为黑图的原因及修复方案
问题产生原因
- 核心原因:数值类型与范围不匹配。
skimage.transform.rotate输出的图像是值范围在[0,1]的float64类型数组,但OpenCV的cv.imwrite保存8位PNG图像时,要求输入为值范围[0,255]的uint8类型数组。直接传入[0,1]范围的浮点数时,浮点数转uint8会直接舍弃小数部分,0~1之间的像素值几乎全部被转换为0,最终输出全黑图像。 - 代码缩进错误:图像读取、旋转的逻辑仅在文件后缀为.png时执行,但重命名、预览、保存的逻辑写在了if判断外部。会导致非png文件被遍历时,直接复用上一次循环生成的旋转结果,出现大量重复错误文件;如果首个遍历到的文件不是png,还会直接触发变量未定义的报错。
- 文件名生成逻辑错误:使用
file.split('.jpg')[0]截取无后缀文件名,但处理对象是.png格式文件,png文件名中不存在'.jpg'子串,split不会生效,最终生成的文件名会残留原.png后缀,命名混乱。 - GUI逻辑不合理:循环内每处理一张图就调用
cv.destroyAllWindows(),搭配cv.waitKey(1)极短的等待时间,既无法正常预览图像,还容易触发OpenCV GUI异常。 - 可选注意点:
transform.rotate默认保持原图像尺寸,旋转后超出原画布的图像部分会被裁剪,边角默认填充黑色,若需要保留完整旋转后图像需要额外加参数,该问题不会导致全黑,但会影响旋转效果。
修复方法
- 旋转完成后,将[0,1]范围的浮点型图像转换为[0,255]范围的uint8类型,再交给OpenCV保存。
- 修正代码缩进,将重命名、保存逻辑全部移入.png后缀判断的代码块内,保证逐文件读取、逐文件处理、逐文件保存。
- 用
os.path.splitext(file)[0]获取不带后缀的原文件名,兼容所有后缀格式,避免命名错误。 - 批量处理时如果不需要实时预览,可以直接删除imshow、waitKey、destroyAllWindows相关代码;如果需要预览,把窗口销毁逻辑移到整个循环结束后。
- 如果需要保留旋转后的完整图像,给
transform.rotate传入resize=True参数。
修正后可运行代码
import os import cv2 as cv import numpy as np from skimage import transform path = r'Enhanced/train/NORMAL' save_path = r"Enhanced/train/NORMAL" for dirName, subdirList, fileList in os.walk(path): for file in fileList: # 只处理png文件 if file.endswith(".png"): full_file_path = os.path.join(dirName, file) # 读入灰度图 image = cv.imread(full_file_path, cv.IMREAD_GRAYSCALE) # 旋转图像,需要保留完整图像可加resize=True transformed_image = transform.rotate(image, angle=45, resize=True) # 转换数值范围和类型,适配OpenCV保存要求 transformed_image = (transformed_image * 255).astype(np.uint8) # 正确生成无后缀文件名 file_name_without_ext = os.path.splitext(file)[0] new_filename = f"{file_name_without_ext}_rotation45.png" # 保存图像 cv.imwrite(os.path.join(save_path, new_filename), transformed_image)
注:如果不需要旋转后自动调整画布大小保留完整图像,把
transform.rotate里的resize=True删掉即可。
内容的提问来源于stack exchange,提问作者Unknown
相关产品推荐
相关产品推荐

