Python コンピューター ビジョン (2) - ローカル画像記述子

2.1 ハリスコーナー検出器

Harris コーナー検出アルゴリズムの主な考え方は、ピクセルの周囲に複数の方向にエッジがある場合、その点はコーナー ポイントと呼ばれる注目点とみなされます。

コーナー機能

ローカルウィンドウが全方向に移動して明らかな変化が生じる点、画像の局所的な曲率が急激に変化する点、等高線の交点など、同じシーンであれば、見る角度が変わっても、通常は次のような特徴があります。安定した特性の点、この点の近傍にあるピクセル点 勾配の方向と勾配の大きさの両方に大きな変化があります。

コーナー検出の基本的な考え方

小ウィンドウが任意の方向に移動すると、コーナー近傍画像のグレー値が大きく変化します。
ここにスライスの説明を挿入

ハリスコーナー検出器の数学的考察

関数を使用して、コーナーポイントかどうかを判断できます。


ここに画像の説明を挿入

w(x, y) は長方形のウィンドウを表し、I(x, y) はポイントのグレー値を表します。u と v はウィンドウのオフセットを表します。いずれかの方向にグレーの大きな変化がある場合は、ポイントを判断します。コーナーポイントです。ガウス重み行列を使用すると、大きな変化のある点を強調表示し、より大きな重みを与えることができます。
1 次のテイラー公式を使用して、
ここに画像の説明を挿入
行列で表される上記の関数を簡略化できます。
ここに画像の説明を挿入

M=\begin{pmatrix} I_{x}^{2} &I_{x} I_{y}\\ I_{y} I_{x} & I_{y}^{2} \end{pmatrix}固有値を解く順序\左 |  \lambda EM \right |=0、固有値\ラムダ_{1}\ラムダ_{2}

特徴:

Harris コーナー検出演算子は回転不変です

Harris コーナー検出オペレータは、グレー スケール変換およびグレー スケール変更の影響を受けません。

Harris コーナー検出演算子にはスケール不変性がありません

コーナー検出コードを実装する 

アルゴリズムは python-opencv を使用して Harris コーナー検出を実現します

import numpy as np
import cv2 as cv

# 读取图像
im_name = 'jmu/3.jpg'
im = cv.imread(im_name)
# 图像灰度化,并进行浮点数运算
im_gray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
im_gray = np.float32(im_gray)
# Harris算法检测角点
'''
cv2.cornerHarris(src, blockSize, ksize,k)
函数参数含义:
src:输入图像,通常为灰度图像
blockSize:角点检测算法使用的邻域窗口大小
ksize:Sobel 算子的卷积核大小,用于计算图像的梯度信息,一般为奇数
k:角点响应函数中的自由参数,一般取值为[0,0.04,0.06]
'''
# 角点响应图像
dst = cv.cornerHarris(im_gray, 5, 5, 0.06)
# 标准化响应图像
dst_norm = np.empty_like(dst)
cv.normalize(dst, dst_norm, alpha=0, beta=255, norm_type=cv.NORM_MINMAX)

# 将响应图像转换为8位无符号整数类型
dst_norm = np.uint8(dst_norm)

# 显示响应图像
cv.imshow('Corner Response Image', dst_norm)
cv.waitKey(0)

# 将原图像角点响应值大于阈值t的角点标记为红色
im[dst > 0.005* dst.max()] = [0, 0, 255]

# 防止图片输出时过大
cv.namedWindow('t=0.005', cv.WINDOW_KEEPRATIO)
cv.imshow('t=0.005', im)
cv.waitKey(0)
cv.destroyAllWindows()

 結果:

コーナーレスポンシブ画像

  

t=0.001
t=0.005
t=0.05

結果分析:
0.06 in dst = cv.cornerHarris(im_gray, 5, 5, 0.06) は、コーナー応答関数の自由パラメーター k を表します。k の値を変更すると、検出されるコーナーの数が変更される可能性があります。k の値を大きくすると、コーナー応答値 R が減少し、コーナー検出の感度が低下し、検出されるコーナーの数が減ります。k の値を小さくすると、コーナー応答値 R が増加し、コーナー検出の数が増加します。検出されるコーナーの数を増やします。そして、閾値 t が増加するにつれて、マークされたコーナーの数は減少します。

2.2 SIFT (スケール不変特徴変換)

SIFT 機能には、スケール、回転、明るさに対して不変である特徴点検出器と記述子が含まれます。

興味がある点

SIFT 機能は、ガウス関数の差を使用して関心のある点を特定します。

D(x,\sigma )=\left [ G_{k\sigma }(x)- G_{\sigma }\right(x) ]*I(x)=\left [ G_{k\sigma }- G_{ \sigma }\right ]*I(x)=I_{k\sigma }-I_{\sigma }

その中には、ぼやけたグレースケール画像を使用するG_{\シグマ }2 次元ガウス カーネルがあり、k は差のスケールを決定する定数です。私_{\シグマ }G_{\シグマ }

特徴点は、D(x,\sigma ) 画像の位置とスケールの変化の下での最大点と最小点です。これらの候補位置はフィルタリングされ、不安定な点が削除されます。

ディスクリプタ

関心点位置記述子は、関心点の位置およびスケール情報を与えます。回転の不変性を実現するために、SIFT 記述子は、各点の周囲の画像勾配の方向と大きさに基づいて基準方向を導入します。SIFT 記述子は、主方向を使用して参照方向を記述します。主な方向は、サイズによって重み付けされた方向ヒストグラムを使用して測定されます。画像の明るさに強くするために、SIFT 記述子は画像の勾配を使用します。SIFT 記述子は、各ピクセル付近のサブ領域のグリッドを選択し、各サブ領域の画像勾配方向のヒストグラムを計算します。各サブ領域のヒストグラムが連結されて、記述サブベクトルが形成されます。SIFT 記述子の標準設定では 4 × 4 のサブ領域が使用され、各サブ領域は 8 つの小さな領域間の方向ヒストグラムを使用します。これにより、小領域間に合計 128 個のヒストグラムが生成されます (4 × 4 × 8=128)。 。


SIFT アルゴリズムの特徴マッチングの手順

特徴点を検出し、記述子を計算する

sift = cv.SIFT_create()
kp1、des1 = sift.detectAndCompute(img1、なし)
kp2、des2 = sift.detectAndCompute(img2、なし)

一致する記述子

bf = cv.BFMatcher(cv.NORM_L2)
一致 = bf.knnMatch(des1, des2, k=2)

機能マッチングコードを実装する

アルゴリズムは python-opencv を使用して SIFT 特徴マッチングを実現します

import cv2 as cv

# 读取图像
img1 = cv.imread(r'jmu/3.jpg')
img2 = cv.imread(r'jmu/4.jpg')

# 创建SIFT特征点检测
sift = cv.SIFT_create()

# 检测兴趣点并计算描述子
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)

# 使用OpenCV中的BFMatcher算法进行特征匹配,并返回最近邻和次近邻匹配的结果
bf = cv.BFMatcher(cv.NORM_L2)
matches = bf.knnMatch(des1, des2, k=2)

# 储存特征匹配最好的优质匹配点对
'''基于距离阈值选择优质匹配点对,如果最近邻m的距离小于0.7倍的次近邻n的距离,
则认为这个匹配点对是优质的,将它存储在goodMatchs列表中。'''
goodMatchs = []
for m, n in matches:
    if m.distance < 0.65 * n.distance:
        goodMatchs.append(m)

# 可视化特征匹配结果,并保存
pic3 = cv.drawMatches(img1=img1, keypoints1=kp1, img2=img2, keypoints2=kp2, matches1to2=goodMatchs, outImg=None)
cv.imwrite(r'/Users/xionglulu/Downloads/project1/m1.jpg', pic3)

結果: 

特徴一致イメージ

結果分析: 特徴マッチングの結果によると、Harris アルゴリズムと比較して、SIFT アルゴリズムは画像特徴点の抽出においてより包括的であることがわかりますが、マッチングにはエラーもあり、過度に一致する点のマッチング効果はありません。類似性が高いことは良くありません。距離の閾値を変更することで一致点ペアの数を変えることができ、閾値が小さいほど一致数が少なくなり精度が高くなります。

2.3 ジオタグ付き画像の照合

3 つの異なる位置を含む一連の画像を入力し、SIFT 特徴照合アルゴリズムを使用して同じ位置の画像を照合して分類します。

コード

まずサムネイルを保存します

import os
import cv2 as cv
from pylab import *

maxsize = (100, 100)  # 定义缩略图的大小
path = r'/Users/xionglulu/Downloads/project1/jmu'

# 读取整个文件夹的图片
def read_path(pathname):
    imgname_list = os.listdir(pathname)
    img_list = []
    i = 0
    # 图片列表
    for imgname in imgname_list:
        if imgname.endswith('.jpg'):
            img = cv.imread(pathname + '/' + imgname)
            img_n = cv.resize(img, maxsize, cv.INTER_AREA)
            filename = path + str(i) + '.png'
            cv.imwrite(filename, img_n) 
            i = i + 1
    return img_list

list = read_path(r'/Users/xionglulu/Downloads/project1/jmu')
print(list)

次にジオタグ付き画像と一致します

import os
import cv2 as cv
from pylab import *
import pydotplus as pydot

# 读取整个文件夹的图片
def read_path(pathname):
    imgname_list = os.listdir(pathname)
    img_list = []
    # 图片列表
    for imgname in imgname_list:
        if imgname.endswith('.jpg'):
            img = cv.imread(pathname + '/' + imgname)
            img_list.append(img)
    return img_list


img_list = read_path(r'/Users/xionglulu/Downloads/project1/jmu')
nbr_images = len(img_list)
match_scores = zeros((nbr_images, nbr_images))

for i in range(nbr_images):
    for j in range(i, nbr_images): 
        print('comparing ', i, j)
        sift = cv.xfeatures2d.SIFT_create()
        kp1, des1 = sift.detectAndCompute(img_list[i], None)
        kp2, des2 = sift.detectAndCompute(img_list[j], None)
        # BFMatch匹配
        bf = cv.BFMatcher(cv.NORM_L2)
        matches = bf.knnMatch(des1, des2, k=2)
        # 储存差距小的优秀匹配点
        goodMatches = []
        for m, n in matches:
            if m.distance < 0.5 * n.distance:
                goodMatches.append(m)
        # 计算优秀匹配点的和
        nbr_matches = len(goodMatches)
        # 向match_scores赋值
        print('number of matches = ', nbr_matches)
        match_scores[i, j] = nbr_matches

# 复制
for i in range(nbr_images):
    for j in range(i + 1, nbr_images):  # 不用复制自我匹配的对角线
        match_scores[j, i] = match_scores[i, j]
# 可视化
threshold = 2  #  至少2个以上匹配点就可以算是联系
g = pydot.Dot(graph_type='graph')  # 不需要有向图
maxsize = (100, 100)  # 定义缩略图的大小
path = r'/Users/xionglulu/Downloads/project1/jmu'
#两两配对
for i in range(nbr_images):
    for j in range(i + 1, nbr_images):
        if match_scores[i, j] > threshold:
            filename = path + str(i) + '.png'
            g.add_node(pydot.Node(str(i), fontcolor='transparent', shape='rectangle', image=filename))
            filename = path + str(j) + '.png'
            g.add_node(pydot.Node(str(j), fontcolor='transparent', shape='rectangle', image=filename))
            g.add_edge(pydot.Edge(str(i), str(j)))
#绘制S地理标记SIFT匹配图
g.write_jpg('jmuv.jpg')

 結果:

ジオタグ付き画像と一致する

 結果分析: 結果マップから、マッチングにいくつかのエラーがあり、時計塔と孫文記念館が誤って一致し、Lu Building も孫文記念館と誤って一致していることがわかります。ホール これは、3 つの建物が非常に似ているからかもしれません。

おすすめ

転載: blog.csdn.net/summer_524/article/details/130114804