0

元の画像のテンプレートを識別し、それらのテンプレートに一致した領域をコピーすることにより、opencv を使用して画像を複数のサブ画像に分割しようとしています。私はopencvの初心者です!以下を使用してサブイメージを特定しました。

result = cv2.matchTemplate(img, template, cv2.TM_CCORR_NORMED)

いくつかのクリーンアップの後、四角形を表示するために反復するポイントと呼ばれるタプルのリストを取得します。tw と th は、それぞれテンプレートの幅と高さです。

for pt in points:
    re = cv2.rectangle(img, pt, (pt[0] + tw, pt[1] + th), 0, 2)
    print('%s, %s' % (str(pt[0]), str(pt[1])))
    count+=1

私が達成したいのは、八角形 ( https://dl.dropbox.com/u/239592/region01.png ) を別々のファイルに保存することです。

これどうやってするの?輪郭について読んだことがありますが、使い方がわかりません。理想的には、八角形の輪郭を描きたいと思います。

助けてくれてどうもありがとう!

4

2 に答える 2

4

テンプレートマッチングが機能している場合は、それに固執します。たとえば、次のテンプレートを検討しました。

ここに画像の説明を入力してください

次に、入力を前処理してバイナリ入力にし、小さなコンポーネントを破棄します。このステップの後、テンプレートマッチングが実行されます。次に、近いものを破棄することによって一致をフィルタリングする問題です(私はそのためにダミーの方法を使用したので、一致が多すぎる場合は時間がかかることがあります)。どのポイントが遠く離れているかを決定した後(したがって、異なる六角形を識別した後)、次の方法でそれらを微調整できます。

  • y座標で並べ替えます。
  • 隣接する2つのアイテムが近すぎるy座標で始まる場合は、両方を同じy座標に設定します。

これで、トリミングがラスター順に行われるように、このポイントリストを適切な順序で並べ替えることができます。トリミング部分は、によって提供されるスライスを使用して簡単に実現できnumpyます。

import sys
import cv2
import numpy

outbasename = 'hexagon_%02d.png'

img = cv2.imread(sys.argv[1])
template = cv2.cvtColor(cv2.imread(sys.argv[2]), cv2.COLOR_BGR2GRAY)
theight, twidth = template.shape[:2]

# Binarize the input based on the saturation and value.
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
saturation = hsv[:,:,1]
value = hsv[:,:,2]
value[saturation > 35] = 255
value = cv2.threshold(value, 0, 255, cv2.THRESH_OTSU)[1]
# Pad the image.
value = cv2.copyMakeBorder(255 - value, 3, 3, 3, 3, cv2.BORDER_CONSTANT, value=0)

# Discard small components.
img_clean = numpy.zeros(value.shape, dtype=numpy.uint8)
contours, _ = cv2.findContours(value, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for i, c in enumerate(contours):
    area = cv2.contourArea(c)
    if area > 500:
        cv2.drawContours(img_clean, contours, i, 255, 2)


def closest_pt(a, pt):
    if not len(a):
        return (float('inf'), float('inf'))
    d = a - pt
    return a[numpy.argmin((d * d).sum(1))]

match = cv2.matchTemplate(img_clean, template, cv2.TM_CCORR_NORMED)

# Filter matches.
threshold = 0.8
dist_threshold = twidth / 1.5
loc = numpy.where(match > threshold)
ptlist = numpy.zeros((len(loc[0]), 2), dtype=int)
count = 0
print "%d matches" % len(loc[0])
for pt in zip(*loc[::-1]):
    cpt = closest_pt(ptlist[:count], pt)
    dist = ((cpt[0] - pt[0]) ** 2 + (cpt[1] - pt[1]) ** 2) ** 0.5
    if dist > dist_threshold:
        ptlist[count] = pt
        count += 1

# Adjust points (could do for the x coords too).
ptlist = ptlist[:count]
view = ptlist.ravel().view([('x', int), ('y', int)])
view.sort(order=['y', 'x'])
for i in xrange(1, ptlist.shape[0]):
    prev, curr = ptlist[i - 1], ptlist[i]
    if abs(curr[1] - prev[1]) < 5:
        y = min(curr[1], prev[1])
        curr[1], prev[1] = y, y

# Crop in raster order.
view.sort(order=['y', 'x'])
for i, pt in enumerate(ptlist, start=1):
    cv2.imwrite(outbasename % i,
            img[pt[1]-2:pt[1]+theight-2, pt[0]-2:pt[0]+twidth-2])
    print 'Wrote %s' % (outbasename % i)

img_clean六角形の輪郭のみが必要な場合は、代わりにトリミングしますimg(ただし、六角形をラスター順に並べ替えても意味がありません)。

上記のコードを変更せずに2つの例で切り取られるさまざまな領域の表現を次に示します。

ここに画像の説明を入力してください ここに画像の説明を入力してください

于 2013-02-16T15:50:29.427 に答える
1

申し訳ありませんが、matchTemplate と Contours をどのように関連付けるのですかという質問からはわかりませんでした。

とにかく、以下は輪郭を使用した小さなテクニックです。あなたの他の画像もあなたが提供したものと似ていることを前提としています。他の画像でうまくいくかどうかはわかりません。しかし、それはスタートアップを得るのに役立つと思います。これを自分で試して、必要な調整と変更を加えてください。

私がしたこと :

1 - 八角形のエッジが必要でした。そのため、Otsu を使用してしきい値処理された画像を作成し、膨張と浸食を適用します (または、すべての画像に適切に機能する任意の方法を使用しますbeware of the edges in left edge of image)。

2 - 次に、輪郭を見つけました (輪郭の詳細: http://goo.gl/r0ID0

3 - 各等高線について、その凸包を見つけ、その面積 (A) と周囲 (P) を見つけます

4 -完全な八角形の場合P*P/A = 13.25 approximately. こちらで使用してカットして保存しておりました。

5 - トリミングすると、八角形の一部のエッジも削除されることがわかります。必要に応じて、トリミング寸法を調整します。

コード :

import cv2
import numpy as np

img = cv2.imread('region01.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
thresh = cv2.dilate(thresh,None,iterations = 2)
thresh = cv2.erode(thresh,None)

contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
number = 0

for cnt in contours:
    hull = cv2.convexHull(cnt)
    area = cv2.contourArea(hull)
    P = cv2.arcLength(hull,True)

    if ((area != 0) and (13<= P**2/area <= 14)):
        #cv2.drawContours(img,[hull],0,255,3)
        x,y,w,h = cv2.boundingRect(hull)
        number = number + 1
        roi = img[y:y+h,x:x+w]
        cv2.imshow(str(number),roi)
        cv2.imwrite("1"+str(number)+".jpg",roi)

cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

これらの 6 つの八角形は、個別のファイルとして保存されます。

それが役に立てば幸い !!!

于 2013-02-16T11:46:00.193 に答える