ピンク色のボール検出(OpenCV HSV)を使い追尾をプログラミングしてみました。Telloのカメラは解像度やホワイトバランスの関係で、暗めのピンク色のボールが赤っぽく映ることがあります。 この場合、純粋なピンクのHSV/BGR範囲ではうまく検出されない可能性があるので、実際に映っている色に合わせて検出範囲を調整する必要があ☛ました。手順は次に通りです。 ドローンが離陸します。 カメラ映像からピンク色のボールを認識。 見つけた瞬間に「ピンクのボール発見!追尾します」としゃべる。 (pyttsx3 の engine.say() + engine.runAndWait() を使って音声を再生) ボールの位置に合わせて、前後・左右に自動で追尾します。
コードの基本は☛顔認識での自動追尾を元にアレンジしています。
顔検出 | → OpenCVでピンク色の検出に変更 |
音声出力 | → pyttsx3 を使用して**「ピンクのボール発見!」**をしゃべらせる |
追尾制御 | → 既存のPID制御をそのまま流用(中心点と面積) |
音声出力
プログラム内での基本的な使い方
import pyttsx3 # 音声合成ライブラリを読み込み
engine = pyttsx3.init() # 音声エンジンを初期化
engine.say("こんにちは、Telloが追尾します") # 読み上げたいテキスト
engine.runAndWait() # 実際に再生
pyttsx3はPythonのテキスト音声変換ライブラリです。他のライブラリとは異なり、オフラインでも動作します。
import pyttsx3
#音声エンジン初期化
engine = pyttsx3.init()
ball_detected = False # ボールが見つかったかどうかのフラグ
顔検出 → ピンク色検出に置き換えた関数
def findBall(img):
global ball_detected
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# ピンク色のHSV範囲(明るさ・環境によって調整)
lower_pink = np.array([140, 100, 100])
upper_pink = np.array([170, 255, 255])
mask = cv2.inRange(hsv, lower_pink, upper_pink)
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
BallList_center = []
BallList_area = []
ball_center_y = 0
for cnt in contours:
area = cv2.contourArea(cnt)
if area > 500: # ノイズ除去
x, y, w, h = cv2.boundingRect(cnt)
cx = x + w // 2
cy = y + h // 2
BallList_center.append([cx, cy])
BallList_area.append(area)
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 255), 2)
cv2.circle(img, (cx, cy), 10, (0, 0, 255), -1)
cv2.putText(img, f"ballcenter: ({cx}, {cy})", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (204, 0, 255), 1)
if len(BallList_area) != 0:
i = BallList_area.index(max(BallList_area))
if not ball_detected:
engine.say("ピンクのボール発見!追尾します")
engine.runAndWait()
ball_detected = True
return img, [BallList_center[i], BallList_area[i]]
else:
ball_detected = False
return img, [[0, 0], 0]
少し改善が必要です。
問題点:engine.say(“ピンクのボール発見!追尾します”)の音声時のみ映像が、固まります。
この runAndWait()
は 同期的に動作するので、終わるまで次の処理に進まず、映像処理も止まることになります。
解決策:音声再生をスレッドで非同期に実行する
リアルタイム映像制御や物体追尾では、UI・映像処理の応答性を維持するために音声処理は必ず非同期化(スレッド化)するのが鉄則です。
完成コード
import threading
import socket
import time
import cv2
import numpy as np
import pyttsx3
# 音声再生(非同期)
def speak_async(text):
def _speak():
engine = pyttsx3.init()
engine.say(text)
engine.runAndWait()
threading.Thread(target=_speak, daemon=True).start()
# Telloネットワーク設定
host = '0.0.0.0'
port = 8889
locaddr = (host, port)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
tello_address = ('192.168.10.1', 8889)
sock.bind(locaddr)
# Telloからの応答を受信
def recv():
while True:
try:
data, _ = sock.recvfrom(1518)
print(data.decode(encoding="utf-8"))
except Exception:
print('\nExit . . . RECV\n')
break
recvThread = threading.Thread(target=recv)
recvThread.daemon = True
recvThread.start()
# 初期化コマンド
sock.sendto(b'command', tello_address)
time.sleep(0.5)
sock.sendto(b'streamon', tello_address)
time.sleep(1)
sock.sendto(b'takeoff', tello_address)
time.sleep(2)
# カメラ映像取得
addr = 'udp://192.168.10.1:11111'
cap = cv2.VideoCapture(addr)
print('start cap')
# PID制御パラメータ
pid = [0.4, 0.4, 0]
pError = 0
w, h = 480, 360
# RCコマンド初期値
a = b = c = d = 0
ball_detected = False # 音声を一度だけ再生するためのフラグ
# ピンクボール検出関数
def findBall(img):
global ball_detected
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_pink = np.array([140, 100, 100])
upper_pink = np.array([170, 255, 255])
mask = cv2.inRange(hsv, lower_pink, upper_pink)
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
BallList_center = []
BallList_area = []
for cnt in contours:
area = cv2.contourArea(cnt)
if area > 500:
x, y, w_box, h_box = cv2.boundingRect(cnt)
cx = x + w_box // 2
cy = y + h_box // 2
BallList_center.append([cx, cy])
BallList_area.append(area)
cv2.rectangle(img, (x, y), (x + w_box, y + h_box), (255, 0, 255), 2)
cv2.circle(img, (cx, cy), 10, (0, 0, 255), -1)
if len(BallList_area) != 0:
i = BallList_area.index(max(BallList_area))
if not ball_detected:
speak_async("ピンクのボール発見!追尾します")
ball_detected = True
return img, [BallList_center[i], BallList_area[i]]
else:
ball_detected = False
return img, [[0, 0], 0]
# 左右・前後制御(PID)
def TrackBall(info, w, pid, pError):
global b, d
area = info[1]
x, y = info[0]
b = 0
error = x - w / 2
d = pid[0] * error + pid[1] * (error - pError)
d = int(np.clip(d, -100, 100))
if 6200 < area < 6800:
b = 0
elif area > 6800:
b = -20
elif area < 6200 and area != 0:
b = 20
if x == 0:
d = 0
error = 0
return error
# 上下制御(オプション)
def throttle(y):
global c
c = 0
if 50 < y < 110:
c = 20
elif 280 > y > 190:
c = -20
# メインループ
while True:
for i in range(5): # フレームスキップで安定化
ret, frame = cap.read()
if frame is None or frame.size == 0:
continue
frame = cv2.resize(frame, (w, h))
img, info = findBall(frame)
pError = TrackBall(info, w, pid, pError)
throttle(info[0][1])
rc_command = f"rc {a} {b} {c} {d}"
sock.sendto(rc_command.encode('utf-8'), tello_address)
print("Sending RC command with values:", a, b, c, d)
# 画面に情報表示
cv2.putText(img, f'Pitch: {b} Throttle: {c} Yaw: {d}', (20, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 1)
cv2.imshow('Tracking', img)
# ESCキーで終了
if cv2.waitKey(1) & 0xFF == 27:
sock.sendto(b'land', tello_address)
cap.release()
cv2.destroyAllWindows()
sock.close()
break
- 照明の加減で色味が変わる場合 → HSVの範囲を調整:
lower_pink = np.array([140, 100, 100])
upper_pink = np.array([170, 255, 255])
試行錯誤してボールの色に合った値を調整してください。
投稿
- 空撮事始め (2021年6月18日)
- 航空法施行規則改正されました。令和3年6月1日 (2021年6月19日)
- Tello(Ryze Technology 社 POWERED BY DJI)の飛ばし方マニュアル (2021年7月5日)
- 趣味におすすめ!ドローン(Tello)のいろいろな楽しさをお伝えします。 (2021年7月5日)
- プログラミング言語って?Pythonの導入前にプログラミング言語の種類をおおまかにまとめてみました。 (2021年7月6日)
- ドローンのプログラミングらしき事をやってみる! はじめてのPython&IDEのインストール方法 (2021年7月7日)
- Tello の画像をOpenCVでPCに写してみる!!OpenCVの導入方法 (2021年7月9日)
- これだけは知っておこう!ドローンを飛ばすのに法律って関係あるの? (2021年7月15日)
- ドローンの空撮は最高!きままに撮ってみました(^^♪ 空撮Gallery集 (2021年7月30日)
- ドローンを飛ばすなら これだけは知っておこう!ドローンの飛行ルール(令和3年6月施行) (2021年7月30日)
- これだけは知っておこう!ドローン空撮には注意が必要です。映像等のインターネット上での注意事項。 (2021年7月30日)
- socket通信プログラムの部分を少しだけ解説してみました (2021年9月2日)
- OpenCVで遊んでみる。 PC内蔵webカメラから動画の撮影。 (2021年9月14日)
- PCでOpenCVで顔認識して遊んでみる。(^^♪ カスケード分類器の使い方 (2021年10月30日)
- ドローン・無人航空機の登録が義務化されます。リモートIDの付け方 (2021年12月14日)
- ドローンのプログラミングでOpenCVをつかい顔認識をしてみる (2022年1月9日)
- ドローン(Tello)を飛ばしてOpenCVで顔認識してみる改良版 (2022年2月21日)
- TelloでOpenCVで顔認識させたらFLIP(フリップ)させる(^^♪ (2022年5月2日)
- Pythonを使いTello(ドローン)でOpenCV(顔認識)から自動追尾をしてみる!☺ (2022年6月13日)
- フィンガーサインでドローン(Tello)を操縦してみた!MediaPipeを使用 (2022年9月29日)
- Pythonプログラミング・OpenCv&MediaPipeを使いドローン(Tello)を自由に操縦してみた! (2022年11月21日)
- Pythonで「Tello(ドローン)で自動追尾プログラミング」改良版を紹介します!これはいける! (2023年3月22日)
- OpenCVで遊んでみる。 PC内蔵カメラから映像の表示 と ドローンからの映像を表示をする (2023年4月13日)
- Telloとパソコンの通信の部分を少しわかりやすくしてみました (2023年4月13日)
- 100g未満のドローン、100g以上のドローンを飛ばすには?法律や準備しないといけないことは何? (2023年4月21日)
- mediapipe(メディアパイプ)& OpenCV・ Pythonでposeランドマーク検出Telloの自動操縦 (2023年5月8日)
- プログラミングで動かせるオススメ!ドローン・ロボット ベスト2選!! (2023年6月1日)
- 海外、子供に人気!プログランミングで動かせるドローンLitebeeWing紹介(パソコン接続方法解説)します。 (2023年7月2日)
- 講座用ダウンロード サイト (2023年7月7日)
- ドローン(Tello)を音声認識コントロールできる?パソコンで2か所Wi-Fi接続してGoogle Speech to Text (2023年7月9日)
- 最近はまっている 楽しーい気分転換アイテム ドローン&プログラミング学習用教材&ラジコン (2023年7月26日)
- Scratch(スクラッチ)ビデオモーションセンサーでTello(ドローン)操作 AR「拡張現実」? (2024年1月31日)
- スクラッチ(Scratch3-Tello) & (マイコンボード)micro:bitを使って、Telllo(ドローン)をコントロールしてみた(^^♪ (2024年5月5日)
- マイコンでドローン感知ロボットを作ってみました(^^♪ microbit & arduino (2024年6月1日)
- mediapipe & Arduino で 自称ロボットのジェスチャーコントロール (2024年6月5日)
- M5Stackを内蔵のESP32でWiFiサーバーとして使い、コードレスで無線ジェスチャーコントロールをしてみました(^^)/ (2024年6月12日)
- ロボットアームのジェスチャーコントロールへの挑戦 からだアクション操作*目指せ老後の食事介助アーム* (2024年6月27日)
- LiteBee Wing/ SKY / Tello でドローンプログラミングを教えます。プログラミングしたい人集まれ(^^♪ (2024年7月3日)
- 自由研究に!「ドローンをつくろう!学ぼう!」by 神戸ロボットクラブ (2024年8月17日)
- 加速度センサーとジャイロセンサーをArduinoで使って学び、Telloの慣性ユニットに触れる(^_-)-☆ (2025年1月16日)
- RobotDogを音声でコントロールする。音声認識によりコマンドを選定し、赤外線リモコン作り赤外線を送信し、ロボットをコントロールする。 (2025年2月5日)
- Tello ピンクのボールを追尾する(ピンク色のボール検出(OpenCV HSV)を使い追尾) (2025年6月1日)
タグ
- diy
- NPO法人神戸ロボットクラブ
- pyttsx3
- 自動追尾、
- オシロスコープ
- 神戸ロボットクラブ
- 自由研究
- 小学生
- 組立
- 仕組み
- 特定非営利活動法人神戸ロボットクラブ
- arudino
- ドローンプログラミング
- python opencv
- ドローン自動追尾
- MPU6050
- ADLX345
- 加速度センサー
- ジャイロ
- 慣性ユニット
- ロボット、レーダー、トイドローン
- マイコン、microbit
- DSO152
- 知育教育
- MediaPipe
- プログラミング、自動操縦
- プログラミング、顔認識、自動操縦
- python
- プログラミング 自動追尾
- ロボット
- Otto
- 楽しい
- 親子でプログラミング
- 教育
- マッキーの趣味のドローン
- litebee
- litebeewing
- Scratch
- ドローン
- スクラッチ
- 子供
- モーションセンサー
- IMU
- tello
- OpenCv
- プログラミング
- プログラミング、大人の趣味、老後対策
- 食事介助、ロボットアーム、mediapipe
- arduino