方法一:
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)