Skip to content

Instantly share code, notes, and snippets.

@TonyMooori
Last active June 24, 2024 08:21
Show Gist options
  • Save TonyMooori/4cc29c94f7bdbade6ff6102fef45232e to your computer and use it in GitHub Desktop.
Save TonyMooori/4cc29c94f7bdbade6ff6102fef45232e to your computer and use it in GitHub Desktop.
特定の色の座標を抽出するプログラム
import cv2
import numpy as np
# 0 <= h <= 179 (色相) OpenCVではmax=179なのでR:0(180),G:60,B:120となる
# 0 <= s <= 255 (彩度) 黒や白の値が抽出されるときはこの閾値を大きくする
# 0 <= v <= 255 (明度) これが大きいと明るく,小さいと暗い
# ここでは青色を抽出するので120±20を閾値とした
LOW_COLOR = np.array([100, 75, 75])
HIGH_COLOR = np.array([140, 255, 255])
# 抽出する青色の塊のしきい値
AREA_RATIO_THRESHOLD = 0.005
def find_specific_color(frame,AREA_RATIO_THRESHOLD,LOW_COLOR,HIGH_COLOR):
"""
指定した範囲の色の物体の座標を取得する関数
frame: 画像
AREA_RATIO_THRESHOLD: area_ratio未満の塊は無視する
LOW_COLOR: 抽出する色の下限(h,s,v)
HIGH_COLOR: 抽出する色の上限(h,s,v)
"""
# 高さ,幅,チャンネル数
h,w,c = frame.shape
# hsv色空間に変換
hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
# 色を抽出する
ex_img = cv2.inRange(hsv,LOW_COLOR,HIGH_COLOR)
# 輪郭抽出
_,contours,hierarchy = cv2.findContours(ex_img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
# 面積を計算
areas = np.array(list(map(cv2.contourArea,contours)))
if len(areas) == 0 or np.max(areas) / (h*w) < AREA_RATIO_THRESHOLD:
# 見つからなかったらNoneを返す
print("the area is too small")
return None
else:
# 面積が最大の塊の重心を計算し返す
max_idx = np.argmax(areas)
max_area = areas[max_idx]
result = cv2.moments(contours[max_idx])
x = int(result["m10"]/result["m00"])
y = int(result["m01"]/result["m00"])
return (x,y)
def test():
img = cv2.imread("sample.jpg")
# 位置を抽出
pos = find_specific_color(
img,
AREA_RATIO_THRESHOLD,
LOW_COLOR,
HIGH_COLOR
)
if pos is not None:
cv2.circle(img,pos,10,(0,0,255),-1)
cv2.imwrite("result.jpg",img)
def main():
# webカメラを扱うオブジェクトを取得
cap = cv2.VideoCapture(0)
while True:
ret,frame = cap.read()
if ret is False:
print("cannot read image")
continue
# 位置を抽出
pos = find_specific_color(
frame,
AREA_RATIO_THRESHOLD,
LOW_COLOR,
HIGH_COLOR
)
if pos is not None:
# 抽出した座標に丸を描く
cv2.circle(frame,pos,10,(0,0,255),-1)
# 画面に表示する
cv2.imshow('frame',frame)
# キーボード入力待ち
key = cv2.waitKey(1) & 0xFF
# qが押された場合は終了する
if key == ord('q'):
break
cv2.destroyAllWindows()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment