Labelme标注文件,批量resize图片和对应标签,可以得到更多的训练数据
import cv2
import os
import json
def resize_image(image, size):
# 计算新的尺寸,保持宽高比
r = min(size[0] / image.shape[1], size[1] / image.shape[0])
dim = (int(image.shape[1] * r), int(image.shape[0] * r))
# 使用INTER_AREA插值方法进行缩放,适用于缩小图片
resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
return resized, r
def adjust_bounding_boxes(json_file, ratio, output_json_file, new_image_path):
with open(json_file, 'r') as file:
data = json.load(file)
for shape in data['shapes']:
if shape['shape_type'] == 'rectangle':
points = shape['points']
new_points = []
for point in points:
new_x = point[0] * ratio
new_y = point[1] * ratio
new_points.append([new_x, new_y])
shape['points'] = new_points
# 更新图像宽度和高度
data['imageHeight'] = int(data['imageHeight'] * ratio)
data['imageWidth'] = int(data['imageWidth'] * ratio)
# 更新 imagePath 字段
data['imagePath'] = new_image_path
# 将调整后的信息保存到新文件
with open(output_json_file, 'w') as file:
json.dump(data, file, indent=2)
def batch_resize_images_with_bboxes(input_dir, output_dir, labels_dir, output_labels_dir, size):
if not os.path.exists(output_dir):
os.makedirs(output_dir)
if not os.path.exists(output_labels_dir):
os.makedirs(output_labels_dir)
for filename in os.listdir(input_dir):
if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.tiff')):
img_path = os.path.join(input_dir, filename)
img = cv2.imread(img_path)
if img is None:
print(f"Failed to read {img_path}")
continue
resized_img, ratio = resize_image(img, size)
# 构造带有缩放比例后缀的新文件名基础部分
base_name, ext = os.path.splitext(filename)
suffix = f"_scale_{ratio:.2f}".replace('.', '_')
output_base_name = f"{base_name}{suffix}"
# 保存调整大小后的图像
output_img_filename = f"{output_base_name}{ext}"
output_img_path = os.path.join(output_dir, output_img_filename)
cv2.imwrite(output_img_path, resized_img)
print(f"Resized and saved {output_img_path}")
# 获取对应的标签文件名,并应用相同的后缀
label_filename = os.path.splitext(filename)[0] + '.json'
label_path = os.path.join(labels_dir, label_filename)
if os.path.exists(label_path):
output_label_filename = f"{output_base_name}.json"
output_label_path = os.path.join(output_labels_dir, output_label_filename)
# 更新 imagePath 为相对路径或绝对路径,取决于原始文件中的格式
new_image_path = os.path.relpath(output_img_path, start=output_labels_dir)
adjust_bounding_boxes(label_path, ratio, output_label_path, new_image_path)
print(f"Adjusted and saved bounding boxes to {output_label_path}")
#
# 设置你的参数
input_directory = 'test_img' # 输入图片文件夹路径
output_directory = 'Dataset/images' # 输出图片文件夹路径
labels_directory = 'test_labels' # 标签文件夹路径
output_labels_directory = 'Dataset/annotations' # 输出标签文件夹路径
new_size = (1280,720 ) # 新的尺寸(宽度, 高度)
# 执行批量处理
batch_resize_images_with_bboxes(input_directory, output_directory, labels_directory, output_labels_directory, new_size)
这段代码用于批量调整图像大小和相应边界框标注,主要依赖于OpenCV库来处理图像。定义了三个函数:
-
resize_image(image, size)
:根据给定的新尺寸调整图像大小,并保持原始宽高比。使用cv2.INTER_AREA
插值方法缩小图片,该方法在缩小图片时提供了较好的质量。 -
adjust_bounding_boxes(json_file, ratio, output_json_file, new_image_path)
:读取JSON格式的标签文件(假设为矩形边界框),根据图像缩放的比例调整边界框的位置,并更新标签文件中的图像路径、宽度和高度信息,最后将修改后的标签保存到新的JSON文件中。 -
batch_resize_images_with_bboxes(input_dir, output_dir, labels_dir, output_labels_dir, size)
:这是主函数,遍历指定输入目录中的所有图像文件,调用上述两个函数来调整图像大小和对应的边界框,然后将结果保存到指定的输出目录中。
要运行这段代码,请确保你已经安装了所需的库(例如OpenCV)并且设置了正确的输入和输出路径。此外,还需注意以下几点:
- 确保
input_directory
和labels_directory
下的文件名对应正确,即每个图像文件都有一个同名(除了扩展名)的JSON标签文件。 - 如果图像或标签文件位于子目录中,可能需要调整代码以递归地处理这些子目录。
- 图像路径和标签路径的设置应该与你的文件系统结构相匹配,特别是相对路径和绝对路径的选择。
new_size
参数指定了目标图像的宽度和高度,代码会根据这个参数调整所有图像的大小。