OpenCV 3计算机视觉 python语言实现笔记(六)

#图像检索以及基于图像描述符的搜索


#检测角点特征
#使用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())

你可能感兴趣的:(OpenCV3,计算机视觉)