使用OpenCV-python实现以图搜图,首先加载必要的库
import numpy as np
import glob
import csv
import cv2
使用BRISK方法描述图片的特征
建立封面描述,计算特征点和特征点周围的信息
class CoverDescriptor:
def describe(self, image):
# 使用BRISK方法对图片进行特征提取,同类型的还有SIFT,SURF等等
descriptor = cv2.BRISK_create()
# 第一步是detect找到特征点,特征点信息包括关键点的位置,大小,旋转角等等
# 第二步是计算特征点周围的特征描述子,None表示没有遮罩
(kps, descs) = descriptor.detectAndCompute(image, None)
# 这里的keypoint只需要坐标位置就可以了,丢弃其他性质
kps = np.float32([kp.pt for kp in kps])
# 返回ROI点和对应周围的环境描述子
return (kps, descs)
使用KNN和RANSAC方法对特征进行匹配
建立匹配描述
class CoverMatcher:
# 2个必须输入分别为:待查找照片的描述对象,所有封面所在的文件夹位置
# ratio是计算单应矩阵最邻近举例的比例
# BRISK算法产生的是二值特征向量binary feature vectors,不能用欧拉距离衡量,需要使用Hamming方法
# 当然对应的SIFT产生的是实值特征向量real-valued feature vectors,可以用欧拉距离度量
def __init__(self, descriptor, coverPaths, ratio = 0.7, minMatches = 40,
useHamming = True):
self.descriptor = descriptor
self.coverPaths = coverPaths
self.ratio = ratio
self.minMatches = minMatches
self.distanceMethod = "BruteForce"
if useHamming:
self.distanceMethod += "-Hamming"
def search(self, queryKps, queryDescs):
results = {
}
for coverPath in self.coverPaths:
cover = cv2.imread(coverPath)
gray = cv2.cvtColor(cover, cv2.COLOR_BGR2GRAY)
(kps, descs) = self.descriptor.describe(gray)
# query是待查图片的特征信息,后面的是当前数据库里每一张图片的信息
score = self.match(queryKps, queryDescs, kps, descs)
# 把分数存入字典,字典的键固定为50个,值为对应的匹配分
results[coverPath] = score
if len(results) > 0:
results = sorted([(v, k) for (k, v) in results.items() if v > 0],
reverse = True)
return results
# 输入为两张图的keypoints和feature vectors
def match(self, kpsA, featuresA, kpsB, featuresB):
# 新建一个描述匹配的对象,距离的度量方法是BruteForce-Hamming
matcher = cv2.DescriptorMatcher_create(self.distanceMethod)
# 对两幅图片的特征描述做knn近邻匹配
# 2表示对每个特征向量寻找和他最近的2个邻居
# 返回的并不是实际映射的关键点mapping keypoints
rawMatches