计算机视觉(二):图像检索以及基于图像描述符的搜索

1 - 引言

在图像识别中,我们通常将图片的特征提取出来,并使用这些主要特征来进行识别。
在OpenCV中提供了许多特征检测算法,下面让我们来学习一下怎么使用这些算法

2 - 特征定义

粗略的讲,特征就是有意义的图像区域,该区域具有独特性或易于识别性。因此,角点以及高密度区域是很好的特征,而大量重复的模式或低密度区域则不是好的特征。大多数特征检测算法都会涉及图像的角点、变和斑点的识别。

2.1 - 检测角点特征

Opencv提供cornerHarris来识别角点

import cv2
import numpy as np

img = cv2.imread('images/7.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv2.cornerHarris(gray,2,23,0.04)
"""
第二参数是标记号的大小。即参数值越小,标记角点的记号越小
最重要的是第三个参数,该参数限定了Sobel算子的中孔,取值必须是介于3和31之间的奇数。
"""
img[dst>0.01*dst.max()] = [0,0,255]
while(True):
    cv2.imshow('corners',img)
    if cv2.waitKey(0):
        break


在这里插入图片描述

2.2 - 使用DoG和SIFT进行特征提取与描述

  • DoG(Diffrerence of Gaussians)是对同一图像使用不同高斯滤波器所得到的结果
  • SIFT是尺度不变特征变换(Scale-Invariant Feature Transform, SIFT),可以解决因图像比例而损失特征的变换
    (最新版本的OpenCV中SIFT函数已经被专利保护不能使用,需要安装老版本才能使用,本文使用了3.4.2.16版本)
import cv2
import sys
import numpy as py

# 读入图像
# imgpath=sys.argv[1]
imgpath = 'images/timg_1.jpg'
img = cv2.imread(imgpath)
# 更换颜色空间
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 创建sift对象,计算灰度图像,会使用dog检测角点
sift = cv2.xfeatures2d.SIFT_create()
keypoints, descriptor = sift.detectAndCompute(gray, None)

# print(keypoints)
# 关键点有以下几个属性
# angle 表示特征的方向
# class_id 关键点的id
# octave 特征所在金字塔的等级
# pt 图像中关键点的坐标
# response 表示关键点的强度
# size 表示特征的直径
img = cv2.drawKeypoints(image=img,
 outImage=img,
 keypoints=keypoints,
 color=(51, 163, 236),
 flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# 显示图像
cv2.imshow('sift_keypoints', img)
while (True):
 if cv2.waitKey(int(1000 / 12)) & 0xFF == ord('q'):
    break
cv2.destroyAllWindows()

在这里插入图片描述

2.3 使用快速Hessian算法和SURF来提取和检测特征

SURF特征检测算法由Herbert Bay于2006年发表,该算法比SIFT快好几倍,它吸收了SIFT算法的思想。(也被专利保护)

import cv2
import numpy as np

img = cv2.imread('images/timg_1.jpg')  # 读取要处理的图片
alg = input('Select an Alg --> ')


def fd(algorithm):
    if algorithm == 'SIFT':
        return cv2.xfeatures2d.SIFT_create()
    if algorithm == 'SURF':
        threshold = input('Enter a threshold --> ')  # 提示输入SURF算法所采用的阈值
        return cv2.xfeatures2d.SURF_create(float(threshold))


gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转换为灰度图像
fd_alg = fd(alg)
keypoints, descriptor = fd_alg.detectAndCompute(gray, None)  # 进行算法的检测和计算

img = cv2.drawKeypoints(image=img, outImage=img, keypoints=keypoints,
                        flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS,
                        color=(51, 163, 236))
cv2.imshow('keypoints', img)
while (True):
    if cv2.waitKey(30) & 0xff == ord('q'):
        break
cv2.destroyAllWindows()

使用SURF算法,并且阈值设为8000所得的结果,阈值越高提取的特征也越少,我们可以修改阈值来达到最好的特征提取效果
在这里插入图片描述

2.4 - 基于ORB的特征检测和特征匹配

ORB处于起步阶段,是用来替代SIFT和SURF的,与二者相比,ORB有更快的速度,在2011年才首次发布,ORB基于FAST关键点检测和BRIEF描述符的技术结合

  1. FAST算法
    在像素周围绘制一个圆,该圆包括16个像素,然后将每个像素与加上一个阈值的圆心像素进行比较,若有连续、比加上上一个阈值的圆心的像素值还亮或者暗的像素,则可认为圆心是角点。

  2. BRIEF算法
    是一种关键点描述符,并找到他们的共同之处,是一种特征匹配的算法。

  3. 暴力匹配

下面先使用最简单的暴力匹配来实现特征匹配

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('images/LAKERS_LOGO.jpg',cv2.IMREAD_GRAYSCALE)#希望检测出的特征图片
img2 = cv2.imread('images/LAKERS.jpg',cv2.IMREAD_GRAYSCALE)#测试图片

orb = cv2.ORB_create()
"""
分别对查询图像和训练图像进行检测,然后计算关键点和描述符
"""
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True)
"""
使用暴力BFMatcher实现匹配
"""
matches = bf.match(des1,des2)
matches = sorted(matches, key= lambda x:x.distance)
img3 = cv2.drawMatches(img1,kp1,img2,kp2,matches[:40],img2,flags=2)
plt.imshow(img3),plt.show()

LOGO图像:
在这里插入图片描述

球场图像:
在这里插入图片描述

进行匹配后:
在这里插入图片描述

  1. K-NN匹配

使用机器学习中的K-NN算法来替代暴力匹配法
只需稍微修改上面的代码即可

matches = bf.knnMatch(des1,des2,k=2)
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,img2,flags=2)
  1. FLANN匹配

FLANN是最近邻的快速库,也就是说FLANN可以在库中根据数据本身来选择最适合的算法进行匹配,经验证,FLANN比其他的最近邻搜索软件块10倍

猜你喜欢

转载自blog.csdn.net/HHH_ANS/article/details/85259460