読者です 読者をやめる 読者になる 読者になる

OpenCV-Python を使って囲碁の勝敗判定させてみよう (1)

f:id:asdm:20151215220049j:plain

この記事は CAMPHOR- Advent Calendar 2015 の16日目の記事です.

こんにちは.@asadamanです.

最近,OpenCV-Pythonで遊んでいるので,それについて書いてみようと思います.
OpenCV-Pythonのチュートリアルをやっているだけでも十分楽しいのですが,それを使ってこんなのができたらいいなっていうのがあるとワクワクしてきますよね!

ということで,「囲碁の勝敗判定をさせてみる」という目標を立ててみました.

囲碁は陣地取りのゲームで,勝敗はどちらの方が多く陣地を取れたかで決まります.陣地とは,自分の石(黒石か白石)で囲まれた碁盤の交点の数です.
(分かりやすい説明は囲碁の基本:囲碁の勝負の付け方を参考にしていただればと思います.)

さて,処理の流れとしてはざっくり分けて,
画像から碁盤の領域を切り出す (→ ダメ詰め,死石などの処理) → 交点を検出し,白黒の陣地を計算する
という感じになると思います.

本当は全部やって記事にしたかったのですが,とりあえず出来たところまで書いてみようと思います…

画像から碁盤の領域を切り出す

import cv2
import numpy as np

# 画像を読み込み
img = cv2.imread('sample.jpg')

# グレースケール
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# ガウスフィルタ
smooth = cv2.GaussianBlur(gray,(11,11),0)

# Canny Edge Detectionで輪郭抽出
edges = cv2.Canny(smooth, 100, 200)

image, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 面積が大きい順にソート
contours.sort(key=cv2.contourArea, reverse=True)

for cntr in contours:
  arclen = cv2.arcLength(cntr, True)
  approx = cv2.approxPolyDP(cntr, 0.01*arclen, True)

  # 緑色の線を引く
  cv2.drawContours(img, [approx], -1, (0,255,0), 2)

# 輪郭抽出して,元画像に重ねた結果を出力
cv2.imwrite('edgeDetection.png', img)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)

# Harris Corner Detectionでコーナーの検出
dst = cv2.cornerHarris(gray,5,3,0.04)

# 検出されたコーナーに赤色で印をつける
img[dst>0.03*dst.max()]=[0,0,255]
# コーナー検出された結果を出力
cv2.imwrite('cornerDetection.png', img)

輪郭抽出結果 f:id:asdm:20151215231629p:plain

コーナー検出結果 f:id:asdm:20151215231639p:plain

ここから碁盤の四隅を正しく検出して画像を抜き出したいわけですが,どうしようか…という状況です.
直線出してその交点を取るとかもよいらしいが…

画像サイズどうなってんだよ!?とか,ノイズ除去どうなってんだよ!?とか,パラメータどうなってんだよ!?とか,終局後の整地もっと綺麗にやれよ!?とかいろんな鉞が飛んできそうで戦々恐々としてるのですが,温かい目で見ていただけると幸いです.

リベンジ編書きたいな…

参考リンク

python/OpenCVでレシートみたいな四角いものを見つけてトリミングする - BlankTar

OpenCV-Python Tutorials — OpenCV-Python Tutorials 1 documentation

明日の CAMPHOR- Advent Calendar 2015 の記事は,@shotarokの担当です!お楽しみに!