四角形と三角形の中から三角形だけ抽出する(特定形状の抽出)
四角形と三角形が混在する画像から、三角形のみを抽出します。
opencvのcv2.findContours関数で領域を抽出、cv2.approxPolyDP関数で輪郭の近似図形を求め、近似図形が三角形(頂点の数が3)の場合に輪郭を縁どります。
関連記事
環境
準備
以下のコードでランダムな向きと大きさの三角形と四角形の混在した画像(figures.png)を生成します。
import cv2 import random import math import numpy as np def tri(x, y): radius = random.uniform(20,40) rotate = random.uniform(0,120) pts = np.array(((x+int(radius*math.cos(rotate/360*2*math.pi)), y+int(radius*math.sin(rotate/360*2*math.pi))), (x+int(radius*math.cos((rotate+120)/360*2*math.pi)), y+int(radius*math.sin((rotate+120)/360*2*math.pi))), (x+int(radius*math.cos((rotate+240)/360*2*math.pi)), y+int(radius*math.sin((rotate+240)/360*2*math.pi))))) cv2.fillPoly(img, [pts], (0, 150, 0), cv2.LINE_AA) def square(x, y): radius = random.uniform(20,40) rotate = random.uniform(0,90) pts = np.array(((x+int(radius*math.cos(rotate/360*2*math.pi)), y+int(radius*math.sin(rotate/360*2*math.pi))), (x+int(radius*math.cos((rotate+90)/360*2*math.pi)), y+int(radius*math.sin((rotate+90)/360*2*math.pi))), (x+int(radius*math.cos((rotate+180)/360*2*math.pi)), y+int(radius*math.sin((rotate+180)/360*2*math.pi))), (x+int(radius*math.cos((rotate+270)/360*2*math.pi)), y+int(radius*math.sin((rotate+270)/360*2*math.pi))))) cv2.fillPoly(img, [pts], (0, 150, 0), cv2.LINE_AA) img = np.zeros((400, 400, 3), np.uint8) img[:,:,:] = 245 for y in range(50,400,100): for x in range(50,400,100): switch = random.choice([0, 1]) if switch == 0: tri(x, y) else: square(x, y) cv2.imwrite('figures.png', img)
三角形と四角形が8個ずつ描画されました。
figures.png
コード
import cv2 import numpy as np img = cv2.imread('figures.png') # 画像読み出し img_gray = cv2.imread('figures.png', cv2.IMREAD_GRAYSCALE) # 画像をグレイスケールで読み出し _, threshold = cv2.threshold(img_gray, 125, 255, cv2.THRESH_BINARY) # 画像を二値化 contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 領域検出 triangles = 0 # 三角形カウント用 #抽出した領域を1つずつ取り出し輪郭を近似する。三角形の場合、輪郭を赤くする for cnt in contours: epsilon = 0.1*cv2.arcLength(cnt, True) approx = cv2.approxPolyDP(cnt, epsilon, True) if len(approx) == 3: cv2.drawContours(img, [approx], 0, (0, 0, 255), 2) triangles += 1 print(triangles) # 三角形の数を表示 cv2.imwrite('triangles.png',img) # 三角形の輪郭を加えた画像を保存
実行結果
抽出された三角形の個数が表示されます
8
三角形が赤く縁どられた画像が保存されます。
triangles.png
以下のサイトを参考にさせていただきました
OpenCV-Python Tutorials >> 輪郭: 初めの一歩
S-Analysis >> OpenCV-Pythonでの図形検出、図形数える