1、圖像描述符、特征描述符和特征向量的定義
特征向量:用於表示和量化圖像的數字列表,簡單理解成將圖片轉化為一個數字列表表示。特征向量中用來描述圖片的各種屬性的向量稱為特征矢量。
圖像描述符:理解成一種算法和方法,控制整個圖像如何轉變為特征向量。量化是的圖像形狀,顏色,紋理,或三者的任何組合。輸入1個圖像時,圖像描述符將返回1個特征向量。主要用於圖像分類。缺乏區分圖像中不同對象的能力。
特征描述符:是一種算法和方法,控制圖像部分區域,對部分區域返回多個特征向量。輸入1個圖像,返回多個特征向量(主要用來處理圖像的局部)。主要用於圖像匹配(視覺檢測),匹配圖像中的物品。
2、色彩通道統計
運行命令:python color_channel_stats.py
原理:通過統計圖像中的每個色彩通道(及RGB色彩通道),憑據通道值和標准差等方法,量化和表示圖像的顏色分布,從而對圖像進行分類。(主要運用顏色差異名義,不同場景圖片分類)
from scipy.spatial import distance as dist from imutils import paths import numpy as np import cv2 imagePaths = sorted(list(paths.list_images("dinos"))) index = {} for imagePath in imagePaths: image = cv2.imread(imagePath) filename = imagePath[imagePath.rfind("/") + 1:] (means, stds) = cv2.meanStdDev(image)#計算圖像中每個色彩通道的平均值和標准偏差 features = np.concatenate([means, stds]).flatten()#將每個色彩通道的平均值和標准偏差連接在一起,形成我們的特征向量 index[filename] = features query = cv2.imread(imagePaths[0]) cv2.imshow("Query (trex_01.png)", query) keys = sorted(index.keys()) for (i, k) in enumerate(keys): if k == "trex_01.png": continue image = cv2.imread(imagePaths[i]) d = dist.euclidean(index["trex_01.png"], index[k])#計算目標圖像特征向量與我們數據集中的特征向量之間的歐幾里德距離。d越小,顏色通道越相似,圖片越相似。 cv2.putText(image, "%.2f" % (d), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2) cv2.imshow(k, image) cv2.waitKey(0)
3、彩色直方圖
原理:通過顏色的分布,運用機器學習中的K均值聚類運用於聚類顏色直方圖。無參考值進行圖像分類。(關鍵是需要對顏色直方圖理解)
文件結構:
|--- pyimagesearch
import cv2 import imutils class LabHistogram: def __init__(self, bins): self.bins = bins def describe(self, image, mask=None): lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB) hist = cv2.calcHist([lab], [0, 1, 2], mask, self.bins, [0, 256, 0, 256, 0, 256])#獲取3D直方圖 #將圖片大小標准化,忽略圖片大小對直方圖的影響 if imutils.is_cv2(): hist = cv2.normalize(hist).flatten() else: hist = cv2.normalize(hist,hist).flatten() return hist
cluster_histograms.py
from pyimagesearch.descriptors.labhistogram import LabHistogram from sklearn.cluster import KMeans from imutils import paths import numpy as np import argparse import cv2 ap = argparse.ArgumentParser() ap.add_argument("-d", "--dataset", required=True, help="path to the input dataset directory") ap.add_argument("-k", "--clusters", type=int, default=2, help="# of clusters to generate")#默認設置k值為2,及將圖片分為倆類。 args = vars(ap.parse_args()) desc = LabHistogram([8, 8, 8]) data = [] imagePaths = list(paths.list_images(args["dataset"])) imagePaths = np.array(sorted(imagePaths)) for imagePath in imagePaths: image = cv2.imread(imagePath) hist = desc.describe(image) data.append(hist)#描述符加入到數據集中 #對描述符進行聚類 clt = KMeans(n_clusters=args["clusters"]) labels = clt.fit_predict(data) for label in np.unique(labels): #獲取每個集群的唯一ID,進行分類 labelPaths = imagePaths[np.where(labels == label)] #將同一集群的圖片輸出顯示 for (i, path) in enumerate(labelPaths): image = cv2.imread(path) cv2.imshow("Cluster {}, Image #{}".format(label + 1, i + 1), image) cv2.waitKey(0) cv2.destroyAllWindows()
4、胡默斯
作用:用於物品形狀檢測,處理二值圖片,提取圖片中物體的形狀。
運行命令:python extract_hu_moments.py
extract_hu_moments.py
import cv2 import imutils image = cv2.imread("planes.png") image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) moments = cv2.HuMoments(cv2.moments(image)).flatten() print("ORIGINAL MOMENTS: {}".format(moments)) cv2.imshow("Image", image) cv2.waitKey(0) #找到圖片中每個物件的行輪廓 cnts = cv2.findContours(image.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if imutils.is_cv2() else cnts[1] for (i, c) in enumerate(cnts): (x, y, w, h) = cv2.boundingRect(c) roi = image[y:y + h, x:x + w] #提取每個形狀的hu_monebts值 moments = cv2.HuMoments(cv2.moments(roi)).flatten() print("MOMENTS FOR PLANE #{}: {}".format(i + 1, moments)) cv2.imshow("ROI #{}".format(i + 1), roi) cv2.waitKey(0)
作用:隨機生成數據集
運行命令:python generate_images.py --output output
genetate_images.py
import numpy as np import argparse import uuid import cv2 ap = argparse.ArgumentParser() ap.add_argument("-o", "--output", required=True, help="Path to the output directory") ap.add_argument("-n", "--num-images", type=int, default=500, help="# of disctrator images to generate") args = vars(ap.parse_args()) for i in range(0, args["num_images"]): image = np.zeros((500, 500, 3), dtype="uint8") (x, y) = np.random.uniform(low=105, high=405, size=(2,)).astype("int0") r = np.random.uniform(low=25, high=100, size=(1,)).astype("int0")[0] color = np.random.uniform(low=0, high=255, size=(3,)).astype("int0") color = tuple(map(int, color)) cv2.circle(image, (x, y), r, color, -1) cv2.imwrite("{}/{}.jpg".format(args["output"], uuid.uuid4()), image) image = np.zeros((500, 500, 3), dtype="uint8") topLeft = np.random.uniform(low=25, high=225, size=(2,)).astype("int0") botRight = np.random.uniform(low=250, high=400, size=(2,)).astype("int0") color = np.random.uniform(low=0, high=255, size=(3,)).astype("int0") color = tuple(map(int, color)) cv2.rectangle(image, tuple(topLeft), tuple(botRight), color, -1) cv2.imwrite("{}/{}.jpg".format(args["output"], uuid.uuid4()), image)
作用:從數據集中,找出異常形狀
運行命令:python find_rectangle.py --dataset output
find_rectangle.py
from sklearn.metrics.pairwise import pairwise_distances import numpy as np import argparse import glob import cv2 import imutils ap = argparse.ArgumentParser() ap.add_argument("-d", "--dataset", required=True, help="Path to the dataset directory") args = vars(ap.parse_args()) imagePaths = sorted(glob.glob(args["dataset"] + "/*.jpg")) data = [] for imagePath in imagePaths: image = cv2.imread(imagePath) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 5, 255, cv2.THRESH_BINARY)[1] cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if imutils.is_cv2() else cnts[1] c = max(cnts, key=cv2.contourArea) (x, y, w, h) = cv2.boundingRect(c) roi = cv2.resize(thresh[y:y + h, x:x + w], (50, 50))#忽略圖片大小的影響 moments = cv2.HuMoments(cv2.moments(roi)).flatten() data.append(moments) D = pairwise_distances(data).sum(axis=1) i = np.argmax(D) #獲取距離最大的圖形,圓形距離很小,矩形距離較大 image = cv2.imread(imagePaths[i]) print("Found square: {}".format(imagePaths[i])) cv2.imshow("Outlier", image) cv2.waitKey(0)
5、Zernike時刻
運用Zernike矩陣量化圖像中的形狀。在圖片中尋找某個特定的形狀
from scipy.spatial import distance as dist import numpy as np import mahotas import cv2 import imutils def describe_shapes(image): shapeFeatures = [] gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (13, 13), 0) cv2.imshow("2", blurred) thresh = cv2.threshold(blurred, 120, 255, cv2.THRESH_BINARY)[1] thresh = cv2.dilate(thresh, None, iterations = 4) thres = cv2.erode(thresh, None, iterations = 2) cv2.imshow("1", thres) cv2.waitKey(0) cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if imutils.is_cv2() else cnts[1] for c in cnts: mask = np.zeros(image.shape[:2], dtype = "uint8") cv2.drawContours(mask, [c], -1, 255, -1) (x, y, w, h) = cv2.boundingRect(c) roi = mask[y:y + h, x:x + w] cv2.imshow("roi", roi) cv2.waitKey(0) features = mahotas.features.zernike_moments(roi, cv2.minEnclosingCircle(c)[1], degree = 8) shapeFeatures.append(features) return(cnts, shapeFeatures) refImage = cv2.imread("2.jpg") (_, gameFeatures) = describe_shapes(refImage) shapesImage = cv2.imread("1.jpg") (cnts, shapeFeatures) = describe_shapes(shapesImage) D = dist.cdist(gameFeatures, shapeFeatures) i = np.argmin(D) #獲取最小距離的下標 for (j, c) in enumerate(cnts): if i != j: box = cv2.minAreaRect(c) box = np.int0(cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)) cv2.drawContours(shapesImage, [box], - 1, (0, 0, 255), 2) box = cv2.minAreaRect(cnts[i]) box = np.int0(cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)) cv2.drawContours(shapesImage, [box], - 1, (0, 255, 0), 2) (x, y, w, h) = cv2.boundingRect(cnts[i]) cv2.putText(shapesImage, "FOUND!", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 3) cv2.imshow("Input Image", refImage) cv2.imshow("Detected Shapes", shapesImage) cv2.waitKey(0)
6、Haralick紋理功能
依據數據學習,分析紋理,再將數據圖片依據紋理分類:
from sklearn.svm import LinearSVC import argparse import glob import mahotas import cv2 ap = argparse.ArgumentParser() ap.add_argument("-d", "--training", required = True, help = "Path to the dataset of textures") ap.add_argument("-t", "--test", required = True,help = "Path to the test images" ) args = vars(ap.parse_args()) print("[INFO] extracting features...") data = [] labels = [] for imagePath in glob.glob(args["training"] + "/*.jpg"): image = cv2.imread(imagePath) image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) texture = imagePath[imagePath.rfind("/") + 1:].split("_")[0] features = mahotas.features.haralick(image).mean(axis = 0) data.append(features) labels.append(texture) print("[INFO] training model...") model = LinearSVC(C = 10.0, random_state = 42) model.fit(data, labels) print("[INFO] classifying...") for imagePath in glob.glob(args["test"] + "/*.jpg"): image = cv2.imread(imagePath) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) features = mahotas.features.haralick(gray).mean(axis = 0) print features pred = model.predict(features.reshape(1, - 1))[0] print pred cv2.putText(image, pred, (20, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 3) cv2.imshow("Image", image) cv2.waitKey(0)
7、本地二進制模式
原理:LBP 在本地處理像素, 而不是使用灰度共生矩陣。通過量化小區域特征,分析圖片的特征向量,再對圖片進行分類。
注意點:記住半徑r 和點數p的影響也很重要。積分越多p 你品嘗,更多的模式,你可以編碼,但在同一時間,你增加你的計算成本。另一方面,如果增加半徑大小r, 則可以在圖像中捕捉較大的紋理細節。但是,如果增加r 而不增加p ,那么您將失去LBP描述符的局部區分能力。
例:時尚索引
文件結構: |--- pyimagesearch | |--- __init__.py | |--- descriptors | | |---- __init__.py | | |--- localbinarypatterns.py |--- search_shirts.py
作用:創建二進制描述符。
localbinarypatterns.py
from skimage import feature import numpy as np class LocalBinaryPatterns: def __init__(self, numPoints, radius): #圍繞中心像素的圖案半徑,半徑外圍點數,決定計算量 self.numPoints = numPoints self.radius = radius def describe(self, image, eps=1e-7): lbp = feature.local_binary_pattern(image, self.numPoints, self.radius, method="uniform") (hist, _) = np.histogram(lbp.ravel(), bins=range(0, self.numPoints + 3), range=(0, self.numPoints + 2)) # normalize the histogram hist = hist.astype("float") hist /= (hist.sum() + eps) # return the histogram of Local Binary Patterns return hist
作用:測試二進制描述符的紋理特征效果
運行命令:python search_shirts.py --dataset shirts --query queries/query_01.jpg
search_shirts.py:
from __future__ import print_function from pyimagesearch import LocalBinaryPatterns from imutils import paths import numpy as np import argparse import cv2 ap = argparse.ArgumentParser() ap.add_argument("-d", "--dataset", required=True, help="path to the dataset of shirt images") ap.add_argument("-q", "--query", required=True, help="path to the query image") args = vars(ap.parse_args()) desc = LocalBinaryPatterns(24, 8) index = {} for imagePath in paths.list_images(args["dataset"]): image = cv2.imread(imagePath) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) hist = desc.describe(gray) filename = imagePath[imagePath.rfind("/") + 1:] index[filename] = hist query = cv2.imread(args["query"]) queryFeatures = desc.describe(cv2.cvtColor(query, cv2.COLOR_BGR2GRAY)) cv2.imshow("Query", query) results = {} for (k, features) in index.items(): d = 0.5 * np.sum(((features - queryFeatures) ** 2) / (features + queryFeatures + 1e-10)) results[k] = d results = sorted([(v, k) for (k, v) in results.items()])[:3]#選取前較小距離(相似性)高的,前3個結果 for (i, (score, filename)) in enumerate(results):#將前3個結果顯示出來 print("#%d. %s: %.4f" % (i + 1, filename, score)) image = cv2.imread(args["dataset"] + "/" + filename) cv2.imshow("Result #{}".format(i + 1), image) cv2.waitKey(0)
8、定向梯度直方圖
原理:運用HOG描述符,他主要用於描述圖像中物體的結構形狀和外觀,使其成為物體分類的優秀描述符。但是,由於HOG捕獲局部強度梯度和邊緣方向,因此它也會產生良好的紋理描述符
知識點:pixels_per_cell中的像素 越多,我們的表示越粗糙。類似地,pixels_per_cell的較小值將產生更細粒度(輪廓更明顯)
疑問:1、from sklearn.neighbors import KNeighborsClassifier
解釋:http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html
運行命令:python recognize_car_logos.py --training car_logos --test test_images
recognize_car_logs.py
from sklearn.neighbors import KNeighborsClassifier from skimage import exposure from skimage import feature from imutils import paths import argparse import imutils import cv2 ap = argparse.ArgumentParser() ap.add_argument("-d", "--training", required=True, help="Path to the logos training dataset") ap.add_argument("-t", "--test", required=True, help="Path to the test dataset") args = vars(ap.parse_args()) print "[INFO] extracting features..." data = [] labels = [] for imagePath in paths.list_images(args["training"]): #提取每個標志的hog特征向量 make = imagePath.split("/")[-2] image = cv2.imread(imagePath) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) edged = imutils.auto_canny(gray) cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if imutils.is_cv2() else cnts[1] c = max(cnts, key=cv2.contourArea) (x, y, w, h) = cv2.boundingRect(c) logo = gray[y:y + h, x:x + w] logo = cv2.resize(logo, (200, 100)) H = feature.hog(logo, orientations=9, pixels_per_cell=(10, 10), cells_per_block=(2, 2), transform_sqrt=True, block_norm="L1") data.append(H) labels.append(make) print("[INFO] training classifier...") model = KNeighborsClassifier(n_neighbors=1) #對特征數據進行K值分類 model.fit(data, labels) print("[INFO] evaluating...") for (i, imagePath) in enumerate(paths.list_images(args["test"])): image = cv2.imread(imagePath) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) logo = cv2.resize(gray, (200, 100)) (H, hogImage) = feature.hog(logo, orientations=9, pixels_per_cell=(10, 10), cells_per_block=(2, 2), transform_sqrt=True, block_norm="L1", visualise=True) pred = model.predict(H.reshape(1, -1))[0] hogImage = exposure.rescale_intensity(hogImage, out_range=(0, 255)) hogImage = hogImage.astype("uint8") cv2.imshow("HOG Image #{}".format(i + 1), hogImage) cv2.putText(image, pred.title(), (10, 35), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 3) cv2.imshow("Test Image #{}".format(i + 1), image) cv2.waitKey(0)
9、關鍵點檢測
9.1、FAST關鍵點檢測
原理:必須有至少Ñ沿着連續像素圓形周邊具有半徑- R是所有或者亮或更暗比中心像素由閾值t
疑問:是否可以修改參數,半徑-R和N值?
運行命令:python fast_keypoint.py
fast_keypoint.py
from __future__ import print_function import numpy as np import cv2 import imutils image = cv2.imread("next.png") orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("FAST") kps = detector.detect(gray) else: detector = cv2.FastFeatureDetector_create() kps = detector.detect(gray, None) print("# of keypoints: {}".format(len(kps))) for kp in kps: r = int(0.5 * kp.size) (x, y) = np.int0(kp.pt) cv2.circle(image, (x, y), r, (0, 255, 255), 2) cv2.imshow("Images", np.hstack([orig, image])) cv2.waitKey(0)
9.2Harris關鍵點檢測
原理:將分別在x和y方向上對該區域中的梯度值求和:


如果這兩個值都足夠“大”,那么我們可以將該區域定義為角落。該過程針對輸入圖像中的每個像素完成。這種方法是有效的,因為紅色圓圈內的區域會有大量的水平和垂直梯度 - 當發生這種情況時,我們知道我們找到了一個角落.
疑問:1、harris函數的參數的作用:
• img - 數據類型為 float32 的輸入圖像。
• blockSize - 角點檢測中要考慮的領域大小。
• ksize - Sobel 求導中使用的窗口大小
• k - Harris 角點檢測方程中的自由參數,取值參數為 [0,04,0.06].
2、harris什么時候被調用?
harris_keypoint.py
from __future__ import print_function import numpy as np import cv2 import imutils def harris(gray, blockSize=2, apetureSize=3, k=0.1, T=0.02): gray = np.float32(gray) H = cv2.cornerHarris(gray, blockSize, apetureSize, k) kps = np.argwhere(H > T * H.max()) kps = [cv2.KeyPoint(pt[1], pt[0], 3) for pt in kps] return kps image = cv2.imread("next.png") orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("HARRIS") kps = detector.detect(gray) else: kps = harris(gray) print("# of keypoints: {}".format(len(kps))) for kp in kps: r = int(0.5 * kp.size) (x, y) = np.int0(kp.pt) cv2.circle(image, (x, y), r, (0, 255, 255), 2) # show the image cv2.imshow("Images", np.hstack([orig, image])) cv2.waitKey(0)
9.3、GFTT關鍵點檢測
原理:提出了以下R的計算來表明一個地區是否是一個角落:在這種情況下,我們只是取特征值分解分量的最小值。如果這個值R大於我們的閾值T (即
),那么我們可以將該區域標記為拐角。(在harris基礎上改進)
from __future__ import print_function import numpy as np import cv2 import imutils def gftt(gray, maxCorners=0, qualityLevel=0.01, minDistance=1, mask=None, blockSize=3, useHarrisDetector=False, k=0.04): kps = cv2.goodFeaturesToTrack(gray, maxCorners, qualityLevel, minDistance, mask=mask, blockSize=blockSize, useHarrisDetector=useHarrisDetector, k=k) return [cv2.KeyPoint(pt[0][0], pt[0][1], 3) for pt in kps] image = cv2.imread("next.png") orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("GFTT") kps = detector.detect(gray) else: kps = gftt(gray) for kp in kps: r = int(0.5 * kp.size) (x, y) = np.int0(kp.pt) cv2.circle(image, (x, y), r, (0, 255, 255), 2) print("# of keypoints: {}".format(len(kps))) cv2.imshow("Images", np.hstack([orig, image])) cv2.waitKey(0)
9.4、DoG關鍵點檢測器
通過對圖像縮放變化,尋找角點,獲取的角點繪制出來的圓有大小區別。
from __future__ import print_function import numpy as np import cv2 import imutils image = cv2.imread("next.png") orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("SIFT") kps = detector.detect(gray) else: detector = cv2.xfeatures2d.SIFT_create() (kps, _) = detector.detectAndCompute(gray, None) print("# of keypoints: {}".format(len(kps))) for kp in kps: r = int(0.5 * kp.size) (x, y) = np.int0(kp.pt) cv2.circle(image, (x, y), r, (0, 255, 255), 2) cv2.imshow("Images", np.hstack([orig, image])) cv2.waitKey(0)
9.5、Fast_Hessian關鍵點檢測
作用:類似於高斯差分,快速Hessian關鍵點檢測器用於定位圖像中可重復的“斑點”狀區域。這些區域可能是邊緣,角落或兩者
from __future__ import print_function import numpy as np import cv2 import imutils image = cv2.imread("next.png") orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("SURF") kps = detector.detect(gray) else: detector = cv2.xfeatures2d.SURF_create() (kps, _) = detector.detectAndCompute(gray, None) print("# of keypoints: {}".format(len(kps))) for kp in kps: r = int(0.5 * kp.size) (x, y) = np.int0(kp.pt) cv2.circle(image, (x, y), r, (0, 255, 255), 2) cv2.imshow("Images", np.hstack([orig, image])) cv2.waitKey(0)
9.6、STAR關鍵點檢測
運用情況:用於檢測圖像中的“斑點”狀區域
from __future__ import print_function import numpy as np import cv2 import imutils image = cv2.imread("next.png") orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("STAR") kps = detector.detect(gray) else: detector = cv2.xfeatures2d.StarDetector_create() kps = detector.detect(gray) print("# of keypoints: {}".format(len(kps))) for kp in kps: r = int(0.5 * kp.size) (x, y) = np.int0(kp.pt) cv2.circle(image, (x, y), r, (0, 255, 255), 2) cv2.imshow("Images", np.hstack([orig, image])) cv2.waitKey(0)
9.7、MSER關鍵點檢測
作用:MSER檢測器用於檢測圖像中的“斑點”狀結構。假設這些區域很小,具有相對相同的像素強度,並且被對比像素包圍
from __future__ import print_function import numpy as np import cv2 import imutils image = cv2.imread("next.png") orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # detect MSER keypoints in the image if imutils.is_cv2(): detector = cv2.FeatureDetector_create("MSER") kps = detector.detect(gray) else: detector = cv2.MSER_create() kps = detector.detect(gray, None) print("# of keypoints: {}".format(len(kps))) for kp in kps: r = int(0.5 * kp.size) (x, y) = np.int0(kp.pt) cv2.circle(image, (x, y), r, (0, 255, 255), 2) cv2.imshow("Images", np.hstack([orig, image])) cv2.waitKey(0)
9.8、密集關鍵點檢測
作用:濃密檢測器 將圖像中的每個k像素標記為關鍵點
from __future__ import print_function import numpy as np import argparse import cv2 import imutils def dense(image, step, radius): kps = [] for x in range(0, image.shape[1], step): for y in range(0, image.shape[0], step): kps.append(cv2.KeyPoint(x, y, radius * 2)) return kps ap = argparse.ArgumentParser() ap.add_argument("-s", "--step", type=int, default=28, help="step (in pixels) of the dense detector") args = vars(ap.parse_args()) image = cv2.imread("next.png") orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) kps = [] radii = (4, 8, 12) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("Dense") detector.setInt("initXyStep", args["step"]) rawKps = detector.detect(gray) else: rawKps = dense(gray, args["step"], 1) for rawKp in rawKps: for r in radii: kp = cv2.KeyPoint(x=rawKp.pt[0], y=rawKp.pt[1], _size=r * 2) kps.append(kp) print("# dense keypoints: {}".format(len(rawKps))) print("# dense + multi radii keypoints: {}".format(len(kps))) for kp in kps: r = int(0.5 * kp.size) (x, y) = np.int0(kp.pt) cv2.circle(image, (x, y), r, (0, 255, 255), 1) cv2.imshow("Images", np.hstack([orig, image])) cv2.waitKey(0)
9.9、BRISK關鍵點檢測器
運用情況:多尺度版本
from __future__ import print_function import numpy as np import cv2 import imutils image = cv2.imread("next.png") orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("BRISK") kps = detector.detect(gray) else: detector = cv2.BRISK_create() kps = detector.detect(gray, None) print("# of keypoints: {}".format(len(kps))) for kp in kps: r = int(0.5 * kp.size) (x, y) = np.int0(kp.pt) cv2.circle(image, (x, y), r, (0, 255, 255), 2) cv2.imshow("Images", np.hstack([orig, image])) cv2.waitKey(0)
9.10、ORB關鍵點檢測器的運用
作用:ORB用於檢測圖像中的角點
from __future__ import print_function import numpy as np import cv2 import imutils image = cv2.imread("next.png") orig = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("ORB") kps = detector.detect(gray) else: detector = cv2.ORB_create() kps = detector.detect(gray, None) print("# of keypoints: {}".format(len(kps))) for kp in kps: r = int(0.5 * kp.size) (x, y) = np.int0(kp.pt) cv2.circle(image, (x, y), r, (0, 255, 255), 2) cv2.imshow("Images", np.hstack([orig, image])) cv2.waitKey(0)
10、局部不變描述符
10.1、SIFT
作用:檢測關鍵點並從圖像中提取SIFT特征向量
from __future__ import print_function import argparse import cv2 import imutils ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image") args = vars(ap.parse_args()) image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("SIFT") extractor = cv2.DescriptorExtractor_create("SIFT") kps = detector.detect(gray) (kps, descs) = extractor.compute(gray, kps) else: detector = cv2.xfeatures2d.SIFT_create() (kps, descs) = detector.detectAndCompute(gray, None) print("[INFO] # of keypoints detected: {}".format(len(kps))) print("[INFO] feature vector shape: {}".format(descs.shape))
10.2、RootSIFT
作用:定義RootSIFT檢測器,獲取關鍵點特征
rootsift.py
import numpy as np import cv2 import imutils class RootSIFT: def __init__(self): if imutils.is_cv2(): self.extractor = cv2.DescriptorExtractor_create("SIFT") else: self.extractor = cv2.xfeatures2d.SIFT_create() def compute(self, image, kps, eps=1e-7): if imutils.is_cv2: (kps, descs) = self.extractor.compute(image, kps) else: (kps, descs) = self.extractor.detectAndCompute(image, None) if len(kps) == 0: return ([], None) descs /= (descs.sum(axis=1, keepdims=True) + eps) descs = np.sqrt(descs) return (kps, descs)
作用:從圖像中提取RootSIFT描述符
extract_rpptsift.py
from __future__ import print_function from pyimagesearch.descriptors import RootSIFT import argparse import cv2 import imutils ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image") args = vars(ap.parse_args()) image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("SIFT") extractor = RootSIFT() kps = detector.detect(gray) else: detector = cv2.xfeatures2d.SIFT_create() extractor = RootSIFT() (kps, _) = detector.detectAndCompute(gray, None) (kps, descs) = extractor.compute(gray, kps) print("[INFO] # of keypoints detected: {}".format(len(kps))) print("[INFO] feature vector shape: {}".format(descs.shape))
10.3、SURF
作用:SURF的第一步是選擇圍繞關鍵點的圖像的矩形區域。在關鍵點檢測階段確定區域的確切大小
extract_surf.py
from __future__ import print_function import argparse import cv2 import imutils ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image") args = vars(ap.parse_args()) image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("SURF") extractor = cv2.DescriptorExtractor_create("SURF") kps = detector.detect(gray) (kps, descs) = extractor.compute(gray, kps) else: detector = cv2.xfeatures2d.SURF_create() (kps, descs) = detector.detectAndCompute(gray, None) print("[INFO] # of keypoints detected: {}".format(len(kps))) print("[INFO] feature vector shape: {}".format(descs.shape))
10.4、實值特征匹配
知識點:提取關鍵點的圖像坐標,例:ksp[0].pt
運行命令:1、python draw_matches.py --first jp_01.png --second jp_02.png --detector SURF --extractor SIFT
2、python draw_matches.py --first jp_01.png --second jp_02.png --detector SURF --extractor RootSIFT
3、python draw_matches.py --first jp_01.png --second jp_02.png --detector SURF --extractor SURF
#coding=utf-8 from __future__ import print_function import numpy as np import argparse import cv2 from imutils.feature.factories import FeatureDetector_create, DescriptorExtractor_create, DescriptorMatcher_create ap = argparse.ArgumentParser() ap.add_argument("-f", "--first", required = True, help = "Path to first image") #提取關鍵點和特征向量的第一幅圖像的路經 ap.add_argument("-s", "--second", required = True, help = "Path to second image")#提取關鍵點和特征向量的第二幅圖像的路經 ap.add_argument("-d", "--detector", type = str, default="SURF", help = "Kepyoint detector to use.Options ['BRISK', 'DENSE', 'DOG', 'SIFT', 'FAST', 'FASTHESSIAN', 'SURF', 'GFTT','HARRIS', 'MSER', 'ORB', 'STAR']")#用於在倆個圖像執行關鍵點檢測的關鍵點的檢測器 ap.add_argument("-e", "--extractor", type = str, default = "SIFT", help = "Keypoint detector to use.Options['RootSIFT', 'SIFT', 'SURF']")#關鍵點區域提取局部不變描述符 ap.add_argument("-m", "--matcher", type = str, default ="BruteForce", help = "Feature matcher to use. Options ['BruteForce', 'BruteForce-SL2', 'BruteForce-L1','FlannBased']")#尋找沒對描述符最小距離方法 #ap.add_argument("-v", "--visualize", type = str, default = "Yes", help="Whether the visualiz image should be shown. Options ['Yes', 'No', 'Each']") ap.add_argument("-v", "--visualize", type = str, default = "Yes", help="Whether the visualiztion image should be shown. Options ['Yes', 'No', 'Each']")#繪制對關鍵點和描述符之間的匹配 args = vars(ap.parse_args()) if args["detector"] == "DOG": detector = FeatureDetector_create("SIFT") elif args["detector"] == "FASTHESSIAN": detector = FeatureDetector_create("SURF") else: detector = FeatureDetector_create(args["detector"]) extractor = DescriptorExtractor_create(args["extractor"])#提取關鍵點區域的特征描述符 matcher = DescriptorMatcher_create(args["matcher"]) imageA = cv2.imread(args["first"]) imageB = cv2.imread(args["second"]) grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY) grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY) #提取關鍵點 kpsA = detector.detect(grayA) kpsB = detector.detect(grayB) #提取關鍵的局部特征描述符 (kpsA, featuresA) = extractor.compute(grayA, kpsA) (kpsB, featuresB) = extractor.compute(grayB, kpsB) rawMatches = matcher.knnMatch(featuresA, featuresB, 2) matches = [] if rawMatches is not None: for m in rawMatches: #篩選符合條件的關鍵點 if len(m) == 2 and m[0].distance < m[1].distance*0.8: matches.append((m[0].trainIdx, m[0].queryIdx)) print("# of keypoints from first image:{}".format(len(kpsA)))
11、二進制描述符
11.1、ORB
from __future__ import print_function import argparse import cv2 import imutils ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image") args = vars(ap.parse_args()) image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("ORB") extractor = cv2.DescriptorExtractor_create("ORB") kps = detector.detect(gray) (kps, descs) = extractor.compute(gray, kps) else: detector = cv2.ORB_create() (kps, descs) = detector.detectAndCompute(gray, None) # show the shape of the keypoints and local invariant descriptors array print("[INFO] # of keypoints detected: {}".format(len(kps))) print("[INFO] feature vector shape: {}".format(descs.shape))
11.2、BRISK
from __future__ import print_function import argparse import cv2 import imutils ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image") args = vars(ap.parse_args()) image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("BRISK") extractor = cv2.DescriptorExtractor_create("BRISK") kps = detector.detect(gray) (kps, descs) = extractor.compute(gray, kps) else: detector = cv2.BRISK_create() (kps, descs) = detector.detectAndCompute(gray, None) print("[INFO] # of keypoints detected: {}".format(len(kps))) print("[INFO] feature vector shape: {}".format(descs.shape))
11.3、BRIEF
from __future__ import print_function import argparse import cv2 import imutils ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image") args = vars(ap.parse_args()) image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("FAST") extractor = cv2.DescriptorExtractor_create("BRIEF") else: detector = cv2.FastFeatureDetector_create() extractor = cv2.xfeatures2d.BriefDescriptorExtractor_create() kps = detector.detect(gray) (kps, descs) = extractor.compute(gray, kps) print("[INFO] # of keypoints detected: {}".format(len(kps))) print("[INFO] feature vector shape: {}".format(descs.shape))
from __future__ import print_function import argparse import cv2 import imutils # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="Path to the image") args = vars(ap.parse_args()) image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if imutils.is_cv2(): detector = cv2.FeatureDetector_create("FAST") extractor = cv2.DescriptorExtractor_create("FREAK") kps = detector.detect(gray) (kps, descs) = extractor.compute(gray, kps) else: detector = cv2.FastFeatureDetector_create() extractor = cv2.xfeatures2d.FREAK_create() kps = detector.detect(gray, None) (kps, descs) = extractor.compute(gray, kps) print("[INFO] # of keypoints detected: {}".format(len(kps))) print("[INFO] feature vector shape: {}".format(descs.shape))