カメラ画像のオレンジ色の領域を抽出し、
その重心位置を計算するプログラムです。
その重心位置に目玉の瞳を描いています。
space key を押すと、モードが切り替わります。
mode 0: 抽出した領域の輪郭線を描画
mode 1: 目玉を表示
環境
python 3.6.5
opencv3.4.4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# -*- coding: utf-8 -*- import numpy as np import cv2 # パラメータ H_LOW = 0 # Hの下限 赤 H_HIGH = 30 # Hの上限 黄色 S_LOW = 100 # Sの下限 V_LOW = 65 # Vの下限 RADIUS_LOW = 10 # 外接円の半径の下限 N_MODE = 2 # 表示モード数 # 全体で使う変数 mode = 0 # カメラオブジェクト作成 cap = cv2.VideoCapture(1) # USBカメラなら1 # メインループ while True: ret, img = cap.read() # カメラ画像 img img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # HSVに変換 mask = cv2.inRange(img_hsv, (H_LOW, S_LOW, V_LOW), (H_HIGH, 255, 255)) # オレンジ領域の2値画像 conts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1] # 全輪郭線 # 文字の描画 cv2.putText(img, 'mode %d' % mode, (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 200), thickness=3) if mode == 0: # 輪郭線の描画 img = cv2.drawContours(img, conts, -1, (0, 255, 0), 1) if mode == 1: # 目玉の描画 for cnt in conts: # 各輪郭線についての処理 # cnt の外接円の中心 (rx, ry)と半径 radius (rx, ry), radius = cv2.minEnclosingCircle(cnt) if radius > RADIUS_LOW: # 外接円の半径がRADIUS_LOWよりも大きいとき # 重心 cx, cy を計算 M=cv2.moments(cnt) if M['m00'] > 0: cx=int(M['m10'] / M['m00']) cy=int(M['m01'] / M['m00']) # 目玉の描画 cv2.circle(img, (cx, cy), int(radius * 0.5), (30, 50, 100), -1) cv2.circle(img, (cx, cy), int(radius * 0.3), (0, 0, 0), -1) cv2.circle(img, (cx + 3, cy - 2), int(radius * 0.1), (255, 255, 255), -1) cv2.imshow('img', img) # 描画 INPUT = cv2.waitKey(10) & 0xFF # 押しているキーの取得 if INPUT == ord(' '): # モードの切り替え mode += 1 if mode >= N_MODE: mode = 0 if INPUT == ord('q'): # 終了 cv2.destroyAllWindows() break |