python-旋转矩形根据四个点的矩形框顺序进行方向矫正并裁剪

  方法一:

import cv2
import numpy as np

def order_points(pts,angle):
    # 将四个点按照顺时针顺序排列
    rect = np.zeros((4, 2), dtype="float32")
    
    s = pts.sum(axis=1)
    if angle>0:
    # 左上角的点具有最小的和,右下角的点具有最大的和
      rect[0] = pts[np.argmin(s)]
      rect[2] = pts[np.argmax(s)]
    else:
      rect[0] = pts[np.argmax(s)]
      rect[2] = pts[np.argmin(s)]

    # 计算点的差值
    diff = np.diff(pts, axis=1)
    if angle>0:
      rect[1] = pts[np.argmin(diff)]
      rect[3] = pts[np.argmax(diff)]
    else:
      rect[1] = pts[np.argmax(diff)]
      rect[3] = pts[np.argmin(diff)]

    return rect

import math
def calculate_angle(point1, point2):
    """
    参数:
    point1 (tuple): 第一个点的坐标,形式为 (x, y)。
    point2 (tuple): 第二个点的坐标,形式为 (x, y)。

    返回:
    float: 两点之间的角度,单位为度。
    """
    x1, y1 = point1
    x2, y2 = point2
    dx = x2 - x1
    dy = y2 - y1
    angle = math.degrees(math.atan2(dy, dx))
    return angle

def crop_and_correct(image, pts, angle):
    # 获取顺序排列的点
    # print(pts)
    rect = order_points(pts, angle)
    # print(rect)

    bbox = cv2.minAreaRect(pts)
    (center, (maxWidth, maxHeight), _) = bbox
    maxWidth, maxHeight = int(maxWidth), int(maxHeight)
    # print(maxWidth, maxHeight)

    # 构建变换后的图像的四个点
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype="float32")

    # 计算透视变换矩阵
    M = cv2.getPerspectiveTransform(rect, dst)
    # 进行透视变换
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))

    if calculate_angle(pts[0],center) * angle<0:
        warped = cv2.rotate(warped, cv2.ROTATE_90_CLOCKWISE)
    return warped

import os
import json
image_path = './mengniu_rote/'
save_path='./test_images/cut/'
for img_name in os.listdir(image_path):
  if img_name.endswith('.jpg'):
    print(os.path.join(image_path,img_name))
    image = cv2.imread(os.path.join(image_path,img_name))
    json_file_name = os.path.join(image_path,img_name.split('.')[0] +'.json')
    with open(json_file_name, 'r', encoding='utf-8') as file:
        json_data = json.load(file)
        bboxes = json_data['shapes']#
        # print(bboxes)
        i = 0
        for bbox in bboxes:
          pts = np.array(bbox['points'],dtype=np.float32)
          # print(pts)
          angle = calculate_angle(pts[1],pts[2])
          print(angle)
          rotated_box = crop_and_correct(image, pts,angle)
          img_name_new = img_name.split('.')[0] + '._%d.jpg' %(i)
          i+=1
          cv2.imwrite(save_path+img_name_new,rotated_box)
          print(save_path+img_name)

方法二:

import cv2
import numpy as np
import math

def calculate_angle(point1, point2):
    """
    参数:
    point1 (tuple): 第一个点的坐标,形式为 (x, y)。
    point2 (tuple): 第二个点的坐标,形式为 (x, y)。

    返回:
    float: 两点之间的角度,单位为度。
    """
    x1, y1 = point1
    x2, y2 = point2
    dx = x2 - x1
    dy = y2 - y1
    angle = math.degrees(math.atan2(dy, dx))
    return angle

def crop_and_correct(image, pts, angle):

    bbox = cv2.minAreaRect(pts)
    (center, (maxWidth, maxHeight), _) = bbox
   
    w = math.sqrt(math.pow((pts[0][0]-pts[1][0]),2)+math.pow((pts[0][1]-pts[1][1]),2))
    h = math.sqrt(math.pow((pts[1][0]-pts[2][0]),2)+math.pow((pts[1][1]-pts[2][1]),2)) 
    print('w, h:',w, h)
    if w>h:
       maxWidth, maxHeight = max(int(maxHeight), int(maxWidth)),min(int(maxHeight), int(maxWidth))
    else:
       maxWidth, maxHeight = min(int(maxHeight), int(maxWidth)),max(int(maxHeight), int(maxWidth))
    print('angle:',angle)
    print('maxWidth, maxHeight:',maxWidth, maxHeight)

    # 构建变换后的图像的四个点
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype="float32")

    # 计算透视变换矩阵
    M = cv2.getPerspectiveTransform(pts, dst)
    # 进行透视变换
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))

    return warped

import os
import json
image_path = './test_images/test/'
save_path='./test_images/cut/'
for img_name in os.listdir(image_path):
  if img_name.endswith('.jpg'):
    print(os.path.join(image_path,img_name))
    image = cv2.imread(os.path.join(image_path,img_name))
    json_file_name = os.path.join(image_path,img_name.split('.')[0] +'.json')
    with open(json_file_name, 'r', encoding='utf-8') as file:
        json_data = json.load(file)
        bboxes = json_data['shapes']#
        # print(bboxes)
        i = 0
        for bbox in bboxes:
          pts = np.array(bbox['points'],dtype=np.float32)
          # print(pts)
          angle = calculate_angle(pts[1],pts[2])
       
          rotated_box = crop_and_correct(image, pts,angle)
          img_name_new = img_name.split('.')[0] + '._%d.jpg' %(i)
          i+=1
          cv2.imwrite(save_path+img_name_new,rotated_box)
          print(save_path+img_name)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值