第6章 图像检索以及基于图像描述符的搜索

本文涉及的产品
图像搜索,任选一个服务类型 1个月
简介: 第6章 图像检索以及基于图像描述符的搜索

第6章 图像检索以及基于图像描述符的搜索


OpenCV可以检测图像的主要特征,然后提取这些特征,使其成为图像描述符,类似于人的眼睛和大脑。


本章介绍如何使用OpenCV检测图像特征,并通过这些特征进行图像匹配和检测。 本章选取一些图像,检测它们的主要特征,并通过单应性来检测这些图像是否存在于另一个图像中。


6.1 特征检测算法


OpenCV中最常用的特征检测和提取算法:


Harris:用于检测角点


SIFT:用于检测斑点(Blob)


SURF:用于检测斑点


FAST:检测角点


BRIEF:检测斑点


ORB:带方向的FAST算法和具有选择不变性的BRIEF算法。


匹配算法:


暴力(Brute-Force)匹配法


基于FLANN的匹配法



6.1.1 特征定义


特征是有意义的图像区域,该区域具有独特性和易于识别性。


因此,角点及高密度区域是很好的特征,而大量重复的模式和低密度区域不是好的特征。边缘可以将图像分成两个区域,因此也可以看作好的特征,


斑点(和周围差别很大的区域)也是有意义的特征。




检测角点特征:


import cv2

import numpy as np

img = cv2.imread("images/chess_board.png")

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

gray = np.float32(gray)

dst = cv2.cornerHarris(gray,2,23,0.04)

img[dst>0.01 * dst.max()] = [0,255,0]

while(True):

   cv2.imshow('corners',img)

   if cv2.waitKey(84) & 0xff == ord('q'):

       break

cv2.destroyAllWindows()



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


通过SIFT得到充满角点和特征的图像


import cv2

import numpy as np


imgpath = r".\images\varese.jpg"

img = cv2.imread(imgpath)

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

sift = cv2.xfeatures2d.SIFT_create()

keypoints,descriptor = sift.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('sift_keypoints',img)

cv2.waitKey()



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


SURF特征检测算法比SIFT快好几倍,它吸收了SIFT算法的思想。


SURF是OpenCV的一个类,SURF使用快速Hessian算法检测关键点,SURF会提取特征。


import cv2

import numpy as np


imgpath = r".\images\varese.jpg"

img = cv2.imread(imgpath)

alg = "SURF"

def fd(algorithm):

   if algorithm == "SIFT":

       return cv2.xfeatures2d.SIFT_create()

   if algorithm == "SURF":

       return  cv2.xfeatures2d.SURF_create(float(8000))



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=4,color=(51,163,236))

cv2.imshow('sift_keypoints',img)

cv2.waitKey()



6.1.4 基于ORB的特征检测和特征匹配


ORB是一种新的算法,用来替代SIFT和SURF算法。


ORB将基于FAST关键点检测的技术和基于BRIEF描述符的技术相结合、


1.FAST(Feature from Accelerated Segment Test)


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


2.BRIEF(Binary Robust Independent Elemetary Features)并不是特征检测算法,它只是一个描述符。


3.暴力匹配


暴力匹配是一种描述符匹配方法,该方法会比较两个描述符,并产生匹配结果的列表,称为暴力匹配的原因是该算法不涉及优化,第一个描述符的所有特征都和第二个描述符的特征进行比较。


6.1.5 ORB特征匹配


import numpy as np

import  cv2

from matplotlib import  pyplot as plt


img1 = cv2.imread('images/manowar_logo.png',cv2.IMREAD_GRAYSCALE)

img2 = cv2.imread('images/manowar_single.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)

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()


6.1.6 K-最近邻匹配(运行出错)


只需对前面的匹配操作进行修改:



6.1.7 FLANN匹配


近似最近邻的快速库


import numpy as np

import  cv2

from matplotlib import  pyplot as plt


queryImage = cv2.imread('images/bathory_album.jpg',0)

trainingImage = cv2.imread('images/vinyls.jpg',0)


sift = cv2.xfeatures2d.SIFT_create()

kp1, des1 = sift.detectAndCompute(queryImage,None)

kp2, des2 = sift.detectAndCompute(trainingImage,None)


FLANN_INDEX_KDTREE = 0

indexParams = dict(algorithm = FLANN_INDEX_KDTREE, trees=5)

searchParams = dict(checks=50)

flann = cv2.FlannBasedMatcher(indexParams,searchParams)

matches = flann.knnMatch(des1,des2,k=2)


matchesMask = [[0,0] for i in range(len(matches))]


for i,(m,n) in enumerate(matches):

   if m.distance < 0.7 *n.distance:

       matchesMask[i]=[1,0]


drawParams = dict(matchColor=(0,255,0),singlePointColor = (255,0,0),

                 matchesMask=matchesMask, flags=0)

resultImage = cv2.drawMatchesKnn(queryImage,kp1,trainingImage,kp2,matches,None,**drawParams)

plt.imshow(resultImage,),plt.show()



6.1.8 FLANN的单应性匹配


单应性是一个条件,该条件表面当两幅图像中一副出现投影畸变时,还能匹配。


import numpy as np

import cv2

from matplotlib import  pyplot as plt


MIN_MATCH_COUNT = 10


img1 = cv2.imread('images/bb.jpg',0)

img2 = cv2.imread('images/color2_small.jpg',0)


sift = cv2.xfeatures2d.SIFT_create()

kp1,des1 = sift.detectAndCompute(img1,None)

kp2,des2 = sift.detectAndCompute(img2,None)


FLANN_INDEX_KDTREE = 0

index_params = dict(algorithm=FLANN_INDEX_KDTREE,trees=5)

search_params = dict(checks=50)


flann = cv2.FlannBasedMatcher(index_params,search_params)


matches = flann.knnMatch(des1,des2,k=2)


good = []

for m,n in matches:

   if m.distance < 0.7*n.distance:

       good.append(m)

if len(good)>MIN_MATCH_COUNT:

   scr_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)

   dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)


   M,mask = cv2.findHomography(scr_pts,dst_pts,cv2.RANSAC,5.0)

   matchesMask = mask.ravel().tolist()

   h,w = img1.shape

   pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)

   dst = cv2.perspectiveTransform(pts,M)

   img2 = cv2.polylines(img2,[np.int32(dst)],True,255,3,cv2.LINE_AA)

else:

   print("Not enough matches are found")

   matchesMask = None


draw_params = dict(matchColor=(0,255,0),singlePointColor = None,

                  matchesMask = matchesMask,flags=2)


img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)

plt.imshow(img3,'gray'), plt.show()














6.1.9 基于文身取证的应用程序示例


#1.generate_description.py


import cv2

import numpy as np

from os import  walk

from os.path import  join

import sys


def create_descritors(folder):

   files = []

   for(dirpath,dirnames,filenames) in walk(folder):

       files.extend(filenames)

   for f in files:

       save_descriptor(folder,f,cv2.xfeatures2d.SIFT_create())


def save_descriptor(folder,image_path,feature_detector):

   img = cv2.imread(join(folder,image_path),0)

   keypoints,descriptors = feature_detector.detectAndCompute(img,None)

   descriptor_file = image_path.replace("jpg","npy")

   np.save(join(folder,descriptor_file),descriptors)


dir = 'anchors'

create_descritors(dir)


#2scan_and_match.py

from os.path import  join


from os import  walk


import  numpy as np


import  cv2


from sys import argv




folder = "anchors"


query = cv2.imread( join(folder,"tattoo_seed.jpg"),0)








files = []


images = []


descriptiors = []


for (dirpath,dirnames,filenames) in walk(folder):


   files.extend(filenames)


   for f in files:


       if f.endswith("npy") and f != "tattoo_seed.npy":


           descriptiors.append(f)


   print(descriptiors)






sift = cv2.xfeatures2d.SIFT_create()


query_kp ,query_ds = sift.detectAndCompute(query,None)




FLANN_INDEX_KDTREE = 0


index_params = dict(algorithm=FLANN_INDEX_KDTREE,trees = 5)


search_params = dict(checks = 50)


flann = cv2.FlannBasedMatcher(index_params,search_params)








MIN_MATCH_COUNT = 10




potential_culprits = {}


print(">>初始化图像扫描...")


for d in descriptiors:


   print("-----分析%s ---------"%d)


   matches=flann.knnMatch(query_ds,np.load(join(folder,d)),k=2)


   good = []


   for m,n in matches:


       if m.distance < 0.7*n.distance:


           good.append(m)


   if len(good)>MIN_MATCH_COUNT:


           print("%s 匹配!(%d)"%(d,len(good)))


   else:


           print("%s 不匹配!" % d)


   potential_culprits[d] = len(good)




max_matches = None


potential_suspect = None


for culprit, matches in potential_culprits.items():


   if max_matches == None or matches>max_matches:


       max_matches = matches


       potential_suspect = culprit




print("嫌疑人 %s" %potential_suspect.replace("npy","").upper())


相关文章
|
存储 分布式计算 Java
详细探讨在线上环境中慎用BigDecimal的原因和可能的替代方案
详细探讨在线上环境中慎用BigDecimal的原因和可能的替代方案
489 0
详细探讨在线上环境中慎用BigDecimal的原因和可能的替代方案
Sklearn库中的决策树模型有哪些主要参数?
Sklearn的决策树模型参数包括:criterion(默认&quot;gini&quot;)用于特征选择,splitter(默认&quot;best&quot;)决定划分点,max_depth限制树的最大深度,min_samples_split设置内部节点划分的最小样本数,min_samples_leaf定义叶子节点最少样本数,max_features(默认&quot;auto&quot;)控制搜索最优划分时的特征数量,random_state设定随机数种子,max_leaf_nodes限制最大叶子节点数,以及min_impurity_decrease阻止不纯度减少不足的节点划分。
277 0
|
7月前
|
存储 自然语言处理 NoSQL
6.4K star!轻松搞定专业领域大模型推理,这个知识增强框架绝了!
🔥「垂直领域大模型落地难?逻辑推理总出错?这个来自OpenSPG的开源框架,让专业领域知识服务变得像搭积木一样简单!」
320 3
|
存储 数据可视化 数据管理
基于阿里云服务的数据平台架构实践
本文主要介绍基于阿里云大数据组件服务,对企业进行大数据平台建设的架构实践。
1968 2
|
安全 Windows
win11系统‘ipconfig‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件
win11系统‘ipconfig‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件
2158 0
win11系统‘ipconfig‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件
|
SQL 消息中间件 分布式计算
Apache Doris 系列: 入门篇-数据导入及查询
Apache Doris 系列: 入门篇-数据导入及查询
1951 0
|
机器学习/深度学习 编解码 计算机视觉
YOLOv8改进 | 主干篇 | SwinTransformer替换Backbone(附代码 + 详细修改步骤 +原理介绍)
YOLOv8改进 | 主干篇 | SwinTransformer替换Backbone(附代码 + 详细修改步骤 +原理介绍)
1408 0
|
安全 Java Android开发
安卓开发中的新趋势:Kotlin与Jetpack的完美结合
【6月更文挑战第20天】在不断进化的移动应用开发领域,Android平台以其开放性和灵活性赢得了全球开发者的青睐。然而,随着技术的迭代,传统Java语言在Android开发中逐渐显露出局限性。Kotlin,一种现代的静态类型编程语言,以其简洁、安全和高效的特性成为了Android开发中的新宠。同时,Jetpack作为一套支持库、工具和指南,旨在帮助开发者更快地打造优秀的Android应用。本文将探讨Kotlin与Jetpack如何共同推动Android开发进入一个新的时代,以及这对开发者意味着什么。
203 5
|
存储 缓存 算法框架/工具
Transformers 4.37 中文文档(十三)(8)
Transformers 4.37 中文文档(十三)
278 1