PCA 在图像分析上的应用

同一物体旋转角度求取

直接上代码:

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)

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AICVer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值