OPENCV(python)--初学之路(十四)哈里斯角检测

一前言

今天起得太晚,下午又是满课,所以今天的内容会少一点,但是我觉得挺有意思的,也有用处。

二主要内容--特征检测哈里斯角

解释说明

我们大多数人都玩过拼图游戏。我们获得由大量图片碎片,并且需要将他们组合起来形成一张完整的图片。问题来了,我们如何实现呢? 我们如何将相同的理论投射到计算机程序中,以便计算机可以玩拼图游戏?如果计算机可以玩拼图游戏了,为什么我们不能给计算机提供很多真实的自然风景图像,并告诉它将所有这些图像拼接成一个大的单一图像?如果计算机可以将多个自然图像拼接成一个,那么如何提供大量建筑物或任何结构的图片并告诉计算机从中创建 3D 模型呢?

那么,问题和想象力还在继续。但这一切都取决于最基本的问题:你如何玩拼图游戏?你如何将大量的混乱图像片段排列成一个大的单个图像?如何将大量自然图像拼接到单个图像中?

答案是,我们正在寻找独特的特定模式或特定特征,可以轻松跟踪和比较。如果我们找到这样一个特征的定义,我们可能会发现很难用文字表达,但我们知道它们是什么。如果有人要求您指出可以在多个图像之间进行比较的一个好的功能,您可以指出一个。这就是为什么即使是小孩子也可以简单地玩这些游戏。我们在图像中搜索这些特征,找到它们,在其他图像中查找相同的特征并对齐它们。而已。 (在拼图游戏中,我们更多地关注不同图像的连续性)。所有这些能力都存在于我们身上。

因此,我们的一个基本问题扩展到更多,但变得更具体。这些功能是什么?

我们回答了我们的问题,"这些特征是什么?"。但接下来的问题出现了。我们如何找到它们?或者我们如何找到角落?我们以直观的方式回答了这一点,即在图像中寻找在其周围的所有区域中移动(少量)时具有最大变化的区域。在接下来的章节中,这将被投射到计算机语言中。因此,查找这些图像特征称为特征检测。

获得这些功能及其描述后,您可以在所有图像中找到相同的功能并对齐它们,将它们拼接在一起或做任何您想做的事情。

OpenCV 中的 Harris 角点检测器

OpenCV 中的 cv.cornerHarris() 函数用来实现 Harris 角点检测。

dst = cv.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]])

参数说明

参数 说明
src 输入图像,必须是 单通道8位浮点型 图像
blockSize 邻域大小(用于计算协方差矩阵的窗口大小)
ksize Sobel算子的孔径大小(必须为奇数,如 3, 5, 7)
k Harris检测器的自由参数(经验值 0.04~0.06)
dst 输出图像,存储Harris响应值(大小与src相同)
borderType 像素外推方法(默认 cv.BORDER_DEFAULT)

基本原理

Harris角点检测基于以下观察:

  • 平坦区域:所有方向移动,图像强度变化小

  • 边缘区域:沿边缘方向移动变化小,垂直方向变化大

  • 角点区域:所有方向移动,图像强度变化都大

优势应用场景

  • 纹理丰富的图像(棋盘、建筑、织物)

  • 刚性物体(机器零件、建筑物)

  • 光照变化不大的环境

  • 需要精确位置定位的任务

局限性场景

  • 纹理单一的区域(天空、纯色墙壁)

  • 非刚性物体(水、云、火焰)

  • 严重模糊或低分辨率图像

  • 快速运动导致的运动模糊

Harris角点检测作为计算机视觉的基础算法,虽然原理简单,但因其计算效率高实现简单对旋转不变等特点,仍然是许多实际应用中的首选方法或预处理步骤。

python 复制代码
import numpy as np
import cv2 as cv

# 读取图像文件
filename = 'D:\python_code\pic\sumoiao.webp'
img = cv.imread(filename)

# 转换为灰度图像并转换为浮点型
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
gray = np.float32(gray)

# 使用Harris角点检测算法
dst = cv.cornerHarris(gray, 2, 3, 0.04)

# 膨胀结果以便更好地标记角点
dst = cv.dilate(dst, None)

# 设置阈值并标记检测到的角点
img[dst > 0.01 * dst.max()] = [0, 0, 255]

# 显示结果图像
cv.imshow('Harris Corner Detection', img)

# 等待按键或ESC退出
if cv.waitKey(0) & 0xff == 27:
    cv.destroyAllWindows()
 

效果如下

这是一个标准的棋盘,可以看到检测的效果很好,那我们换一个试一下

这是一张素描图像,很明显效果并不好,这也是哈里斯算法的局限

所以我将介绍一个更好的算法

具有亚像素级精度的角点

有时,您可能需要以最高精度找到角点。OpenCV 带有一个函数 cv.cornerSubPix() ,它进一步细化了角点检测,以达到亚像素级精度。

什么是亚像素级角点检测?

  • 标准角点检测:返回整数像素坐标(如(100, 50))

  • 亚像素级检测:返回浮点数坐标(如(100.325, 50.781))

  • 精度提升:可达0.1像素甚至更高精度

为什么需要亚像素精度?

  • 整数像素坐标存在量化误差

  • 许多应用需要毫米级甚至微米级精度

  • 提高后续计算的准确性(如3D重建、测量)

代码如下

python 复制代码
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

# 参数配置
IMAGE_PATH = 'D:/python_code/pic/qipan.jpg'  # 使用正斜杠避免转义问题
HARRIS_BLOCK_SIZE = 2
HARRIS_KSIZE = 3
HARRIS_K = 0.04
THRESHOLD_RATIO = 0.01
SUBPIX_WIN_SIZE = (5, 5)

# 图像读取与校验
input_img = cv.imread(IMAGE_PATH)
if input_img is None:
    raise FileNotFoundError(f"图像文件读取失败: {IMAGE_PATH}")

# 灰度转换
gray_img = cv.cvtColor(input_img, cv.COLOR_BGR2GRAY)

# Harris角点检测
gray_float = np.float32(gray_img)
harris_response = cv.cornerHarris(gray_float, HARRIS_BLOCK_SIZE, HARRIS_KSIZE, HARRIS_K)
harris_response = cv.dilate(harris_response, None)

# 阈值处理与连通区域分析
_, thresholded = cv.threshold(harris_response, THRESHOLD_RATIO * harris_response.max(), 255, 0)
thresholded = np.uint8(thresholded)
_, _, stats, centroids = cv.connectedComponentsWithStats(thresholded)

# 角点处理
if len(centroids) > 1:
    raw_corners = centroids[1:]  # 排除背景点
    print(f"检测到 {len(raw_corners)} 个初始角点")
    
    # 角点精化
    criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 100, 0.001)
    refined_corners = cv.cornerSubPix(gray_float, np.float32(raw_corners), SUBPIX_WIN_SIZE, (-1,-1), criteria)
else:
    print("未检测到有效角点")
    raw_corners = refined_corners = np.array([])

# 可视化处理
def draw_corners(img, corners, color, radius):
    for pt in corners:
        x, y = map(int, pt)
        if 0 <= x < img.shape[1] and 0 <= y < img.shape[0]:
            cv.circle(img, (x, y), radius, color, -1)

result_img = input_img.copy()
draw_corners(result_img, raw_corners, (0, 0, 255), 5)    # 红色原始角点
draw_corners(result_img, refined_corners, (0, 255, 0), 3) # 绿色精化角点

# 结果展示
plt.figure(figsize=(12, 6))
plt.subplot(121), plt.imshow(cv.cvtColor(input_img, cv.COLOR_BGR2RGB))
plt.title('原始图像'), plt.axis('off')
plt.subplot(122), plt.imshow(cv.cvtColor(result_img, cv.COLOR_BGR2RGB))
plt.title(f'角点检测结果\n共检测到 {len(raw_corners)} 个角点'), plt.axis('off')
plt.tight_layout()
plt.savefig('corner_detection_result.png', dpi=300, bbox_inches='tight')
plt.show()
 

其实源代码没有这么麻烦,但是涉及显示问题,即使我下了QT库也无法正常显示所以只能用matplotlib代替。

效果如下

这样的效果就好一点了,而且运行的时候还会显示角点数

三最后一语

今天就先学这么多吧,新的一周开始了希望大家新的一周又更多收获。

"唯独在这些孤独和沉思默想的时刻。我才是我,和天性相符的我, 我才既无忧烦又无羁束。"

------卢梭《一个孤独的散步者的遐想》

感谢观看,共勉!!

相关推荐
咚咚王者2 小时前
人工智能之数据分析 Pandas:第九章 性能优化
人工智能·数据分析·pandas
Acrel150003531382 小时前
重构能源管理:Acrel EMS 3.0 让降本增效成为底层逻辑
大数据·人工智能
dhdjjsjs2 小时前
Day31 PythonStudy
人工智能·机器学习
TextIn智能文档云平台2 小时前
深度学习在版面分析中的应用方法
人工智能·深度学习
金融小师妹2 小时前
黄金上探4260后基于阻力位识别模型回落,本周聚焦美联储决议的LSTM-NLP联合预测
大数据·人工智能·深度学习
Coding茶水间2 小时前
基于深度学习的船舶检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
图像处理·人工智能·深度学习·yolo·目标检测·计算机视觉
我不是小upper2 小时前
CNN+BiLSTM !!最强序列建模组合!!!
人工智能·python·深度学习·神经网络·cnn
锐学AI2 小时前
从零开始学MCP(四)- 认识MCP clients
人工智能·python
QT 小鲜肉2 小时前
【孙子兵法之下篇】010. 孙子兵法·地形篇深度解析与现代应用
人工智能·笔记·读书·孙子兵法