小白从零开始勇闯人工智能:计算机视觉初级篇(OpenCV进阶操作(下))

引言

在本篇文章里,我们将要学习Harris角点检测的原理与应用,理解SIFT特征提取与描述的方法,并探索如何利用这些特征实现多幅图像的精准拼接。掌握这些技术,我们就能够赋予程序"识别"和"组装"图像的能力,为后续的目标跟等高级应用奠定基础。

一、特征检测之Harris角点检测

1、什么是角点?

角点是图像中一种重要的局部特征点,它指的是在两个或多个方向上灰度(或颜色)发生显著变化的像素位置。角点通常位于物体的边缘拐角处,是图像中"结构"信息最丰富的地方。由于其同时具有边缘变化剧烈和位置易于精确定位的特性,角点对图像的旋转、缩放都能保持相对稳定。在计算机视觉中,角点是图像匹配和目标跟踪的基础,因为它们是特征描述符(如SIFT、ORB)进行提取和匹配的关键位置。

2、Harris角点检测原理

Harris角点检测的原理是:通过量化图像局部窗口在各个方向移动时引起的灰度变化强度,来识别角点这一关键特征。首先,计算图像在x和y方向的梯度,接着基于这些梯度构造二阶矩矩阵,用以描述该点的局部灰度变化结构,随后,通常对该矩阵应用高斯加权以增强稳健性,计算每个像素的角点响应函数R值,最后,通过设定阈值筛选R值,并配合非极大值抑制来定位最终的角点。

3、Harris角点响应函数

Harris角点检测的角点响应函数 R 是一个关键的计算指标,其定义为:R = det(M) - k · (trace(M))²。 Harris角点检测的角点响应函数 R 是一个关键的计算指标,其定义为:R = det(M) - k · (trace(M))²。

其中,M 是之前步骤中计算得到的自相关矩阵,它综合了局部窗口内像素梯度的分布信息。矩阵的行列式 det(M) 近似代表了该点的两个主方向上的变化强度的乘积,而矩阵的迹 trace(M) 则近似代表了这两个方向上的变化强度之和。经验常数 k 通常取值在0.04到0.06之间,用于调节对边缘的敏感度。通过计算出的 R 值可以有效地对像素点进行分类:

1、R 值为较大的正数时,表示该点在任何方向上移动都会引起较大的灰度变化,即被判定为角点。

2、R 值为绝对值较大的负数时,表示该点仅在某个单一方向上变化显著,对应图像边缘。

3、R 值绝对值很小时,则对应灰度均匀的平坦区域。

4、OpenCV示例

复制代码
import cv2
import numpy as np
img = cv2.imread('R-C.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst = cv2.cornerHarris(gray,4,3,0.04)
# 标记检测到的角点
img[dst > 0.01 * dst.max()] = [0, 0, 255]
# 这里通过对角点响应进行阈值处理,标记出检测到的角点。
# 0.05 * dst.max() 是一个阈值,大于这个值的像素点会被标记为红色。
cv2.imshow('img',img)
cv2.waitKey(0)

二、特征检测之SIFT特征检测

1、为什么需要SIFT?

SIFT算法是为了解决Harris角点检测方法对图像尺度变化敏感的问题。SIFT的优势在于其实现了尺度不变性,它通过构造高斯差分金字塔来检测不同尺度下的稳定关键点,并为之生成独特的描述子,从而使得特征匹配能够在图像缩放、旋转等多种变换下保持鲁棒性,极大地提升了在复杂场景中特征识别的可靠性与实用性。

2、SIFT算法的特点与流程

首先,算法利用高斯差分金字塔进行尺度空间极值检测以发现潜在关键点。随后,通过关键点定位步骤精确定位其位置并剔除低对比度或边缘响应点。接着,方向分配步骤为每个关键点计算主方向,赋予其旋转不变性。最后,算法在关键点邻域内生成具有高区分度的128维特征描述向量。

3、OpenCV示例

复制代码
import cv2
import numpy as np
# 检测图像中的关键点
cv2.SIFT_create() #cv2.xfeatures2d.SIFT_create()#创建一个sift特征的提取对象
# sift.detect(img)在图像中查找关键点

img = cv2.imread('R-C.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#
sift = cv2.SIFT_create()  #sift对象
kp = sift.detect(img_gray)
# kp.pt:关键点的(x, y)
# 坐标。
# kp.size:关键点的大小(尺度)。
# kp.angle:关键点的方向。
# kp.response:关键点的响应值。
# kp.octave:关键点所在的金字塔层级。
#查找关键点
# drawKeypoints(image, keypoints, outImage, color=None, flags=None)
# image:原始图片
# keypoints:从原图中获得的关键点,这也是画图时所用到的数据
# outputimage:输出图像,可以是原始图片,也可以是None
# color:颜色设置,通过修改(b,g,r)的值,更改画笔的颜色,b=蓝色,g=绿色,r=红色。
# flags:绘图功能的标识设置                                       绘制富有信息的关键点。
img_sift = cv2.drawKeypoints(img,kp,None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow('img_sift',img_sift)


# 使用sift.compute()计算关键点描述符,方便后期的特征匹配
kp,des = sift.compute(img,kp)  #
print(np.array(kp).shape,des.shape)
cv2.waitKey(0)
# 输出关键点的形状和描述符的形状。
# np.array(kp).shape 表示关键点的数量和属性。
# des.shape 表示描述符的数量和属性。

三、图像拼接

1、图像拼接流程

图像拼接是将两幅图像合并为一张无缝全景图,其标准流程首先利用SIFT算法分别在两幅图像中检测出稳定的特征点。随后,通过特征匹配步骤建立这些点之间的对应关系。基于匹配点对,算法计算单应性矩阵以精确估计图像间的几何变换关系。接着,依据此变换将其中一幅图像投影到另一幅图像的坐标系中,实现几何对齐。最后,通过图像融合技术处理重叠区域,消除亮度差异和拼接痕迹,从而生成视觉连贯、自然平滑的最终拼接结果。

2、特征匹配策略

在特征匹配阶段,为了确保匹配的准确性,SIFT算法采用了基于最近邻距离比的稳健策略。对于待匹配的关键点A,首先在其目标图像中寻找欧氏距离最近的两个关键点X和Y,其距离分别记为d1和d2(且d1<d2)。随后计算比值d1/d2。若该比值较大(例如接近或超过0.8),则表明A与X的区分度不足,很可能由噪声或重复纹理引起,应该要拒绝,反之,若比值足够小(如低于0.7),则证明A与X的描述向量具有显著的独特性,从而判定为一次可靠的正确匹配。

3、图像拼接实现

复制代码
import cv2
import numpy as np
import sys

def cv_show(name, img):
    cv2.imshow(name, img)

def detectAndDescribe(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 将彩色图片转换成灰度图
    sift = cv2.SIFT_create()  # 建立SIFT生成器
    # 检测SIFT特征点,并计算描述符,第二个参数为掩膜
    (kps, des) = sift.detectAndCompute(gray, None)
    # 将结果转换成NumPy数组
    kps_float = np.float32([kpc.pt for kpc in kps])
    # kpc 包含两个值,分别是关键点在图像中的 x 和 y 坐标。这些坐标通常是浮点数,可以精确地描述关键点在图像中的位置。
    return (kps, kps_float, des)  # 返回特征点集,及对应的描述特征

'''读取拼接图片'''
imageA = cv2.imread("1.jpg")
cv_show('imageA', imageA)
imageB = cv2.imread("2.jpg")
cv_show('imageB', imageB)

'''计算图片特征点及描述符'''
(kpsA, kps_floatA, desA) = detectAndDescribe(imageA)
(kpsB, kps_floatB, desB) = detectAndDescribe(imageB)

'''建立匹配器BFMatcher,在匹配大图训练集合时使用FlannBasedMatcher速度更快。'''
matcher = cv2.BFMatcher()

rawMatches = matcher.knnMatch(desB, desA, k=2)
good = []
matches = []

for m in rawMatches:
    # 当最近距离跟次近距离的比值小于0.65时,保留此匹配对
    if len(m) == 2 and m[0].distance < 0.65 * m[1].distance:
        good.append(m)
        # 存储两个点在featuresA、featuresB中的索引值
        matches.append((m[0].queryIdx, m[0].trainIdx))

print(len(good))
print(matches)

vis = cv2.drawMatchesKnn(imageB, kpsB, imageA, kpsA, good, outImg=None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv_show("Keypoint Matches", vis)

'''透视变换'''
if len(matches) > 4:  # 当筛选后的匹配对大于4时,计算视角变换矩阵。
    # 获取匹配对的点坐标
    ptsB = np.float32([kps_floatB[i] for (i, _) in matches])  # matches是通过阈值筛选之后的特征点对象,
    ptsA = np.float32([kps_floatA[i] for (_, i) in matches])  # kps_floatA是图片A中的全部特征点坐标

    # 计算透视变换矩阵
    # findHomography(srcPoints, dstPoints, method=None, ransacReprojThreshold=None, mask=None, maxIters=None, confidence=None)
    # 计算视角变换矩阵,透视变换函数,与cv2.getPerspectiveTransform()的区别在与可多个数据点变换
    # 参数srcPoints:图片A的匹配点坐标
    # 参数dstPoints:图片B的匹配点坐标
    # 参数method:计算变换矩阵的方法。
    # 0 - 使用所有的点,最小二乘
    # RANSAC - 基于随机样本一致性,见 https://zhuanlan.zhihu.com/p/402727549
    # LMEDS - 最小中值
    # RHO - 基于渐近样本一致性
    # ransacReprojThreshold: 最大允许重投影错误阈值。该参数只有在method参数为RANSAC与RHO的时启用,默认为3
    # 返回值:中值为变换矩阵,mask是掩模标志,指示哪些点对应内点,哪些是外点。内点:指那些与估计的模型非常接近的数据点,通常是正确匹配或真实数据。外点:指那些与估计的模型非常接近的数据点,通常是正确匹配或真实数据。
    H, mask = cv2.findHomography(ptsB, ptsA, cv2.RANSAC, 5.0)
else:
    print('图片未找到4个以上的匹配点')
    sys.exit()

result = cv2.warpPerspective(imageB, H, (imageB.shape[1] + imageA.shape[1], imageB.shape[0]))
cv_show('resultB', result)
# 将图片A传入resultB后显示
result[0:imageA.shape[0], 0:imageA.shape[1]] = imageA
cv_show('result', result)
cv2.waitKey(0)

cv2.imwrite('pingjie.jpg', result)
相关推荐
阳艳讲ai2 小时前
九尾狐AI智能矩阵:重构企业获客新引擎
大数据·人工智能
Liue612312312 小时前
窗帘检测与识别_YOLOv26模型详解与应用_1
人工智能·yolo·目标跟踪
玄同7652 小时前
SQLAlchemy 会话管理终极指南:close、commit、refresh、rollback 的正确打开方式
数据库·人工智能·python·sql·postgresql·自然语言处理·知识图谱
萤丰信息2 小时前
四大核心技术领航,智慧园区重构产业生态新范式
java·大数据·人工智能·智慧城市·智慧园区
言無咎2 小时前
从人工失误到AI精准:财务机器人如何重构企业财务数据体系
人工智能·重构·机器人
H7998742422 小时前
2026动态捕捉推荐:8款专业产品全方位测评
大数据·前端·人工智能
chatexcel2 小时前
从Excel到AI,数据看板工具选型思路梳理
人工智能·信息可视化·excel
企业老板ai培训2 小时前
从九尾狐AI案例解析智能矩阵的AI获客架构设计与实现
人工智能
小陈phd2 小时前
langGraph从入门到精通(十一)——基于langgraph构建复杂工具应用的ReAct自治代理
前端·人工智能·react.js·自然语言处理