PythonでWebカメラの映像から円(硬貨)をリアルタイム検出する!
- 画像から円形の物体を検出したい
- opencvの
HoughCircles
を使うと良い。ただし、公式ドキュメントが「半径が安定しない」と注意事項を挙げている。半径の測定には向かない。
解説
HoughCircles
については色んなサイトで解説されている。
サンプルプログラム
Webカメラで複数の硬貨を撮影し、円検出する。撮像→検出のサイクルを繰り返すことでリアルタイム処理っぽくなっている。
Webカメラ
Baffalo製のBSW32KM01Hという10年も前のUSBカメラを使用した。最近のUSBカメラならもっときれいに映るかも。
結果
すべての硬貨を検出(緑色枠で囲うことが)できた。硬貨の置き方を変えても検出が追従できているし、それに伴い照明の当たり方が変わっても問題がない。ただし、HoughCircles
のパラメーターの合わせ込みが難しいのが難点。また、撮影する距離や角度が変わると劇的に検出しなくなるため、安定した撮像システムにしか馴染まない手法だと思う。
ソースコード
import sys #from time import sleep import cv2 #Webカメラのインスタンス作成 #引数はカメラ番号。0番はラップトップ内蔵カメラ。 cap = cv2.VideoCapture(1) #Webカメラのインスタンス作成に失敗したらプログラム終了 if not cap.isOpened(): print("Camera Not Found") sys.exit() #キャプチャと円検出を繰り返す while True: # sleep(1) #キャプチャ取得 _, frame = cap.read() img = frame.copy() #前処理 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.medianBlur(gray ,7) gray = cv2.equalizeHist(gray) #円検出 circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp=4, minDist=50, param1=400, param2=100, minRadius=30, maxRadius=50) #円の検出に成功したらオリジナルのimgに円を描画 if circles is not None: for i in circles[0].astype('uint16'): cv2.circle(img,(i[0],i[1]),i[2],(0,255,0),2) cv2.imshow('Detect', img) k = cv2.waitKey(5) & 0xFF if k == 27: break cv2.destroyAllWindows() cap.release()