原图labelme标注
使用以下程序,裁剪labelme的json不规则多边形标签保存成矩形图像
import os
import cv2
import math
import json
import numpy as np
from PIL import Image, ImageDraw
def calculate_bounding_box(points):
"""计算多边形的最小外包矩形"""
min_x = min(point[0] for point in points)
min_y = min(point[1] for point in points)
max_x = max(point[0] for point in points)
max_y = max(point[1] for point in points)
return min_x, min_y, max_x, max_y
def crop_and_rectify_polygon(image_path, json_path, output_dir=None):
"""根据JSON标注读取不规则四边形 并转换为规则矩形图像"""
with Image.open(image_path) as img:
img_width, img_height = img.size
with open(json_path, 'r') as f:
data = json.load(f)
if not output_dir:
output_dir = os.path.dirname(image_path)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for idx, shape in enumerate(data['shapes'], start=1):
# 确保处理的是不规则四边形
if len(shape['points']) != 4:
continue
label = shape['label']
# if "ocr_" in label or "smg_" in label:
if label=="车牌":
# 计算不规则四边形的长边和短边长度
x1, y1, x2, y2 = calculate_bounding_box(shape['points'])
# 裁剪图像
cropped_img = img.crop((x1, y1, x2, y2))
# 保存裁剪后的图像
output_filename = f"{os.path.splitext(os.path.basename(image_path))[0]}_{label}_{idx}_cropped.jpg"
output_path = os.path.join(output_dir, output_filename)
cropped_img.save(output_path)
print(f"裁剪完成并保存至: {output_path}")
if __name__ == '__main__':
image_path = '1.jpg'
json_path = '1.json'
crop_and_rectify_polygon(image_path, json_path, output_dir="./")
效果图
使用以下程序,裁剪labelme的json不规则多边形标签保存成矩形图像
增加了放射变换
def perspective_transform(image_path, pts, output_size=(500, 500)):
"""
对图像中的四边形区域进行透视变换,矫正为规则矩形。
:param image_path: 图像路径
:param pts: 四边形的四个顶点坐标,顺序为[(top_left), (top_right), (bottom_right), (bottom_left)]
:param output_size: 输出图像的尺寸,默认为(500, 500)
:return: 矫正后的图像
"""
# 读取图像
img = cv2.imread(image_path)
height, width = img.shape[:2]
# 四边形顶点坐标调整为浮点数,并确保正确的顺序
src = np.array(pts, dtype=np.float32)
# 目标矩形的顶点坐标,即输出图像的四个角
dst = np.array([
[0, 0],
[output_size[0], 0],
[output_size[0], output_size[1]],
[0, output_size[1]]
], dtype=np.float32)
# 计算透视变换矩阵
M = cv2.getPerspectiveTransform(src, dst)
# 执行透视变换
warped = cv2.warpPerspective(img, M, output_size)
return warped
def calculate_bounding_wh(points):
"""计算四边形的边长"""
w1 = math.dist(points[0], points[1])
h1 = math.dist(points[1], points[2])
w2 = math.dist(points[2], points[3])
h2 = math.dist(points[3], points[0])
return int(max(w1,w2)), int(max(h1,h2))
def crop_and_perspective_polygon(image_path, json_path, output_dir=None):
"""根据JSON标注读取不规则四边形 并放射变换为规则矩形图像"""
with open(json_path, 'r') as f:
data = json.load(f)
if not output_dir:
output_dir = os.path.dirname(image_path)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for idx, shape in enumerate(data['shapes'], start=1):
# 确保处理的是不规则四边形
if len(shape['points']) != 4:
continue
label = shape['label']
# if "ocr_" in label or "smg_" in label:
if label=="车牌":
print(shape['points'])
# 计算最小外包矩形
w, h = calculate_bounding_wh(shape['points'])
# 仿射变换
corrected_image = perspective_transform(image_path, shape['points'], output_size=(w, h))
# 保存裁剪后的图像
output_filename = f"{os.path.splitext(os.path.basename(image_path))[0]}_{label}_{idx}_perspective_cropped.jpg"
output_path = os.path.join(output_dir, output_filename)
cv2.imwrite(output_path, corrected_image)
print(f"裁剪完成并保存至: {output_path}")
if __name__ == '__main__':
image_path = '1.jpg'
json_path = '1.json'
crop_and_perspective_polygon(image_path, json_path, output_dir="./")
效果图