机器学习进阶<7>人脸识别特征锚点Python实现

前言

本项目展示了径向基函数网络(RBFN)在人脸识别中的应用思想。通过这个项目,你将理解如何将复杂的人脸用几个关键"锚点"来表示,并利用特征点到这些锚点的距离进行人脸分析和相似度比较。

第1步:环境准备

导入库和基本设置

python 复制代码
import cv2          # 图像处理
import numpy as np  # 数学计算
import matplotlib.pyplot as plt  # 绘图
from scipy.spatial import distance  # 计算距离
import warnings
warnings.filterwarnings('ignore')  # 忽略警告信息

# 设置中文字体(让图表能显示中文)
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False  # 正确显示负号

解释

  • cv2:用于绘制和操作图像

  • numpy:处理数学运算和数组

  • matplotlib:绘制各种图表

  • scipy.spatial.distance:计算点与点之间的距离

第2步:创建合成人脸

2.1 创建人脸轮廓

python 复制代码
def create_synthetic_face():
    # 创建400×400像素的空白图像(浅灰色背景)
    width, height = 400, 400
    image = np.zeros((height, width, 3), dtype=np.uint8)
    image.fill(240)  # 填充浅灰色
    
    # 在图像中心绘制椭圆形脸
    face_center = (width // 2, height // 2)  # 中心点(200,200)
    cv2.ellipse(image, face_center, (120, 150), 0, 0, 360, (255, 220, 180), -1)
    # 参数解释:(图像, 中心点, (横轴半径,纵轴半径), 旋转角度, 起始角度, 结束角度, 颜色, 厚度)

2.2 添加面部特征

python 复制代码
    # 添加眼睛(对称位置)
    left_eye_center = (face_center[0] - 50, face_center[1] - 30)   # 左眼
    right_eye_center = (face_center[0] + 50, face_center[1] - 30)  # 右眼
    
    # 绘制左眼:白色眼球+黑色瞳孔
    cv2.circle(image, left_eye_center, 20, (255, 255, 255), -1)  # 白色眼球
    cv2.circle(image, left_eye_center, 20, (0, 0, 0), 2)         # 黑色边框
    cv2.circle(image, left_eye_center, 8, (0, 0, 0), -1)         # 黑色瞳孔
    # 右眼同理...

2.3 定义关键"锚点"

锚点概念:就像地图上的地标,用它们作为参考点来描述整个面部的特征位置。

python 复制代码
    # 定义5个关键锚点
    key_points = {
        'left_eye': left_eye_center,      # 左眼中心
        'right_eye': right_eye_center,    # 右眼中心
        'nose': nose_tip,                  # 鼻尖
        'left_mouth': (mouth_center[0] - 30, mouth_center[1]),   # 左嘴角
        'right_mouth': (mouth_center[0] + 30, mouth_center[1])   # 右嘴角
    }

2.4 生成特征点

在锚点周围生成一些随机点,模拟面部细节特征:

python 复制代码
    # 设置随机种子(确保每次运行结果一致)
    np.random.seed(42)
    feature_points = {}
    
    # 为每个锚点生成5个特征点
    for name, center in key_points.items():  # 遍历5个锚点
        for j in range(5):  # 每个锚点生成5个点
            # 在锚点周围随机生成位置
            angle = np.random.uniform(0, 2 * np.pi)  # 随机角度
            radius = np.random.uniform(10, 30)        # 随机半径(10-30像素)
            x = int(center[0] + radius * np.cos(angle))
            y = int(center[1] + radius * np.sin(angle))
            
            # 保存这个特征点
            point_name = f"{name}_p{j+1}"
            feature_points[point_name] = (x, y)
            
            # 在图像上绘制这个点(橙色)
            cv2.circle(image, (x, y), 3, (0, 100, 200), -1)

效果:在5个锚点周围各有5个橙色的特征点,总共25个点。

第3步:计算距离和影响力

3.1 计算特征点到锚点的距离

python 复制代码
def calculate_distances_to_anchors(points, anchor_points):
    """计算每个特征点到所有锚点的距离"""
    distances = {}
    
    for point_name, point in points.items():  # 遍历每个特征点
        point_distances = {}
        for anchor_name, anchor in anchor_points.items():  # 遍历每个锚点
            # 计算欧氏距离:√[(x1-x2)² + (y1-y2)²]
            dist = distance.euclidean(point, anchor)
            point_distances[anchor_name] = dist
        
        distances[point_name] = point_distances
    
    return distances

举例:对于特征点"left_eye_p1":

  • 到左眼的距离:29.0像素

  • 到右眼的距离:122.6像素

  • 到鼻尖的距离:77.1像素

  • 等等...

3.2 计算RBF影响力(核心概念)

RBF思想:距离越近的点影响力越大,距离越远影响力越小(呈指数衰减)。

python 复制代码
def calculate_rbf_influence(distances, sigma=50.0):
    """使用高斯函数将距离转换为影响力"""
    influences = {}
    
    for point_name, point_distances in distances.items():
        point_influences = {}
        for anchor_name, dist in point_distances.items():
            # 高斯RBF公式:exp(-dist²/(2σ²))
            influence = np.exp(-dist ** 2 / (2 * sigma ** 2))
            point_influences[anchor_name] = influence
        
        influences[point_name] = point_influences
    
    return influences

理解σ参数

  • σ=50:影响力范围较广,较远的点也有一定影响力

  • σ越小:只有很近的点才有影响力

  • σ越大:较远的点也有较大影响力

第4步:创建相似人脸进行比较

4.1 轻微修改特征点位置

python 复制代码
def create_similar_face(image, key_points, feature_points, variation=10):
    """创建一张相似的人脸(特征点位置轻微变化)"""
    new_image = image.copy()
    new_feature_points = {}
    
    np.random.seed(123)  # 固定随机种子,确保变化一致
    
    for name, point in feature_points.items():
        # 在原位置基础上随机偏移(-10到+10像素)
        dx = np.random.randint(-variation, variation + 1)
        dy = np.random.randint(-variation, variation + 1)
        new_point = (point[0] + dx, point[1] + dy)
        new_feature_points[name] = new_point
        
        # 用不同颜色绘制新点
        cv2.circle(new_image, new_point, 3, (200, 100, 0), -1)
    
    return new_image, key_points, new_feature_points

意义:模拟真实情况中,同一个人不同照片的特征点微小变化。

4.2 比较两张人脸的相似度

python 复制代码
def compare_faces(face1_points, face2_points, anchor_points):
    # 计算两张脸的特征点到锚点的距离
    distances1 = calculate_distances_to_anchors(face1_points, anchor_points)
    distances2 = calculate_distances_to_anchors(face2_points, anchor_points)
    
    # 计算RBF影响力
    influences1 = calculate_rbf_influence(distances1)
    influences2 = calculate_rbf_influence(distances2)
    
    # 计算相似度
    similarity_scores = {}
    for anchor_name in anchor_points.keys():
        # 获取所有特征点对该锚点的影响力值
        inf1 = np.array([influences1[p][anchor_name] for p in face1_points.keys()])
        inf2 = np.array([influences2[p][anchor_name] for p in face2_points.keys()])
        
        # 计算相关系数(0-1之间,越大越相似)
        corr = np.corrcoef(inf1, inf2)[0, 1]
        similarity_scores[anchor_name] = max(0, corr)  # 负相关视为0(不相似)
    
    return similarity_scores, influences1, influences2

相关系数解释

  • 1.0:完全相关(特征分布模式完全相同)

  • 0.9+:高度相似

  • 0.0:完全不相关

  • 负值:负相关(这里处理为0)

第5步:可视化分析

5.1 创建6个分析子图

python 复制代码
def visualize_face_analysis(image, key_points, feature_points, distances, influences):
    fig, axes = plt.subplots(2, 3, figsize=(15, 10))
    # 创建2行3列共6个子图

6个子图内容

  1. 原始人脸:基础的人脸图像

  2. 特征点与锚点:用不同颜色标记锚点和特征点

  3. 连线图:每个特征点连接到最近的锚点

  4. 距离热力图:特征点到各锚点的距离(矩阵形式)

  5. 影响力热力图:距离经RBF转换后的影响力值

  6. 距离分布条形图:5个示例特征点到各锚点的距离

5.2 绘制热力图

python 复制代码
# 创建距离矩阵
anchor_names = list(key_points.keys())
point_names = list(feature_points.keys())[:15]  # 只显示前15个点

distance_matrix = np.zeros((len(point_names), len(anchor_names)))

for i, point_name in enumerate(point_names):
    for j, anchor_name in enumerate(anchor_names):
        distance_matrix[i, j] = distances[point_name][anchor_name]

# 使用imshow绘制热力图
im = axes[1, 0].imshow(distance_matrix, cmap='YlOrRd', aspect='auto')
plt.colorbar(im, ax=axes[1, 0], label='距离(像素)')  # 添加颜色条

热力图解读

  • 每一行:一个特征点

  • 每一列:一个锚点

  • 颜色越黄:距离越大

  • 颜色越红:距离越小

第6步:主程序整合

6.1 执行流程

python 复制代码
def main():
    # 1. 创建第一张人脸
    image1, key_points, feature_points1 = create_synthetic_face()
    
    # 2. 计算距离和影响力
    distances1 = calculate_distances_to_anchors(feature_points1, key_points)
    influences1 = calculate_rbf_influence(distances1)
    
    # 3. 创建第二张相似人脸
    image2, _, feature_points2 = create_similar_face(image1, key_points, feature_points1, variation=15)
    
    # 4. 比较相似度
    similarity_scores, _, _ = compare_faces(feature_points1, feature_points2, key_points)
    
    # 5. 可视化
    # ...(绘制3个图表)
    
    # 6. 显示结果
    plt.show()

6.2 运行程序

python 复制代码
if __name__ == "__main__":
    main()

项目源码

下面这段代码实现了一个基于径向基函数网络(RBFN)思想的人脸特征表示和相似度分析的完整演示案例。它通过以下几个核心步骤展示RBFN在人脸识别中的应用原理:

首先,代码创建了一个合成人脸图像 ,定义了人脸轮廓、眼睛、鼻子和嘴巴等基本特征。接着,它确定了五个关键"锚点" :左眼中心、右眼中心、鼻尖、左嘴角和右嘴角,作为人脸特征的参考基准。在这些锚点周围,代码随机生成了25个特征点,模拟面部细节特征。

然后,代码计算每个特征点到所有五个锚点的欧氏距离 ,形成一个距离矩阵,将几何位置关系量化为数值特征。这些距离通过高斯RBF函数转换为影响力值,距离越近影响力越大,距离越远影响力呈指数衰减,体现了RBFN对局部特征的重点关注。

为了验证RBFN对特征变化的鲁棒性,代码创建了第二张相似人脸 ,通过轻微扰动特征点位置模拟真实世界的变化。最后,它比较两张人脸的相似度,计算每个锚点区域的特征分布相关系数,结果显示平均相似度高达0.9735,验证了RBFN方法对局部特征变化的稳定性。

整个演示通过多层次可视化(包括特征点标记、连线图、距离热力图、影响力矩阵等)直观展示了RBFN如何将复杂的人脸结构简化为关键锚点周围的局部特征分布,为理解RBFN在模式识别中的应用提供了清晰的案例。

python 复制代码
import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import distance
import warnings

warnings.filterwarnings('ignore')

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False


def create_synthetic_face():
    """创建合成人脸图像和特征点"""
    # 创建一个空白图像
    width, height = 400, 400
    image = np.zeros((height, width, 3), dtype=np.uint8)
    image.fill(240)  # 浅灰色背景

    # 创建椭圆脸
    face_center = (width // 2, height // 2)
    cv2.ellipse(image, face_center, (120, 150), 0, 0, 360, (255, 220, 180), -1)
    cv2.ellipse(image, face_center, (120, 150), 0, 0, 360, (150, 100, 50), 2)

    # 创建眼睛
    left_eye_center = (face_center[0] - 50, face_center[1] - 30)
    right_eye_center = (face_center[0] + 50, face_center[1] - 30)

    cv2.circle(image, left_eye_center, 20, (255, 255, 255), -1)
    cv2.circle(image, left_eye_center, 20, (0, 0, 0), 2)
    cv2.circle(image, left_eye_center, 8, (0, 0, 0), -1)

    cv2.circle(image, right_eye_center, 20, (255, 255, 255), -1)
    cv2.circle(image, right_eye_center, 20, (0, 0, 0), 2)
    cv2.circle(image, right_eye_center, 8, (0, 0, 0), -1)

    # 创建鼻子
    nose_tip = (face_center[0], face_center[1] + 20)
    cv2.ellipse(image, (nose_tip[0], nose_tip[1] - 15), (10, 20), 0, 0, 180, (200, 150, 100), -1)
    cv2.circle(image, nose_tip, 5, (200, 150, 100), -1)

    # 创建嘴巴
    mouth_center = (face_center[0], face_center[1] + 70)
    cv2.ellipse(image, mouth_center, (40, 20), 0, 0, 180, (200, 50, 50), 3)

    # 定义关键特征点(锚点)
    key_points = {
        'left_eye': left_eye_center,
        'right_eye': right_eye_center,
        'nose': nose_tip,
        'left_mouth': (mouth_center[0] - 30, mouth_center[1]),
        'right_mouth': (mouth_center[0] + 30, mouth_center[1])
    }

    # 创建一些随机特征点(模拟面部细节)
    np.random.seed(42)  # 固定随机种子以便重现
    feature_points = {}

    # 在每个锚点周围生成随机点
    for i, (name, center) in enumerate(key_points.items()):
        for j in range(5):  # 每个锚点周围5个特征点
            # 在锚点周围随机分布
            angle = np.random.uniform(0, 2 * np.pi)
            radius = np.random.uniform(10, 30)
            x = int(center[0] + radius * np.cos(angle))
            y = int(center[1] + radius * np.sin(angle))

            point_name = f"{name}_p{j + 1}"
            feature_points[point_name] = (x, y)

            # 在图像上绘制点
            cv2.circle(image, (x, y), 3, (0, 100, 200), -1)

    return image, key_points, feature_points


def calculate_distances_to_anchors(points, anchor_points):
    """计算每个点到各个锚点的距离"""
    distances = {}

    for point_name, point in points.items():
        point_distances = {}
        for anchor_name, anchor in anchor_points.items():
            dist = distance.euclidean(point, anchor)
            point_distances[anchor_name] = dist
        distances[point_name] = point_distances

    return distances


def calculate_rbf_influence(distances, sigma=50.0):
    """计算RBF影响力(高斯函数)"""
    influences = {}

    for point_name, point_distances in distances.items():
        point_influences = {}
        for anchor_name, dist in point_distances.items():
            # 高斯RBF函数:exp(-dist^2 / (2*sigma^2))
            influence = np.exp(-dist ** 2 / (2 * sigma ** 2))
            point_influences[anchor_name] = influence
        influences[point_name] = point_influences

    return influences


def visualize_face_analysis(image, key_points, feature_points, distances, influences):
    """可视化人脸分析结果"""
    fig, axes = plt.subplots(2, 3, figsize=(15, 10))

    # 1. 原始合成人脸
    axes[0, 0].imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    axes[0, 0].set_title('合成人脸图像')
    axes[0, 0].axis('off')

    # 2. 特征点标记
    img_with_points = image.copy()

    # 绘制锚点
    colors = {'left_eye': (255, 0, 0),  # 蓝色
              'right_eye': (0, 0, 255),  # 红色
              'nose': (0, 255, 0),  # 绿色
              'left_mouth': (255, 255, 0),  # 青色
              'right_mouth': (255, 0, 255)}  # 紫色

    labels = {'left_eye': '左眼',
              'right_eye': '右眼',
              'nose': '鼻尖',
              'left_mouth': '左嘴角',
              'right_mouth': '右嘴角'}

    for name, point in key_points.items():
        color = colors[name]
        cv2.circle(img_with_points, point, 10, color, -1)
        cv2.putText(img_with_points, labels[name], (point[0] + 12, point[1] - 12),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)

    # 绘制特征点
    for name, point in feature_points.items():
        cv2.circle(img_with_points, point, 4, (0, 150, 255), -1)

    axes[0, 1].imshow(cv2.cvtColor(img_with_points, cv2.COLOR_BGR2RGB))
    axes[0, 1].set_title('特征点与锚点')
    axes[0, 1].axis('off')

    # 3. 锚点到特征点的连线
    img_with_lines = image.copy()

    # 绘制锚点和特征点
    for name, point in key_points.items():
        color = colors[name]
        cv2.circle(img_with_lines, point, 10, color, -1)

    # 绘制连线(每个特征点连接到最近的锚点)
    for point_name, point in feature_points.items():
        # 找到最近的锚点
        min_dist = float('inf')
        nearest_anchor = None

        for anchor_name, anchor in key_points.items():
            dist = distance.euclidean(point, anchor)
            if dist < min_dist:
                min_dist = dist
                nearest_anchor = anchor_name

        if nearest_anchor:
            cv2.line(img_with_lines, point, key_points[nearest_anchor],
                     colors[nearest_anchor], 1, cv2.LINE_AA)

        cv2.circle(img_with_lines, point, 4, (0, 150, 255), -1)

    axes[0, 2].imshow(cv2.cvtColor(img_with_lines, cv2.COLOR_BGR2RGB))
    axes[0, 2].set_title('特征点与最近锚点连线')
    axes[0, 2].axis('off')

    # 4. 距离热力图
    # 创建距离矩阵
    anchor_names = list(key_points.keys())
    point_names = list(feature_points.keys())[:15]  # 只显示前15个点

    distance_matrix = np.zeros((len(point_names), len(anchor_names)))

    for i, point_name in enumerate(point_names):
        for j, anchor_name in enumerate(anchor_names):
            distance_matrix[i, j] = distances[point_name][anchor_name]

    im = axes[1, 0].imshow(distance_matrix, cmap='YlOrRd', aspect='auto')
    axes[1, 0].set_title('距离矩阵(特征点到锚点)')
    axes[1, 0].set_xlabel('锚点')
    axes[1, 0].set_ylabel('特征点')
    axes[1, 0].set_xticks(range(len(anchor_names)))
    axes[1, 0].set_xticklabels([labels[a] for a in anchor_names], rotation=45)
    axes[1, 0].set_yticks(range(len(point_names)))
    axes[1, 0].set_yticklabels([f'P{i + 1}' for i in range(len(point_names))], fontsize=8)
    plt.colorbar(im, ax=axes[1, 0], label='距离(像素)')

    # 5. RBF影响力热力图
    influence_matrix = np.zeros((len(point_names), len(anchor_names)))

    for i, point_name in enumerate(point_names):
        for j, anchor_name in enumerate(anchor_names):
            influence_matrix[i, j] = influences[point_name][anchor_name]

    im2 = axes[1, 1].imshow(influence_matrix, cmap='viridis', aspect='auto', vmin=0, vmax=1)
    axes[1, 1].set_title('RBF影响力矩阵')
    axes[1, 1].set_xlabel('锚点')
    axes[1, 1].set_ylabel('特征点')
    axes[1, 1].set_xticks(range(len(anchor_names)))
    axes[1, 1].set_xticklabels([labels[a] for a in anchor_names], rotation=45)
    axes[1, 1].set_yticks(range(len(point_names)))
    axes[1, 1].set_yticklabels([f'P{i + 1}' for i in range(len(point_names))], fontsize=8)
    plt.colorbar(im2, ax=axes[1, 1], label='影响力')

    # 6. 特征向量可视化(示例点的距离分布)
    if len(point_names) >= 5:
        # 选择5个特征点
        sample_points = point_names[:5]

        # 为每个锚点创建子图
        ax = axes[1, 2]
        bar_width = 0.15
        indices = np.arange(len(sample_points))

        # 修复:使用正确的颜色列表(从BGR转换为RGB并归一化)
        color_list = [
            (1, 0, 0),  # 红色 - 左眼 (原始是BGR的(255,0,0),转换为RGB的(1,0,0))
            (0, 0, 1),  # 蓝色 - 右眼 (原始是BGR的(0,0,255),转换为RGB的(0,0,1))
            (0, 1, 0),  # 绿色 - 鼻子
            (1, 1, 0),  # 黄色 - 左嘴角 (青色在RGB中近似黄色)
            (1, 0, 1)  # 品红色 - 右嘴角
        ]

        for idx, anchor_name in enumerate(anchor_names):
            # 获取这5个点到当前锚点的距离
            anchor_distances = [distances[p][anchor_name] for p in sample_points]
            ax.bar(indices + idx * bar_width, anchor_distances, bar_width,
                   label=labels[anchor_name], color=color_list[idx])

        ax.set_title('5个特征点到各锚点的距离')
        ax.set_xlabel('特征点')
        ax.set_ylabel('距离(像素)')
        ax.set_xticks(indices + bar_width * 2)
        ax.set_xticklabels([f'P{i + 1}' for i in range(len(sample_points))])
        ax.legend()

    plt.tight_layout()
    return fig


def create_similar_face(image, key_points, feature_points, variation=10):
    """创建一张相似的人脸(轻微变化)"""
    # 复制原图像
    new_image = image.copy()

    # 创建新的特征点(轻微变化)
    new_feature_points = {}

    np.random.seed(123)  # 固定随机种子以便重现
    for name, point in feature_points.items():
        # 添加随机变化
        dx = np.random.randint(-variation, variation + 1)
        dy = np.random.randint(-variation, variation + 1)
        new_point = (point[0] + dx, point[1] + dy)
        new_feature_points[name] = new_point

        # 绘制新点(用不同颜色)
        cv2.circle(new_image, new_point, 3, (200, 100, 0), -1)

    return new_image, key_points, new_feature_points


def compare_faces(face1_points, face2_points, anchor_points):
    """比较两张人脸的相似度"""
    # 计算到锚点的距离
    distances1 = calculate_distances_to_anchors(face1_points, anchor_points)
    distances2 = calculate_distances_to_anchors(face2_points, anchor_points)

    # 计算RBF影响力
    influences1 = calculate_rbf_influence(distances1)
    influences2 = calculate_rbf_influence(distances2)

    # 计算相似度(基于RBF影响力)
    similarity_scores = {}
    for anchor_name in anchor_points.keys():
        # 获取所有特征点对该锚点的影响力
        inf1 = np.array([influences1[p][anchor_name] for p in face1_points.keys()])
        inf2 = np.array([influences2[p][anchor_name] for p in face2_points.keys()])

        # 计算相关系数
        corr = np.corrcoef(inf1, inf2)[0, 1]
        similarity_scores[anchor_name] = max(0, corr)  # 负相关视为不相似

    return similarity_scores, influences1, influences2


def main():
    print("=" * 60)
    print("人脸识别 - 特征锚点演示")
    print("RBFN思想:把每张脸表示为到'锚点'的距离和影响力")
    print("=" * 60)

    # 创建第一张人脸
    print("\n创建第一张合成人脸...")
    image1, key_points, feature_points1 = create_synthetic_face()

    print(f"关键锚点(5个):")
    labels = {'left_eye': '左眼', 'right_eye': '右眼',
              'nose': '鼻尖', 'left_mouth': '左嘴角', 'right_mouth': '右嘴角'}

    for key, point in key_points.items():
        print(f"  {labels[key]}: {point}")

    print(f"\n特征点({len(feature_points1)}个)分布在锚点周围")

    # 计算距离和影响力
    distances1 = calculate_distances_to_anchors(feature_points1, key_points)
    influences1 = calculate_rbf_influence(distances1)

    print("\n距离计算示例(前3个特征点):")
    point_names = list(feature_points1.keys())
    for i in range(min(3, len(point_names))):
        point_name = point_names[i]
        print(f"\n{point_name}:")
        for anchor_name, dist in distances1[point_name].items():
            print(f"  到{labels[anchor_name]}的距离: {dist:.1f}像素")
            print(f"  对{labels[anchor_name]}的影响力: {influences1[point_name][anchor_name]:.4f}")

    # 创建第二张相似人脸
    print("\n\n创建第二张相似人脸(特征点轻微变化)...")
    image2, _, feature_points2 = create_similar_face(image1, key_points, feature_points1, variation=15)

    # 比较两张人脸
    similarity_scores, inf1, inf2 = compare_faces(feature_points1, feature_points2, key_points)

    print("\n两张人脸在各锚点区域的相似度(基于RBF影响力):")
    total_similarity = 0
    for anchor_name, score in similarity_scores.items():
        print(f"  {labels[anchor_name]}区域: {score:.4f}")
        total_similarity += score

    avg_similarity = total_similarity / len(similarity_scores)
    print(f"\n平均相似度: {avg_similarity:.4f}")

    # 可视化第一张人脸的分析结果
    print("\n生成可视化图表...")
    fig1 = visualize_face_analysis(image1, key_points, feature_points1, distances1, influences1)
    plt.suptitle('人脸1:特征锚点分析', fontsize=16, y=1.02)

    # 显示第二张人脸
    fig2, axes2 = plt.subplots(1, 2, figsize=(10, 5))

    axes2[0].imshow(cv2.cvtColor(image1, cv2.COLOR_BGR2RGB))
    axes2[0].set_title('人脸1')
    axes2[0].axis('off')

    axes2[1].imshow(cv2.cvtColor(image2, cv2.COLOR_BGR2RGB))
    axes2[1].set_title('人脸2(特征点轻微变化)')
    axes2[1].axis('off')

    plt.suptitle('两张相似人脸对比', fontsize=14, y=1.05)
    plt.tight_layout()

    # 显示相似度柱状图
    fig3, ax3 = plt.subplots(figsize=(8, 5))
    anchor_labels = [labels[a] for a in similarity_scores.keys()]
    scores = list(similarity_scores.values())

    # 使用颜色字符串而不是元组
    colors_str = ['red', 'blue', 'green', 'orange', 'purple']

    bars = ax3.bar(anchor_labels, scores, color=colors_str)
    ax3.set_title('两张人脸在各锚点区域的相似度')
    ax3.set_ylabel('相似度系数')
    ax3.set_ylim(0, 1.1)
    ax3.axhline(y=avg_similarity, color='r', linestyle='--', label=f'平均相似度: {avg_similarity:.4f}')

    # 在柱子上添加数值
    for bar, score in zip(bars, scores):
        height = bar.get_height()
        ax3.text(bar.get_x() + bar.get_width() / 2., height + 0.02,
                 f'{score:.4f}', ha='center', va='bottom')

    ax3.legend()
    plt.tight_layout()

    # 显示所有图表
    plt.show()

    print("\n" + "=" * 60)
    print("演示总结:")
    print("1. 每张人脸用5个关键'锚点'(眼睛、鼻子、嘴角)作为参考基准")
    print("2. 其他特征点到这些锚点的距离构成特征向量")
    print("3. RBFN使用高斯函数将距离转换为'影响力'")
    print("4. 相似的人脸,在这些锚点周围的局部特征分布也相似")
    print("5. RBFN方法对人脸表情、角度变化有一定的鲁棒性")
    print("=" * 60)

    # 保存图像
    cv2.imwrite('face1_with_points.jpg', image1)
    cv2.imwrite('face2_with_points.jpg', image2)
    print("\n图像已保存为:face1_with_points.jpg 和 face2_with_points.jpg")


if __name__ == "__main__":
    main()

项目分析

图片1:人脸1 - 特征锚点分析(6个子图)

1.1 左上:合成人脸图像

  • 内容:显示了一个简单的合成人脸轮廓

  • 分析:这是一个基础的人脸模板,包含椭圆形的脸部轮廓、两个对称的眼睛、鼻子和嘴巴。人脸居中显示,为后续特征点分析提供基础

  • RBFN思想体现:展示了人脸的基本结构,为后续的特征点定位提供参考框架

1.2 中上:特征点与锚点标记

  • 内容:用不同颜色标记了5个关键锚点和25个特征点

  • 分析

    • 红色:左眼中心锚点

    • 蓝色:右眼中心锚点

    • 绿色:鼻尖锚点

    • 黄色:左嘴角锚点

    • 品红色:右嘴角锚点

    • 橙色小点:在锚点周围随机生成的特征点

  • RBFN思想体现:锚点作为参考基准,特征点围绕锚点分布,形成局部特征区域

1.3 右上:特征点与最近锚点连线

  • 内容:每个特征点都连接到其最近的锚点

  • 分析

    • 连线显示了特征点与锚点的归属关系

    • 距离最近的锚点对特征点的影响最大

    • 特征点主要集中在对应的锚点区域

  • RBFN思想体现:通过距离确定特征点的"归属",为计算RBF影响力做准备

1.4 左下:距离热力图

  • 内容:特征点到各锚点的距离矩阵(15×5)

  • 分析

    • 纵轴:15个特征点(P1-P15)

    • 横轴:5个锚点

    • 颜色越亮(黄色)表示距离越大,颜色越暗(红色)表示距离越小

    • 对角线附近颜色较暗,表示特征点主要靠近对应的锚点

  • RBFN思想体现:将几何距离量化为特征向量,每个特征点由到5个锚点的距离组成5维向量

1.5 中下:RBF影响力矩阵

  • 内容:特征点到各锚点的影响力矩阵(经过高斯函数转换)

  • 分析

    • 纵轴:15个特征点

    • 横轴:5个锚点

    • 颜色越亮(绿色)表示影响力越大(距离越近)

    • 颜色越暗(紫色)表示影响力越小(距离越远)

    • 影响力值在0-1之间,距离越近影响力越接近1

  • RBFN思想体现:通过高斯RBF函数将距离非线性转换为影响力,近处的影响大,远处的影响迅速衰减

1.6 右下:5个特征点到各锚点的距离分布

  • 内容:5个示例特征点到5个锚点的距离条形图

  • 分析

    • 横轴:5个特征点(P1-P5)

    • 每种颜色代表一个锚点

    • 每个特征点到不同锚点的距离差异明显

    • 特征点通常对其最近的锚点距离最小

  • RBFN思想体现:展示了特征向量的多样性,不同的距离组合形成独特的特征表示

图片2:两张相似人脸对比

内容:

  • 左图:原始人脸1

  • 右图:特征点轻微变化后的人脸2

  • 变化:所有特征点的位置都有±15像素的随机扰动

分析:

  • 两张人脸在视觉上非常相似

  • 人脸轮廓、锚点位置保持不变

  • 特征点有轻微的位置变化,模拟了真实世界中的人脸表情变化或测量误差

  • 橙色的特征点位置有细微差别

RBFN思想体现:

  • 即使特征点有轻微变化,只要锚点周围的局部特征分布模式相似,两张人脸就能保持高度相似

图片3:相似度柱状图

内容:

  • 横轴:5个锚点区域

  • 纵轴:相似度系数(0-1)

  • 红色虚线:平均相似度

数据:

  • 左眼区域:0.9831

  • 右眼区域:0.9877

  • 鼻尖区域:0.9458

  • 左嘴角区域:0.9857

  • 右嘴角区域:0.9650

  • 平均相似度:0.9735

分析:

  • 所有锚点区域的相似度都很高(>0.94)

  • 眼睛和嘴角区域的相似度最高(>0.98)

  • 鼻尖区域的相似度相对较低(0.9458),但仍很高

  • 平均相似度0.9735表明两张人脸高度相似

RBFN思想体现:

  • 相似度计算基于RBF影响力的相关系数

  • 即使特征点位置有变化,其与锚点的相对距离模式保持相似

  • RBF函数对局部特征变化的鲁棒性

如果报了如下的错误:

说明没有找到cv2模块,我们需要安装opencv-python。

解决方法:

安装必要的库

在命令行中运行以下命令:

python 复制代码
# 安装所有必要的库
pip install opencv-python
pip install opencv-contrib-python
pip install numpy
pip install matplotlib
pip install scipy

下面我以opencv-python与opencv-contrib-python为例:

(1)opencv-python

在命令行中运行以下命令:

python 复制代码
 pip install opencv-python

(2)opencv-contrib-python

在命令行中运行以下命令:

python 复制代码
pip install opencv-contrib-python
相关推荐
深蓝易网2 小时前
MES系统如何帮助企业实现产品质量的全过程追溯
大数据·人工智能
天才少女爱迪生2 小时前
图像序列预测有什么算法方案
人工智能·python·深度学习·算法
计算机学姐2 小时前
基于Python的高校后勤报修系统【2026最新】
开发语言·vue.js·后端·python·mysql·django·flask
乐迪信息2 小时前
乐迪信息:AI摄像机+反光衣佩戴检测,保障智慧煤矿人员作业安全
大数据·运维·人工智能·物联网·安全
胖墩会武术2 小时前
【PyTorch项目实战】Ultralytics YOLO模型本地部署(训练 + 测试 + 推理)
人工智能·pytorch·yolo
Q_Q19632884752 小时前
python+django/flask+vue的智能房价分析与预测系统
spring boot·python·django·flask·node.js·php
测试人社区—小叶子2 小时前
Rust会取代C++吗?系统编程语言的新较量
运维·开发语言·网络·c++·人工智能·测试工具·rust
txwtech2 小时前
第20篇 python如何找到pyd文件的
开发语言·python
O561 6O623O7 安徽正华露2 小时前
(露)脑切片模具 大鼠脑切片模具 小鼠脑切片模具
人工智能