场景
异常:Corrupt JPEG data: 2 extraneous bytes before marker 0xd9
python语言,CV2读图像数据集,训练目标检测模型。在数据集分批送入模型训练过程中,出现大片图片异常情况。
(建议直接去看修复图像方法二,简单直接)
原因分析
在 python 中导入python-opencv库,读图难以检测到这个问题
-
产生图像读取异常的主要原因:图像数据在读取时,因为图像格式问题,解析含有data[0]数据段时,若data[0]后面还有其他字段,需要加上data[0]的实际长度才能赋值后面的字段,否则会覆盖data[0]中相关字段。
-
由于数据集中图像损坏或不完整的 jpeg 图像引起的低级 C 错误,opencv报的warning,在 python 中难以检测到。
3.可能是图像截取或微信下载的时候,命名导致,或重命名图像造成格式上的不对应。
解决办法
使用yolov训练数据集时,出现该错误,不影响训练流程,程序会自动跳过错误的数据。所以,会中断异常的batch,跳过后正常训练。但是,毕竟缺太多关键数据,感觉对不起标注时的付出。所以,想到一个笨办法来解决这个问题,修复图像。
解决步骤:
1)复现异常,找出问题图像。
因为训练数据集图像很多,几千张,要找出来不容易。它在python里面是一个警告,需要用CV2读图的时候才会爆出这个异常。我这里有个笨办法:用手动二分法和cv2.imread读图来定位图像。
def checkImg(dirPath):
for fileName in os.listdir(dirPath):
filePath = Path(os.path.join(dirPath, fileName))
if filePath.suffix.lower() in [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff"]: # 图片扩展名
try:
img = cv2.imread(os.path.join(dirPath, fileName))
except cv2.error as e:
print("图片损坏,图片名称:", fileName, e)
a.
输入图像数据集所在路径path1,运行checkImg。问题图像有多少,就会打印到多少个异常警告。
因为,图像有这个问题,不会终止,会pass,继续下一个。所以需要手动分数据,手动二分法找数据。如果有1000张图,有一张有问题,则需要分10次(2的10次方=1024)。
b.
然后,另外建立一个文件夹path2。分一半数据过去。
再运行checkImg(路径不变)。
如图,证明剩下的文件path1里面还有一张问题图像。
c.
再建一个文件夹path3,分一半数据出去。
再运行checkImg(路径不变)。
如图,证明该路径path1的图片都是正常的,可以设置文件夹名称为ok。有异常的那一张图在刚分出去的路径path3里面。将path3里的数据分一半到path4。
d.
再运行checkImg(path3)
…
一直循环,直到找出问题图像。(1000张图,找10次;2000张,要重复找11次)
将所有有问题的图像归集到bug文件夹。
2)修复图像。
修复图像方法有两种。
方法一:利用photoshop另存图像数据,达到修复的目的。
a.
打开Photoshop(简称ps),选中所有问题图像,全部拉到ps窗口。
b.
选中一个目标,导航菜单处,点击文件,存储为(A),存储替换图像。
c.
保存,替换。
d.
确定。
e.
所有的问题图都重新存储一遍。
f.
然后,执行checkImg(bug),检查所有图像是否修复。
修复完毕。完美。
方法二、用py-opencv直接批量另存问题图像。可以直接用代码,好的坏的全部另存,不用手动查找问题图像。
def convertImg(dirPath):
# 修复图像另存地址。没有该文件夹就创建。
saveDir = r"D:\...\Datasets\HeightBuildingUnderConstruction2023\measureBuildingHeightwith3mRuler\testImage\checkImg\xiufu"
if not os.path.exists(saveDir):
os.makedirs(saveDir)
# 遍历有问题的数据文件夹,中找到所有的图片。
for fileName in os.listdir(dirPath):
filePath = Path(os.path.join(dirPath, fileName))
if filePath.suffix.lower() in [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff"]: # 图片扩展名
try:
img = cv2.imread(os.path.join(dirPath, fileName)) # 读图像数据
new_path = os.path.join(saveDir, fileName)
cv2.imwrite(new_path, img) # 另存同名,同扩展名图像。不破坏数据集
except cv2.error as e:
print("图片损坏,图片名称:", fileName, e)
print("全部图像已另存!")
a.
运行convertImg(bug),将问题图像所在文件夹地址作为输入。
图像表示,该文件夹有四个问题图像。且修复后的图像保存与xiufu文件夹了。
b.
验证是否修复。
执行,checkImg(xiufu)
证明,修复完成。
小结
做人工智能计算机视觉算法工程师几年了,每每出现Corrupt JPEG data: 2 extraneous bytes before marker 0xd9,我都选择飘过,今天终于把问题解决了
- 遇到问题,简单分析,不熟悉的bug直接找百度,看看各大博主是怎么做的。
- 找不到答案,只能靠自己,不管是方法笨不笨,解决了问题总归是在进度!
感谢点赞收藏+关注的朋友!!