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

mac2025-12-19  5

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

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

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

6.1 特征检测算法

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

Harris:用于检测角点

SIFT:用于检测斑点(Blob)

SURF:用于检测斑点

FAST:检测角点

BRIEF:检测斑点

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

匹配算法:

暴力(Brute-Force)匹配法

基于FLANN的匹配法

 

6.1.1 特征定义

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

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

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

 

 

检测角点特征:

import cv2import 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'):         breakcv2.destroyAllWindows()

 

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

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

import cv2import 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 cv2import 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 npimport  cv2from 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 npimport  cv2from 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 = 0indexParams = 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 npimport cv2from matplotlib import  pyplot as plt MIN_MATCH_COUNT = 10img1 = 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 = 0index_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 = Nonedraw_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 cv2import numpy as npfrom os import  walkfrom os.path import  joinimport sysdef 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())

 

 

 

 

最新回复(0)