您的当前位置:首页正文

对指定文件夹中的图像进行裁剪,并根据裁剪后的图像尺寸调整标签坐标

2024-11-10 来源:个人技术集锦

说明:工作中,有时需要处理一批已经标注好的yolo格式的数据集,例如图片裁剪了,相应的标签应该得与裁剪后的图片呼应上,就是框的坐标应同裁剪图像一样作出相应的处理,使得处理后的标签文件里的框坐标能对应上裁剪后的图。

代码如下:

import os  #导入os模块,用于操作文件和文件夹
import cv2  #导入OpenCV库,用于图像处理。

def convert_coordinates(x, y, w, h, img_width, img_height):  #定义一个函数,用于将相对坐标转换为绝对坐标。
    # 将yolo格式的坐标转换为像素坐标
    left = int((x - w / 2) * img_width)
    top = int((y - h / 2) * img_height)
    right = int((x + w / 2) * img_width)
    bottom = int((y + h / 2) * img_height)
    print("left,top,right,bottom:", left,top,right,bottom)
    return left, top, right, bottom

def crop_image(image_path, label_path, output_folder):  #定义一个函数,用于裁剪图像并调整标签坐标。
    # 读取图片
    image = cv2.imread(image_path)  #读取图像文件。
    img_height, img_width, _ = image.shape  # 获取图像的高度和宽度。
    print("yuantu:",image.shape)

  #裁剪图像,将图像高度从y1到y2,宽度从x1到x2的区域提取出来。根据你要裁的坐标改x1,y1,x2,y2的值
    x1 = 300  #左上角坐标(x1,y1)
    y1 = 0
    x2 = 1600  #右下角坐标(x2,y2)
    y2 = 1080
    cropped_image = image[y1:y2, x1:x2]  # 对读取的原始图片裁剪
    print("caihou:",cropped_image.shape)

    # 保存裁剪后的图片
    image_name = os.path.basename(image_path)  #获取图像文件名。
    output_path = os.path.join(output_folder, image_name)  #构建输出图像路径。
    cv2.imwrite(output_path, cropped_image)  #将裁剪后的图像保存到输出路径。

    # 读取对应的标签文件
    label_name = os.path.splitext(image_name)[0] + ".txt"  #构建标签文件名。
    label_file = open(os.path.join(label_path, label_name), "r")  #打开标签文件。

    # 转换标签坐标并保存到新的标签文件中
    new_label_path = os.path.join(output_folder, "new_labels_txt")  #构建新标签文件夹路径。
    os.makedirs(new_label_path, exist_ok=True)  #创建新标签文件夹。
    new_label_file = open(os.path.join(new_label_path, label_name), "w")  #创建新标签文件。

    for line in label_file:   #遍历标签文件中的每一行。
        class_id, x, y, w, h = map(float, line.strip().split())  #解析每一行的标签信息。
        left, top, right, bottom = convert_coordinates(x, y, w, h, img_width, img_height)  #将相对坐标转换为绝对坐标。
        if left >= x1 and right <= x2:   #判断目标框是否在裁剪区域内。
            # 转换裁剪后的坐标
            left -= x1  #调整目标框的左坐标。
            right -= x1  #调整目标框的右坐标。
            new_x = format((left + (right - left) / 2) / (x2 - x1), '6f') #计算调整后的目标框中心点的x坐标。
            new_y = format((top + (bottom - top) / 2) / (y2 - y1), '6f') #计算调整后的目标框中心点的y坐标。
            new_w = format((right - left) / (x2 - x1), '6f')  #计算调整后的目标框的宽度。
            new_h = format((bottom - top) / (y2 - y1), '6f')   #计算调整后的目标框的高度。
            # 保存新的标签坐标
            new_label_file.write(f"{int(class_id)} {new_x} {new_y} {new_w} {new_h}\n")  #写入调整后的标签信息到新标签文件。
            print("new_x,new_y,new_w,new_h:",new_x,new_y,new_w,new_h)

    label_file.close()  #关闭标签文件。
    new_label_file.close()  #关闭新标签文件。

if __name__ == "__main__": 
    image_folder = "E:/images"  #图像文件夹路径。
    label_folder = "E:/labels"   #标签文件夹路径。
    output_folder = "E:/caihou"   #输出文件夹路径。
    # 获取所有图片文件路径
    image_files = [f for f in os.listdir(image_folder) if f.endswith(".jpg")]  #获取图像文件夹中所有以".jpg"结尾的文件。

    # 对每张图片进行裁剪和标签转换
    for image_file in image_files:   #遍历图像文件列表。
        image_path = os.path.join(image_folder, image_file)   #构建图像文件路径。
        crop_image(image_path, label_folder, output_folder)   #调用裁剪图像函数,对图像进行裁剪和标签调整。

最后用labelimg检查裁后的图和对应的标签框。

Top