@fwettyan

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

python についての質問

python のプログラムについて質問です
python のopencvを利用してwebカメラから赤色と緑色の検出はできたのですが、
マスク画像中に検出した赤色と緑色の両方の物体に緑色の重心をつけ,追従させたいのですが上手くできません。どのようなプログラムを書けばよいでしょうか?
ご教授お願いいたします。

python のバージョンは3.7です
下記のプログラムは緑色と赤色を検出するプログラムです。

-- coding: utf-8 --

import cv2
import numpy as np

def red_detect(img):
# HSV色空間に変換
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 赤色のHSVの値域1
hsv_min = np.array([0,127,0])
hsv_max = np.array([30,255,255])
mask1 = cv2.inRange(hsv, hsv_min, hsv_max)

# 赤色のHSVの値域2
hsv_min = np.array([150,127,0])
hsv_max = np.array([179,255,255])
mask2 = cv2.inRange(hsv, hsv_min, hsv_max)

# 緑色のHSVの値域
hsv_min = np.array([34,60,0])
hsv_max = np.array([90,255,255])
mask3 = cv2.inRange(hsv, hsv_min, hsv_max)

return mask1 + mask2 + mask3

def main():

# カメラのキャプチャ
cap = cv2.VideoCapture(0)

while(cap.isOpened()):

    # フレームを取得
    ret, frame = cap.read()

    # 赤色検出
    mask = red_detect(frame)

    # 結果表示
    cv2.imshow("Frame", frame)
    cv2.imshow("Mask", mask)

    # qキーが押されたら途中終了
    if cv2.waitKey(25) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

if name == 'main':
main()

0 likes

1Answer

現状のプログラムでは、関数red_detectで緑色または赤色を同時に検出しています。まず、問題を簡単にするために、緑色を検出したマスクと、赤色を検出したマスクをそれぞれ分けましょう(同時に検出したマスクでも処理は可能ですが、マスクを分けた場合で成功した後に挑戦してみましょう)。以降では赤色の領域のみの重心を表示するサンプルプログラムを示しますが、緑色の領域についても同様にできます。

検出結果であるマスク画像maskでは、興味のある領域(赤色または緑色)の画素値が255, そうでない領域の画素値が0だと思います。マスク画像にて画素値が255である座標 (x, y) をすべて列挙して、xとyそれぞれの平均値を算出すれば、それが領域の重心になります。

import numpy as np

# (途中の処理は省略)

# 赤色検出
mask_red = red_detect(frame)  # red_detectを修正して、赤色だけ検出するようにしましょう

# マスク画像の画素値が255である座標のリスト(正確にはnp.ndarray)を返す。(y, x)の順になっていることに注意
yx = np.argwhere(mask == 255) 

# yとxのそれぞれの平均値が重心の座標である
center_y, center_x = np.mean(yx, axis=0)

また、OpenCVを使っているなら、cv2.momentsを使っても重心を求めることができます。詳細は領域(輪郭)の特徴 — OpenCV-Python Tutorials 1 documentationなど、他の記事を参照してください。

# 赤色検出
mask_red = red_detect(frame)  # red_detectを修正して、赤色だけ検出するようにしましょう

# 重心を検出する
mu = cv2.moments(mask_red)
center_x = mu["m10"]/mu["m00"]
center_y = mu["m01"]/mu["m00"]

# フレームの画像において、赤い領域の重心に緑色の円を描画する
cv2.circle(frame, (int(center_x), int(center_y)), radius=5, color=(0,255,0), thickness=cv2.FILLED)

# 結果表示
cv2.imshow("Frame", frame)

参考

0Like

Comments

  1. @fwettyan

    Questioner

    ご教授有難うございます。
    赤色の検出は上手くいくことができましたので、次は緑色を試したいと思います。
    一応両方の色での重心の検出は上手くいきましたので、二つ合わせたパターンを頑張りたいと思います。
    また、緑色の点(重心点)の大きさの変更は可能なのでしょうか?
  2. >一応両方の色での重心の検出は上手くいきましたので、二つ合わせたパターンを頑張りたいと思います。

    良かったです!

    >また、緑色の点(重心点)の大きさの変更は可能なのでしょうか?

    はい、可能です。関数cv2.circleの引数radiusが描画する円の大きさを示しています。この値を大きくしてみてください。
  3. @fwettyan

    Questioner

    すみません、送っていただいた赤色と緑色の重心検知のプログラムを参考にし、色々と試してみたのですが、上手く実行できません。
    どのようなプログラムを書けばよいか、もう少しご教授していただけないでしょうか?
  4. お手数ですが、具体的なコードと、実行結果(どううまくできないのか)を教えていただけますか。
  5. @fwettyan

    Questioner

    打ち間違いがあり、そこに気づいたので、解決いたしました。
    ご迷惑をかけて申し訳なかったです。
  6. いえいえ、お気になさらず。解決して何よりです!

Your answer might help someone💌