当前位置: 首页 > article >正文

基于opencv的HOG+角点匹配教程

1. 引言

在计算机视觉任务中,特征匹配是目标识别、图像配准和物体跟踪的重要组成部分。本文介绍如何使用 HOG(Histogram of Oriented Gradients,方向梯度直方图)角点检测(Corner Detection) 进行特征匹配。

1.1 为什么选择HOG和角点?

  • HOG特征 适用于物体检测,能够提取局部梯度信息,具有旋转和光照不变性。
  • 角点检测 例如Harris角点、Shi-Tomasi等方法,能够找到图像中结构突变的关键点,提高匹配精度。
  • 结合HOG与角点检测,可以同时利用纹理信息和几何信息,提高匹配的鲁棒性。

2. HOG特征提取

2.1 HOG的基本原理

HOG的基本思想是计算局部区域内像素梯度的方向分布,并构建特征向量。

HOG计算步骤:

  1. 计算梯度:使用Sobel算子计算水平梯度 ( G_x ) 和垂直梯度 ( G_y )。
  2. 计算梯度幅值和方向
    [ M = \sqrt{G_x^2 + G_y^2} ]
    [ \theta = \tan^{-1}(G_y / G_x) ]
  3. 划分细胞(Cells):将图像划分为小的单元格(例如 8×8)。
  4. 计算直方图:在每个Cell中统计不同方向的梯度强度。
  5. 块归一化(Block Normalization):对多个Cells组成的Block进行归一化,以增强光照变化的鲁棒性。
  6. 特征向量拼接:将所有Block的特征向量拼接成最终的HOG描述子。

2.2 代码示例

使用OpenCV和hog库提取HOG特征。

import cv2
import numpy as np
from skimage.feature import hog

def compute_hog(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    features, hog_image = hog(gray, orientations=9, pixels_per_cell=(8, 8),
                              cells_per_block=(2, 2), visualize=True, feature_vector=True)
    return features, hog_image

image = cv2.imread('image.jpg')
hog_features, hog_vis = compute_hog(image)
cv2.imshow('HOG Features', hog_vis)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 角点检测

3.1 角点检测原理

角点是图像中具有显著变化的点,在特征匹配中至关重要。常用角点检测方法:

  • Harris角点检测:基于自相关矩阵,计算图像窗口内的梯度变化。
  • Shi-Tomasi角点检测:改进Harris方法,选择响应更强的角点。
  • FAST角点检测:基于快速关键点检测,适用于实时应用。

3.2 代码示例

使用OpenCV实现Harris角点检测。

import cv2
import numpy as np

def detect_corners(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    gray = np.float32(gray)
    corners = cv2.cornerHarris(gray, blockSize=2, ksize=3, k=0.04)
    image[corners > 0.01 * corners.max()] = [0, 0, 255]  # 标记角点
    return image

image = cv2.imread('image.jpg')
detected_image = detect_corners(image)
cv2.imshow('Corners', detected_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

4. HOG+角点匹配

4.1 结合HOG和角点检测

HOG提取局部特征,而角点提供关键匹配点,可以使用 最近邻搜索(Nearest Neighbor Search, NNS)FLANN(Fast Library for Approximate Nearest Neighbors) 进行匹配。

4.2 代码示例

import cv2
import numpy as np
from skimage.feature import hog
from scipy.spatial import distance

def extract_hog_at_corners(image, corners):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    features = []
    for corner in np.argwhere(corners > 0.01 * corners.max()):
        x, y = corner[1], corner[0]
        patch = gray[max(y-8, 0):min(y+8, gray.shape[0]), max(x-8, 0):min(x+8, gray.shape[1])]
        if patch.shape[0] == 16 and patch.shape[1] == 16:
            hog_feature = hog(patch, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(2, 2), feature_vector=True)
            features.append((x, y, hog_feature))
    return features

def match_features(features1, features2):
    matches = []
    for (x1, y1, f1) in features1:
        best_match = min(features2, key=lambda f2: distance.euclidean(f1, f2[2]))
        x2, y2, _ = best_match
        matches.append(((x1, y1), (x2, y2)))
    return matches

# 读取两张待匹配图像
image1 = cv2.imread('image1.jpg')
image2 = cv2.imread('image2.jpg')

# 角点检测
corners1 = cv2.cornerHarris(cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY).astype(np.float32), 2, 3, 0.04)
corners2 = cv2.cornerHarris(cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY).astype(np.float32), 2, 3, 0.04)

# 提取HOG特征
features1 = extract_hog_at_corners(image1, corners1)
features2 = extract_hog_at_corners(image2, corners2)

# 进行匹配
matches = match_features(features1, features2)

# 可视化匹配结果
for (pt1, pt2) in matches:
    cv2.line(image1, pt1, pt2, (0, 255, 0), 1)

cv2.imshow('Matched Features', image1)
cv2.waitKey(0)
cv2.destroyAllWindows()

5. 优化策略

  • 使用FLANN加速匹配
  • 结合RANSAC剔除错误匹配
  • 多尺度金字塔提高匹配稳定性

6. 结论

HOG结合角点检测能够在图像匹配任务中提供高鲁棒性的特征描述。适用于目标识别、拼接和物体跟踪等应用。


参考资料

  • Dalal & Triggs, “Histograms of Oriented Gradients for Human Detection”, CVPR 2005.
  • OpenCV 官方文档 https://docs.opencv.org

http://www.kler.cn/a/546406.html

相关文章:

  • Day1 25/2/14 FRI
  • 执行js生成json文件并动态写入数据
  • HTTP请求报文头和相应报文头
  • 深入探索C语言中的字符串处理函数:strstr与strtok
  • 科研绘图系列:R语言绘制地图和山脊图(map ridge plot)
  • LVS集群(DR/NAT)
  • 知识拓展:设计模式之装饰器模式
  • 【docker知识】快速找出服务器中占用内存较高的容器
  • 我的新书《青少年Python趣学编程(微课视频版)》出版了!
  • sql调优之数据库开发规范
  • vite让每个scss文件自动导入某段内容
  • uniapp实现首行首列冻结效果
  • 能源物联网数据采集网关 多协议对接解决方案
  • 代码随想录算法营Day38 | 62. 不同路径,63. 不同路径 II,343. 整数拆分,96. 不同的二叉搜索树
  • ICLR2022 | IAA | 从数据分布的角度重新思考对抗转移性
  • Qt接入deepseekv3 API 提供openssl 1.1.1g安装包
  • win11 MBR 启动 如何把我的硬盘改 GPT win11 的 UEFI 启动
  • Vulhub靶机 ActiveMQ任意 文件写入(CVE-2016-3088)(渗透测试详解)
  • 使用爬虫获取1688商品分类:实战案例指南
  • PMP冲刺每日一题(8)