一、清理非图片数据
分析数据集信息。遍历data目录中所有图片,对于每个图片,通过 is_image()
函数来确定是否为图片文件,将不是的直接删除,统计图片文件的数量。通过尝试打开每个图片文件,使用 Image.open()
和 img.load()
方法来检测文件是否完好,如果文件无法打开则将其视为破损图片,最终返回数据集图片数量和破损图片的数量。
# 定义函数,获取指定目录下的数据集信息
def get_data_info(dir_path):
size = 0 # 初始化数据集总大小变量
number = 0 # 初始化图片数量变量
bad_number = 0 # 初始化破损图片数量变量
# 遍历指定目录及其子目录下的所有文件和文件夹
for root, dirs, files in os.walk(dir_path):
# 筛选出当前目录中的所有图片文件
img_files = [file_name for file_name in files if is_image(file_name)]
# 计算当前目录中所有图片文件的总大小
files_size = sum([os.path.getsize(os.path.join(root, file_name)) for file_name in img_files])
# 统计当前目录中的图片文件数量
files_number = len(img_files)
# 累加总大小和图片数量
size += files_size
number += files_number
# 检查每个图片文件的完整性
for file in img_files:
try:
# 尝试打开并加载图片数据
img = Image.open(os.path.join(root, file))
img.load()
except OSError:
# 如果捕获到 OSError 异常,则增加破损图片数量计数
bad_number += 1
# 返回结果:图片数量、破损图片数量
return size / 1024 / 1024, number, bad_number
二、去除损坏图片
检测并移除损坏图片文件。通过递归所有的图片文件,对每个图片文件,通过尝试打开并加载图像数据的方式,使用 PIL.Image.open().load()
方法来验证文件是否完好。如果打开过程中出现异常,则将该图片文件移动到损坏文件新目录中,同时记录损坏图片的数量。最终返回筛选出的损坏图片数量。
# 定义函数,用于去除已损坏的图片文件
def filter_bad(dir_path):
# 创建用于存放筛选后图片的目录
filter_dir = os.path.join(os.path.dirname(dir_path), 'filter_bad')
# 如果目录不存在,则创建它
if not os.path.exists(filter_dir):
os.mkdir(filter_dir)
# 初始化筛选计数器
filter_number = 0
# 遍历目录及其子目录下的所有文件和文件夹
for root, dirs, files in os.walk(dir_path):
# 筛选出当前目录下的所有图片文件
img_files = [file_name for file_name in files if is_image(file_name)]
# 遍历每个图片文件
for file in img_files:
# 获取图片文件的完整路径
file_path = os.path.join(root, file)
try:
# 尝试打开并加载图片文件,用于检测其是否损坏
Image.open(file_path).load()
except OSError:
# 如果损坏,则将其移动到损坏目录中
shutil.move(file_path, filter_dir)
# 增加筛选计数器
filter_number += 1
# 返回被筛选出的损坏图片数量
return filter_number
三、去除过于模糊图片
从数据集中识别和移除过于模糊的图片文件。首先递归遍历目录树,筛选出所有的图片文件。对于每个图片文件,使用 OpenCV 的 imdecode 函数读取图片数据,并计算图片的拉普拉斯变换方差,根据拉普拉斯变换方差判断图片模糊性,模糊图片被移动到模糊图片的新目录中,并且记录移除的模糊图片数量。
# 去除过于模糊图片
def filter_blurred(dir_path):
# 创建一个目录用于存放被移除的模糊图片
filter_dir = os.path.join(os.path.dirname(dir_path), 'filter_blurred')
if not os.path.exists(filter_dir):
os.mkdir(filter_dir)
# 初始化计数器,用于统计被移除的模糊图片数量
filter_number = 0
# 使用os.walk递归遍历指定目录dir_path及其子目录
for root, dirs, files in os.walk(dir_path):
# 获取当前目录下的所有图片文件名
img_files = [file_name for file_name in files if is_image(file_name)]
# 遍历每个图片文件
for file in img_files:
# 构建图片文件的完整路径
file_path = os.path.join(root, file)
# 使用OpenCV的imdecode函数读取图片
img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)
# 计算图片的拉普拉斯变换方差,用来衡量图片的清晰度
image_var = cv2.Laplacian(img, cv2.CV_64F).var()
# 如果图片的拉普拉斯方差小于100,认为图片过于模糊
if image_var < 100:
# 将该图片移动到filter_blurred目录中
shutil.move(file_path, filter_dir)
# 增加过滤掉的模糊图片数量计数
filter_number += 1
# 返回过滤掉的模糊图片数量
return filter_number
四、去除重复图片
经过观察,数据集中存在部分重复图片信息,影响训练效率和准确度。比较两张图片在大小、尺寸和内容上是否完全相同,如果大小、尺寸和内容都相同,则去除一张图片;否则返回两张图片。
def 比较图片大小(dir_image1, dir_image2):
# 读取图片文件1的字节大小
with open(dir_image1, "rb") as f1:
size1 = len(f1.read())
# 读取图片文件2的字节大小
with open(dir_image2, "rb") as f2:
size2 = len(f2.read())
# 比较两张图片的字节大小是否相同
if size1 == size2:
result = "大小相同"
else:
result = "大小不同"
return result
def 比较图片尺寸(dir_image1, dir_image2):
# 使用PIL库打开图片1和图片2
image1 = Image.open(dir_image1)
image2 = Image.open(dir_image2)
# 比较两张图片的尺寸是否相同
if image1.size == image2.size:
result = "尺寸相同"
else:
result = "尺寸不同"
return result
def 比较图片内容(dir_image1, dir_image2):
# 使用PIL库和numpy打开并转换图片1和图片2为数组
image1 = np.array(Image.open(dir_image1))
image2 = np.array(Image.open(dir_image2))
# 比较两张图片的内容(每个像素是否相同)
if np.array_equal(image1, image2):
result = "内容相同"
else:
result = "内容不同"
return result
def 比较两张图片是否相同(dir_image1, dir_image2):
# 比较两张图片是否相同的主函数
result = "两张图不同"
# 第一步:比较大小是否相同
大小 = 比较图片大小(dir_image1, dir_image2)
if 大小 == "大小相同":
# 第二步:比较尺寸是否相同
尺寸 = 比较图片尺寸(dir_image1, dir_image2)
if 尺寸 == "尺寸相同":
# 第三步:比较内容是否相同
内容 = 比较图片内容(dir_image1, dir_image2)
if 内容 == "内容相同":
result = "两张图相同"
return result
五、去除无字体图片
部分图片因为截取问题与旋转问题,并未包含需要识别字体部分,我们对这部分内容进行删除,从而提高模型训练效率和准确度。
# 定义一个函数,判断图片是否包含文字
def contains_text(image_path):
try:
text = pytesseract.image_to_string(Image.open(image_path))
return len(text.strip()) > 0 # 如果识别出文字,则返回 True
except:
return False # 出现任何异常(包括无法打开图片),则返回 False
# 定义一个函数,遍历目录下的所有图片文件,并删除识别不出文字的图片
def delete_images_without_text(dir_path):
for root, dirs, files in os.walk(dir_path):
for file in files:
if file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp')):
image_path = os.path.join(root, file)
if not contains_text(image_path):
os.remove(image_path) # 删除没有文字的图片
print(f"Deleted: {image_path}") # 打印已删除的图片路径
清理后图片数据
六、总结
经过以上数据清洗工作,删去了大量无用图片,实现了对图片数据集的降维,有利于提高模型训练的效率和准确度,获得更好识别效果。