#图像检索以及基于图像描述符的搜索
#检测角点特征
#使用cornerHarris函数检测图像的角点
import cv2
import numpy as np
img = cv2.imread('images/chess_board.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
#进行角点检测
#最重要的是第三个参数:定义了角点检测的敏感度(3,31)
dst = cv2.cornerHarris(gray,2,23,0.04)
img[dst>0.01 * dst.max()] = [0,0,255]
while (True):
cv2.imshow('coeners',img)
cv2.waitKey()
cv2.destroyALLWindows()
#使用DoG和SIFT进行特征提取与描述
import cv2
import sys
import numpy as np
#使用python的sys模块将图像路径通过命令行参数传递给脚本
imgpath = sys.argv[1]
img = cv2.imread(imgpath)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#创建sift对象
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_KEYPOINT,color=(51,163,236))
cv2.imshow('sift_keypoints',img)
while(True):
if cv2.waitKey(1000/12) & 0xff == ord("q")
break
cv2.destroyALLWindows()
#使用快速Hessian算法与SURF来提取和检测特征
import cv2
import sys
import numpy as np
imgpath = sys.argv[1]
img = cv2.imread(imgpath)
alg = sys.argv[2]
#选择检测特征的算法函数
def fd(algorithm):
if algorithm == "SIFT":
return cv2.xfeatures2d.SIFT_create()
if algorithm == "SURF":
return cv2.xfeatures2d.SURF_create(float(sys.argv[3] if len(sys.argv)==4 else 4000))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#创建SURF对象
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('keypoints',img)
cv2.waitKey()
cv2.destroyALLWindows()
#基于ORB的特征检测核特征匹配
#暴力匹配
import cv2
import numpy as np
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对象
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()
#K—最近邻匹配
import cv2
import numpy as np
from matplotlib import pyplot as plt
#获得查询图像和训练图像
img1 = cv2.imread('images/manowar_logo.png',0)
img2 = cv2.imread('images/manowar_single.jpg',0)
#创建ORB对象
orb = cv2.ORB_create()
#分别获得两幅图像的关键点信息和描述符
kp1,des1 = orb.detectAndCompute(img1,None)
kp2,des2 = orb.detectAndCompute(img2,None)
#创建匹配算法对象
bf = cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=True)
#K-最邻近匹配
matches = bf.knnMatch(des1,des2,k=2)
#将两幅图像的相似特征连接起来
img3 = cv2.drawMatches(img1,kp1,img2,kp2,matches[:40],img2,flags=2)
plt.imshow(img3)
plt.show()
#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(query,None)
kp2,des2 = sift.detectAndCompute(trainingImage,None)
#定义FLANN所需的参数
FLANN_INDEX_KDTREE = 0
#索引参数
indexParams = dict(algorithm=FLANN_INDEX_KDTREE,trees=5)
#搜索参数
searchParams = dict(checks=50)
#创建FLANN对象
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)
returnImage = cv2.drawMatchesKnn(queryImage,kp1,trainingImage,kp2,matches,None,**drawParams)
plt.imshow(returnImage)
plt.show()
#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所需的参数
FLANN_INDEX_KDTREE = 0
#索引参数
indexParams = dict(algorithm=FLANN_INDEX_KDTREE,trees=5)
#搜索参数
searchParams = dict(checks=50)
#创建FLANN对象
flann = cv2.FlannBasedMatcher(indexParams,searchParams)
#匹配
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:
#单应性处理
src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
des_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
M,mask = cv2.findHomography(src_pts,dst_pts,cv2.RANSAC,5.0)
matchesMask = mask.reval().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(pst,M)
img2 = cv2.polylines(img2,[np.int32(dst)],True,255,3,cv2.LINE_AA)
else:
print("匹配的特征个数不足")
drawParams = 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)
plt.show()
#======================================================================
#基于文身取证的应用出现示例
#现在已经有了犯罪文身的原始照片,但是不知道罪犯身份,但是已经拥有了
#文身数据库,因此可以通过文身图片来查询文身者的名字。
#可将任务分为两部分:首先将图像描述符保存在文件中,然后利用该照片作为
#查询图像,在数据库中检索匹配的图像。匹配的特征最多的就是罪犯。
#创建描述符并保存到文件中
import cv2
import numpy as np
from os import walk
from os.path import join
import sys
def create_descriptors(folder):
files = []
#根目录路径,根目录下文件夹名称,根目录下文件名称
for (dirpath,dirnames,filename) 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 = sys.argv[1]
create_descriptors(dir)
#扫描匹配
folder = sys.argv[1]
query = cv2.imread(join(folder,"tattoo_seed.jpg"),0)
#获取保存的描述符
files = []
images = []
descriptors = []
for (dirpath,dirnames,filenames) in walk(folder):
files.extend(filenames)
for f in file:
if f.endswith("npy") and f != "tatoo_seed.npy":
descriptors.append(f)
print(descriptors)
#创建sift对象
sift = cv2.xfeatures2d.SIFT_create()
query_kp,query_ds = sift.detectAndCompute(query,None)
#定义FLANN所需的参数
FLANN_INDEX_KDTREE = 0
#索引参数
indexParams = dict(algorithm=FLANN_INDEX_KDTREE,trees=5)
#搜索参数
searchParams = dict(checks=50)
#创建FLANN对象
flann = cv2.FlannBasedMatcher(indexParams,searchParams)
MIN_MATCH_COUNT = 10
potential_culprits = {}
#遍历匹配
for d in descriptors:
#匹配
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:
potential_culprits[d] = len(good)
#遍历寻找最大值
max_matches = None
potential_suspect = None
for culprint,matches in potential_culprits.iteritems():
if max_matches == None or matches>max_matches:
max_matches = matches
potential_suspect = culprint
#输出最有可能的罪犯的名字
print("potential suspect is %s"%potential_suspect.replace("npy","").upper())