#前回まで
グレースケール化,平滑化,閾値処理を行い,画像認識の準備が整いましたが,ここで問題が発生.僕の構想では牌を個別に認識するつもりでした.ご覧の通り,背景と牌の境界は明確になりましたが,牌同士の境界は消失しています.パラメータを調整して牌同士の境界を取り出そうとすると,牌そのものの画像情報が損なわれてしまう等の弊害が生じます.何より,最終的には様々な環境で撮られた写真を入力とすることを想定しており,細かいパラメータを設定してしまうとそれらに対応できなくなることが考えられます.理想は,その都度パラメータの最適化が行われることですが,現状僕には皆目その見当がつきません.
#そのまま分割する
cv2.findContour
で輪郭を抽出することができます.
import cv2
import matplotlib.pyplot as plt
img_path = '/Users/mac/Desktop/sample/agari2.png'
img = cv2.imread(img_path)
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
filtered_img = cv2.GaussianBlur(gray_img, (5, 5), 0)
ret,thresh_img = cv2.threshold(filtered_img,150,255,0)
image, contours, hierarchy = cv2.findContours(thresh_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
plt.imshow(image)
areas = []
for cnt in contours:
area = cv2.contourArea(cnt)
if area > 10000:
epsilon = 0.020*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
areas.append(approx)
cv2.drawContours(img,areas,-1,(0,255,0),5)
plt.imshow(img)
image, contours, hierarchy = cv2.findContours(thresh_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
で輪郭を抽出します.返り値のcontours
は輪郭のリスト,hierarchy
は階層構造のリストです.今回は画像認識の目処を立てるために関数の挙動をとりあえず見てみる,という体なので,後半の角形の近似は理解が及んでいません.必要になったら勉強します.
歪んでいます.近似の際パラメータを調整しなければならない時点でこの方法も諦めムードです.
cv2.boundingRect()
を使って輪郭の座標を取り出し,幅を14分割して牌をとりあえず取り出しました.ここから幾何変形cv2.warpPerspective()
で各牌を整形しました.それぞれ正面からの角度が異なるため,変形率がまちまちでとても綺麗とは言えません.パラメータを一般化してパターンに対応することが不可能かというと,現状僕には分かりませんが,解決するにあたって足踏みすることは必至です.
ということで,僕が使える唯一の武器はほぼ望み薄になってしまったので,他の方法を探してみます.万策尽きた結果,画像認識に戻ってくることも十分考えられますが,ここは一旦引き上げます.
#精確かつパターンに対応できる方法を探す
理解が出来てなんぼだと思っていたので,当初は扱える問題の難易度よりも僕が理解できるかどうかに重点を置いていましたが,それでは問題解決はおろか土俵にすら立たせてもらえないことが分かりました.甘ちゃんでした.考え方を改めて,知らないものでも使ってみることにしましょう.ネットは広大なので,同じような境遇の先人が教えてくれる筈です.
YOLOはリアルタイムオブジェクト検出アルゴリズムです。YOLO(You Look Only Onse)の名前通り、このアルゴリズムでは検出窓をスライドさせるような仕組みを用いず、画像を一度CNNに通すことで、オブジェクトを検出することができます.
参考:∞ReNom
https://www.renom.jp/ja/notebooks/tutorial/image_processing/yolo/notebook.html
比較的学習が用意で,何より精度,処理速度に優れているとのこと.これはいいかもしれません.次回はYOLOについてまとめることにします.