ここにあなたが始めるための何かがあります。新しい問題に飛び込むとき、どこかで使用できるという理由だけで、多くの複雑なステップを試すことにあまり価値がありません。ですから、私の焦点は比較的単純なものを使用することにあります。それは、より多様な状況では失敗しますが、うまくいけば、その価値を理解し、問題をある程度理解できるでしょう。
このアプローチは、完全にコーナー検出に基づいています。この検出の2つの典型的な方法は、Harris検出器、または1994年の論文「GoodFeatures to Track」で説明されているShiとTomasiによる方法です。OpenCV、新しいMatlabにすぐに実装できるという理由だけで、2番目の方法を使用します。そしておそらく他の多くの場所。これらのパッケージへの実装により、コーナーの品質とコーナー間の最小距離に関して、パラメーターの調整が容易になります。では、すべてのコーナーポイントを正しく検出できるとしたら、これらのポイントに基づいて、ある形状が別の形状にどれだけ近いかをどのように測定しますか?画像のサイズは任意なので、ポイント座標を[0、1]の範囲に正規化するのが私の考えです。これにより、元の説明に従って望ましいスケーリングの問題が解決されます。ここで、範囲[0、1]。ここでは、最も単純なことを説明します。1つのポイントを検討します。p
形から、形a
の最も近い点は何b
ですか?この点p
との任意の点との間で絶対的に異なる最小値を持つものであると想定しb
ます。すべての値を合計すると、形状間のスコアが得られます。スコアが低いほど、形状が似ています(このアプローチによる)。
これが私が描いたいくつかの形です:






検出されたコーナーは次のとおりです。






この最後の画像セットではっきりとわかるように、この方法では長方形/正方形と円柱を簡単に混同します。これを処理するには、アプローチを他の記述子と組み合わせる必要があります。最初に、考えられる単純なものは、形状の面積とその境界ボックスの面積の比率です(長方形の場合は1、円柱の場合はそれより低くなります)。
上記の方法で、第1と第2の形状、第1と第3の形状、...の間の測定値は、それぞれ0.02358485、0.41350339、0.30128458 0.4980852、0.18031262です。2番目のキューブは、最初のキューブのサイズを変更したバージョンであり、ご覧のとおり、このメトリックでは非常によく似ています。最後の形状は、最初の立方体のサイズを変更したバージョンですが、アスペクト比を維持せず、メトリックによってはるかに大きな差が得られます。
これを実行するコードを試してみたい場合は、次のようになります(Pythonでは、OpenCV、numpyに依存します)。
import sys
import cv2 as cv
import numpy
inp = []
for fname in sys.argv[1:]:
img_color = cv.imread(fname)
img = cv.cvtColor(img_color, cv.COLOR_RGB2GRAY)
inp.append((img_color, img))
ptsets = []
# Corner detection parameters.
params = (
200, # max number of corners
0.01, # minimum quality level of corners
10, # minimum distance between corners
)
# Params for visual circle markers.
circle_radii = 3
circle_color = (255, 0, 0)
for i, (img_color, img) in enumerate(inp):
height, width = img.shape
cornerMap = cv.goodFeaturesToTrack(img, *params)
corner = numpy.array([c[0] for c in cornerMap])
for c in corner:
cv.circle(img_color, tuple(c), circle_radii, circle_color, -1)
# Just to visually check for correct corners.
cv.imwrite('temp_%d.png' % i, img_color)
# Convert corner coordinates to [0, 1]
cornerUnity = (corner - corner.min()) / (corner.max() - corner.min())
# You might want to use other descriptors here. XXX
ptsets.append(cornerUnity)
def compare_ptsets(p):
res = numpy.zeros(len(p))
base = p[0]
for i in xrange(1, len(p)):
sum_min_diff = sum(numpy.abs(p[i] - value).min() for value in base)
res[i] = sum_min_diff
return res
res = compare_ptsets(ptsets)
print res