该段代码的应用场景为对图像标注过后,想要对图像进行裁切,但是标签不能裁切,所以将原图像按照标签进行二值化后,将二值化后的图像进行裁切,然后使用opencv对裁切后的图像进行处理,识别出白色区域轮廓,并保存坐标信息(YOLOv8图像分割标注格式)
import os
import cv2
import numpy as np
'''
该段代码读取文件夹中的二值图像,输出白色区域的标注信息
格式为YOLOv8图像分割的txt格式
'''
def process_images(input_folder, output_folder):
# 如果输出文件夹不存在,则创建它
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 列出输入文件夹中的所有图像文件
image_files = [f for f in os.listdir(input_folder) if f.endswith(('.png', '.jpg', '.jpeg', '.bmp'))]
total_images = len(image_files)
print(f"在文件夹'{input_folder}'中找到了 {total_images} 张图像。")
# 处理每张图像
for idx, filename in enumerate(image_files, 1):
print(f"正在处理图像 {idx} / {total_images} : {filename}")
# 加载图像
image_path = os.path.join(input_folder, filename)
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
# 检查图像是否正确加载
if image is None:
print(f"图像 {filename} 未能正确加载。")
continue
# 对图像进行阈值处理以获得二值图像
_, binary_image = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)
# 寻找轮廓
contours, _ = cv2.findContours(binary_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 初始化一个列表来存储轮廓坐标
contour_coordinates = []
# 获取图像的尺寸以进行归一化
height, width = image.shape
# 遍历轮廓以提取归一化坐标
for contour in contours:
# 初始化一个列表来存储单个轮廓的坐标
coords = ['0'] # 开头的数字0(没有小数点)
for point in contour:
# 归一化x和y坐标并添加到列表中
x_normalized = point[0][0] / width
y_normalized = point[0][1] / height
coords.extend([f"{x_normalized:.6f}", f"{y_normalized:.6f}"])
# 将单个轮廓的坐标添加到主列表中
contour_coordinates.append(' '.join(coords))
# 定义输出文本文件的路径
output_file_path = os.path.join(output_folder, os.path.splitext(filename)[0] + '.txt')
# 将坐标写入文本文件
with open(output_file_path, 'w') as file:
file.write('\n'.join(contour_coordinates))
# 输入和输出文件夹路径(请替换为实际路径)
input_folder_path = './test_label_pre' # 替换为实际的输入文件夹路径
output_folder_path = './test_labels' # 替换为实际的输出文件夹路径
# 调用函数以处理图像
process_images(input_folder_path, output_folder_path)
示例:
输入图像:
输出信息:
YOLOv8训练所需的txt标注信息: