Pythonでいろいろやってみる

Pythonを使った画像処理や機械学習などの簡単なプログラムを載せています。

四角形と三角形の中から三角形だけ抽出する(特定形状の抽出)

四角形と三角形が混在する画像から、三角形のみを抽出します。
opencvのcv2.findContours関数で領域を抽出、cv2.approxPolyDP関数で輪郭の近似図形を求め、近似図形が三角形(頂点の数が3)の場合に輪郭を縁どります。

関連記事

円の数を数える

環境
  • windows10 home
  • Anaconda 3/ jupyter notebook 5.6.0
  • Python 3.7.0
  • OpenCV 4.0.0
準備

以下のコードでランダムな向きと大きさの三角形と四角形の混在した画像(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個ずつ描画されました。

f:id:T_A_T:20201117211424p:plain
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

三角形が赤く縁どられた画像が保存されます。
f:id:T_A_T:20201117211555p:plain
triangles.png

以下のサイトを参考にさせていただきました

OpenCV-Python Tutorials >> 輪郭: 初めの一歩
S-Analysis >> OpenCV-Pythonでの図形検出、図形数える

ブログランキングに参加しています

にほんブログ村 IT技術ブログへ
にほんブログ村