opencv計算機視覺學習筆記五

第六章 圖像檢索以及基於圖像描述符的搜索

通過提取特徵進行圖像的匹配與搜索

1 特徵檢測算法

常見的特徵和提取算法:

Harris 檢測角點

Sift 檢測斑點(blob) 有專利保護

Surf 檢測斑點 有專利保護

Fast 檢測角點

Brief 檢測斑點

Orb 帶方向的fast算法和具有旋轉不變性的brief算法

特徵的定義

!/usr/bin/env python

-- coding: utf-8 --

@Time : 2016/12/5 12:30

@Author : Retacn

@Site : 檢測圖像的角點

@File : cornerHarris.py

@Software: PyCharm

author = “retacn”
copyright = “property of mankind.”
license = “CN”
version = “0.0.1”
maintainer = “retacn”
email = “[email protected]
status = “Development”

import cv2
import numpy as np

讀入圖像

img = cv2.imread(‘../test1.jpg’)

轉換顏色空間

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

檢測圖像角點

dst = cv2.cornerHarris(gray,
2,
23, # sobel算子的中孔,3-31之間的奇數
0.04)

將檢測到有角點標記爲紅色

img[dst > 0.01 * dst.max()] = [0, 0, 255]
while (True):
cv2.imshow(“corners”, img)
if cv2.waitKey(33) & 0xFF == ord(‘q’):
break
cv2.destroyAllWindows()

使用dog和sift進行特徵提取和描述

示例代碼如下:

import cv2
import sys
import numpy as py

讀入圖像

imgpath=sys.argv[1]

imgpath = ‘../test1.jpg’
img = cv2.imread(imgpath)

更換顏色空間

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

創建sift對象,計算灰度圖像,會使用dog檢測角點

sift = cv2.xfeatures2d.SIFT_create()
keypoints, descriptor = sift.detectAndCompute(gray, None)

print(keypoints)

關鍵點有以下幾個屬性

angle 表示特徵的方向

class_id 關鍵點的id

octave 特徵所在金字塔的等級

pt 圖像中關鍵點的座標

response 表示關鍵點的強度

size 表示特徵的直徑

img = cv2.drawKeypoints(image=img,
outImage=img,
keypoints=keypoints,
color=(51, 163, 236),
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

顯示圖像

cv2.imshow(‘sift_keypoints’, img)
while (True):
if cv2.waitKey(int(1000 / 12)) & 0xFF == ord(‘q’):
break
cv2.destroyAllWindows()

使用心有快速hessian算法和SURF來提取特徵

示例代碼發如下:

!/usr/bin/env python

-- coding: utf-8 --

@Time : 2016/12/10 17:30

@Author : Retacn

@Site : sift用於檢測斑點

@File : sift.py

@Software: PyCharm

author = “retacn”
copyright = “property of mankind.”
license = “CN”
version = “0.0.1”
maintainer = “retacn”
email = “[email protected]
status = “Development”

import cv2
import sys
import numpy as py

讀入圖像

imgpath=sys.argv[1]

alg=sys.argv[2]

threshold=sys.argv[3]

imgpath = ‘../test1.jpg’
img = cv2.imread(imgpath)

alg = ‘SURF’

alg = ‘SIFT’

threshold = ‘8000’

閾值越小特徵點越多

threshold = ‘4000’

def fd(algorithm):
if algorithm == ‘SIFT’:
return cv2.xfeatures2d.SIFT_create()
if algorithm == ‘SURF’:
# return cv2.xfeatures2d.SURF_create(float(threshold) if len(sys.argv) == 4 else 4000)
return cv2.xfeatures2d.SURF_create(float(threshold))

更換顏色空間

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

創建sift對象,計算灰度圖像,會使用dog檢測角點

fd_alg = fd(alg)
keypoints, descriptor = fd_alg.detectAndCompute(gray, None)

print(keypoints)

關鍵點有以下幾個屬性

angle 表示特徵的方向

class_id 關鍵點的id

octave 特徵所在金字塔的等級

pt 圖像中關鍵點的座標

response 表示關鍵點的強度

size 表示特徵的直徑

img = cv2.drawKeypoints(image=img,
outImage=img,
keypoints=keypoints,
color=(51, 163, 236),
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

顯示圖像

cv2.imshow(‘keypoints’, img)
while (True):
if cv2.waitKey(int(1000 / 12)) & 0xFF == ord(‘q’):
break
cv2.destroyAllWindows()

基於ORB的特徵檢測和特徵匹配

ORB是基於

FAST(featuresfrom accelerated segment test)關鍵點檢測技術

在像素周圍繪製一個圓,包含16個像素

BRIEF(binaryrobust independent elementary features) 描述符

暴力(brute-force)匹配法

比較兩個描述符,併產生匹配結果

ORB特徵匹配

示例代碼如下:

import numpy as np
import cv2
from matplotlib import pyplot as plt

cv2.ocl.setUseOpenCL(False)

讀入灰度圖像

img1 = cv2.imread(‘../test2_part.jpg’, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(‘../test2.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()

報如下錯誤:

cv2.error: D:\Build\OpenCV\opencv-3.1.0\modules\python\src2\cv2.cpp:163:error: (-215) The data should normally be NULL! in functionNumpyAllocator::allocate

解決辦法,添加如下代碼 :

cv2.ocl.setUseOpenCL(False)

k最鄰近配匹

import numpy as np
import cv2
from matplotlib import pyplot as plt

cv2.ocl.setUseOpenCL(False)

讀入灰度圖像

img1 = cv2.imread(‘../test2_part.jpg’, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(‘../test2.jpg’, cv2.IMREAD_GRAYSCALE)

創建orb特徵檢測器和描述符

orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)

knn匹配,返回k個匹配

bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=False)
matches = bf.knnMatch(des1, des2, k=2)

顯示圖像

img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, img2, flags=2)
plt.imshow(img3), plt.show()

Flann匹配法

Fast library for approximate nearestneighbors 近似最近鄰的快速庫

import numpy as np
import cv2
from matplotlib import pyplot as plt

讀入圖像

queryImage = cv2.imread(‘../test2_part.jpg’, cv2.IMREAD_GRAYSCALE)
trainingImage = cv2.imread(‘../test2.jpg’, cv2.IMREAD_GRAYSCALE)

創建sift對象

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

運行結果如下:

Flann單應性匹配

示例代碼如下:

!/usr/bin/env python

-- coding: utf-8 --

@Time : 2016/12/11 12:02

@Author : Retacn

@Site : flann的單應性匹配

@File : flann_homography.py

@Software: PyCharm

author = “retacn”
copyright = “property of mankind.”
license = “CN”
version = “0.0.1”
maintainer = “retacn”
email = “[email protected]
status = “Development”

import numpy as np
import cv2
from matplotlib import pyplot as plt

MIN_MATCH_COUNT = 10

讀入圖像

img1 = cv2.imread(‘../test3_part.jpg’, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(‘../test3.jpg’, cv2.IMREAD_GRAYSCALE)

創建sift對象

sift = cv2.xfeatures2d.SIFT_create()

查詢特徵點和描述符

kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, 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)

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)
dst_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.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 -%d/%d” % (len(good), MIN_MATCH_COUNT))
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()

運行結果如下:

基於紋身取證的應用程序示例

A 將圖像描述符保存到文件中

!/usr/bin/env python

-- coding: utf-8 --

@Time : 2016/12/11 13:52

@Author : Retacn

@Site : 將圖像描述符保存到文件中

@File : generate_descriptors.py

@Software: PyCharm

author = “retacn”
copyright = “property of mankind.”
license = “CN”
version = “0.0.1”
maintainer = “retacn”
email = “[email protected]
status = “Development”

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, 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):
print(“reading %s” % image_path)
if image_path.endswith(“npy”) or image_path.endswith(“avi”):
return
img = cv2.imread(join(folder, image_path), cv2.IMREAD_GRAYSCALE)
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)

B 掃描匹配

!/usr/bin/env python

-- coding: utf-8 --

@Time : 2016/12/11 14:05

@Author : Retacn

@Site : 掃描匹配

@File : scan4matches.py

@Software: PyCharm

author = “retacn”
copyright = “property of mankind.”
license = “CN”
version = “0.0.1”
maintainer = “retacn”
email = “[email protected]
status = “Development”

from os.path import join
from os import walk
import numpy as np
import cv2
from sys import argv
from matplotlib import pyplot as plt

創建文件名數組

folder = argv[1]
query = cv2.imread(join(folder, ‘part.jpg’), cv2.IMREAD_GRAYSCALE)

創建全局的文件,圖片,描述符

files = []
images = []
descriptors = []
for (dirpath, dirnames, filenames) in walk(folder):
files.extend(filenames)
for f in files:
if f.endswith(‘npy’) and f != ‘part.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
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(“>> Initiating picture scan…”)
for d in descriptors:
print(“——— analyzing %s for matches ————” % 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 is a match! (%d)’ % (d, len(good)))
else:
print(‘%s is not a match ’ % 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(“potential suspect is %s” % potential_suspect.replace(“npy”, “”).upper())

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章