直接上代码:
import cv2, os
import numpy as np
import time
def perform_pca(image, num_components):
# 将图像转换为浮点型
img_float = np.float32(image)
img_flatten = img_float.reshape(-1, 2)
# 计算均值和协方差矩阵
mean, eigenvectors = cv2.PCACompute(img_flatten, mean=None, maxComponents=num_components)
return mean, eigenvectors
def rotate_coords(coords, theta):
"""
绕原点旋转坐标点集。
参数:
coords: 坐标点集,每个元素是一个(x, y)的元组。
theta: 旋转角度,以弧度为单位。
返回:
旋转后的坐标点集。
"""
# 定义旋转矩阵
rotation_matrix = np.array([[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]])
# 将坐标点集转换为NumPy数组以便进行矩阵运算
coords_array = np.array(coords)
# 应用旋转矩阵
rotated_coords = np.dot(coords_array, rotation_matrix)
return rotated_coords
def judge_direction1(mean, vector, center_x, center_y):
v = np.array([center_x - mean[0][0], center_y - mean[0][1]])
if np.dot(v, vector) < 0:
vector = -vector
return vector
def judge_direction2(mean, vector, image, img_path):
edge_image = cv2.Canny(image, 50, 200)
file_name = img_path.split("/")[-1]
save_path = "/home/xxx/下载/mask/result/"
x_angle = vector_angle(vector,np.array([1, 0]))
edge_non_zero_coords = cv2.findNonZero(edge_image)
edge_non_zero_coords = edge_non_zero_coords - mean[0]
edge_non_zero_coords = rotate_coords(edge_non_zero_coords, np.radians(x_angle))
min_x, min_y = np.min(edge_non_zero_coords, axis=0)[0]
max_x, max_y = np.max(edge_non_zero_coords, axis=0)[0]
new_image = np.zeros((int(max_y-min_y)+1, int(max_x - min_x)+1), np.uint8)
for coord in edge_non_zero_coords:
x, y = coord[0]
new_image[int(y - min_y), int(x - min_x)] = 255
# cv2.imwrite(save_path + file_name, new_image)
if max_x - min_x > max_y - min_y:
if abs(max_x) > abs(min_x):
vector = -vector
else:
if abs(max_y) > abs(min_y):
vector = -vector
return vector
def get_vector(img_path):
image = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
h, w = image.shape
center_x = int(w / 2)
center_y = int(h / 2)
non_zero_coords = cv2.findNonZero(image)
# 执行PCA
num_components = 2
mean, eigenvectors = perform_pca(non_zero_coords, num_components)
vector = eigenvectors[0]
vector = judge_direction2(mean, vector, image, img_path)
return vector
def vector_angle(v1, v2):
# 计算点积
dot_product = np.dot(v1, v2)
# 计算向量的模
norm_v1 = np.linalg.norm(v1)
norm_v2 = np.linalg.norm(v2)
# 计算余弦值
cos_theta = dot_product / (norm_v1 * norm_v2)
# 计算弧度制的夹角
theta_rad = np.arccos(np.clip(cos_theta, -1.0, 1.0))
# 将弧度制转换为角度制
theta_deg = np.degrees(theta_rad)
# 确定角度的方向性
cross_product = np.cross(v1, v2)
if cross_product < 0:
theta_deg = 360 - theta_deg
return 360 - theta_deg
def get_angle(img_path1, img_path2):
vector1 = get_vector(img_path1)
vector2 = get_vector(img_path2)
angle = vector_angle(vector1, vector2)
print(vector1, vector2, angle)
return angle
if __name__ == "__main__":
img_path1 = "/home/xxx/下载/mask/mask3/0.jpg"
img_path2 = "/home/xxx/下载/mask/mask3/32.jpg"
get_angle(img_path1, img_path2)