私はジグソー パズルを持っていて、そのパズルの「通常」、「エッジ」、および「コーナー」ピースを自動的に区別したいと考えています (これらの単語の定義は、ジグソー パズルをやったことがある人には明らかだと思います)。
作業を簡単にするために、9 つのパーツの選択から始めました。そのうち 4 つが通常、4 つがエッジ、1 つがコーナーです。元の画像は次のようになります。
私の最初のアイデアは、各ピースの 4 つの「メジャー コーナー」を検出し、次のように進めることでした。
- 隣接する 2 つの「主要な角」の間の輪郭が直線である場合、それはエッジです。
- 隣接する 3 つの「主要な角」の間の 2 つの輪郭が直線である場合、それは角です。
- 隣接する 2 つの「主要な角」の間に直線がない場合、それは正常な部分です。
ただし、各ピースの 4 つの「メジャー コーナー」を抽出するのに問題があります (これにはハリス コーナーを使用しようとしていました)。
いくつかの前処理を含む私のコードは、私が得たハリスコーナーを含むいくつかの結果と一緒に以下に添付されています. 任意の入力をいただければ幸いです。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image.png')
gray= cv2.imread('image.png',0)
# Threshold to detect rectangles independent from background illumination
ret2,th3 = cv2.threshold(gray,220,255,cv2.THRESH_BINARY_INV)
# Detect contours
_, contours, hierarchy = cv2.findContours( th3.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# Draw contours
h, w = th3.shape[:2]
vis = np.zeros((h, w, 3), np.uint8)
cv2.drawContours( vis, contours, -1, (128,255,255), -1)
# Print Features of each contour and select some contours
contours2=[]
for i, cnt in enumerate(contours):
cnt=contours[i]
M = cv2.moments(cnt)
if M['m00'] != 0:
# for definition of features cf http://docs.opencv.org/3.1.0/d1/d32/tutorial_py_contour_properties.html#gsc.tab=0
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
area = cv2.contourArea(cnt)
x,y,w,h = cv2.boundingRect(cnt)
aspect_ratio = float(w)/h
rect_area = w*h
extent = float(area)/rect_area
print i, cx, cy, area, aspect_ratio, rect_area, extent
if area < 80 and area > 10:
contours2.append(cnt)
# Detect Harris corners
dst = cv2.cornerHarris(th3,2,3,0.04)
#result is dilated for marking the corners, not important
dst = cv2.dilate(dst,None, iterations=5)
# Threshold for an optimal value, it may vary depending on the image.
harris=img.copy()
print harris.shape
harris[dst>0.4*dst.max()]=[255,0,0]
titles = ['Original Image', 'Thresholding', 'Contours', "Harris corners"]
images = [img, th3, vis, harris]
for i in xrange(4):
plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()