89031


ネットからお借りしたコードをraspberry
piで実行した際に、カメラを少し激しく動かしたりすると、以下のようにエラーが発生してフリーズしてしまいます。どのように対処すればよろしいのか、ご指導お願いします。

**エラーメッセージ:**

[code]

    Traceback (most recent call last):
      File "/home/pi/akairo.py", line 83, in <module>
        main()
      File "/home/pi/akairo.py", line 60, in main
        target = analysis_blob(mask)
      File "/home/pi/akairo.py", line 32, in analysis_blob
        max_index = np.argmax(data[:, 4])
      File "<__array_function__ internals>", line 180, in argmax
      File "/home/pi/.local/lib/python3.9/site-packages/numpy/core/fromnumeric.py", line 1216, in argmax
        return _wrapfunc(a, 'argmax', axis=axis, out=out, **kwds)
      File "/home/pi/.local/lib/python3.9/site-packages/numpy/core/fromnumeric.py", line 57, in _wrapfunc
        return bound(*args, **kwds)
    ValueError: attempt to get argmax of an empty sequence
    
[/code]

**ソースコード:**

[code]

    # -*- 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)
        
        return mask1 + mask2
    
    # ブロブ解析
    def analysis_blob(binary_img):
        # 2値画像のラベリング処理
        label = cv2.connectedComponentsWithStats(binary_img)
    
        # ブロブ情報を項目別に抽出
        n = label[0] - 1
        data = np.delete(label[2], 0, 0)
        center = np.delete(label[3], 0, 0)
    
        # ブロブ面積最大のインデックス
        max_index = np.argmax(data[:, 4])
    
        # 面積最大ブロブの情報格納用
        maxblob = {}
    
        # 面積最大ブロブの各種情報を取得
        maxblob["upper_left"] = (data[:, 0][max_index], data[:, 1][max_index]) # 左上座標
        maxblob["width"] = data[:, 2][max_index]  # 幅
        maxblob["height"] = data[:, 3][max_index]  # 高さ
        maxblob["area"] = data[:, 4][max_index]   # 面積
        maxblob["center"] = center[max_index]  # 中心座標
        
        return maxblob
    
    def main():
        videofile_path = "C:/github/sample/python/opencv/video/color_tracking/red_pendulum.mp4"
    
        # カメラのキャプチャ
        cap = cv2.VideoCapture(0)
        
        while(cap.isOpened()):
            # フレームを取得
            ret, frame = cap.read()
    
            # 赤色検出
            mask = red_detect(frame)
    
            # マスク画像をブロブ解析（面積最大のブロブ情報を取得）
            target = analysis_blob(mask)
    
            # 面積最大ブロブの中心座標を取得
            center_x = int(target["center"][0])
            center_y = int(target["center"][1])
    
            # フレームに面積最大ブロブの中心周囲を円で描く
            cv2.circle(frame, (center_x, center_y), 30, (0, 200, 0),
                       thickness=3, lineType=cv2.LINE_AA)
    
            # 結果表示
            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() 
    
[/code]


CC BY-SA 4.0
2022-05-22T15:17:17.640
88985
2022-05-25T00:38:51.910
2022-05-22T16:16:26.897
3060
52750
question
python opencv raspberry-pi camera
OpenCV で一番大きい赤色の物質の判定時にカメラを動かすとエラーが発生する


この現象は、特定条件時にdata配列が期待した次元数が不足もしくは空であることから、data[:,4]で指定した抽出条件では空(empty)になっているのだと推察します。よって、np.argmax()メソッドに渡される引数が無効で例外ValueErrorが発生しています。

dataの次元数などを確認して条件が満たせない場合には例外UserExceptionを故意に発生させ、この故意の例外が発生したら無視して処理を続けるようにしました。

注意点としては、例外が発生した動画フレームをスキップするので、フレーム数を何等かの判定に使用するなどの改変をされる場合には、工夫が必要です。

[code]

    # -*- coding: utf-8 -*-
    import cv2
    import numpy as np
    
    
    # ユーザーの意図的な例外処理を定義する。
    class UserException(Exception):
        pass
    
    
    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)
    
        return mask1 + mask2
    
    # ブロブ解析
    
    
    def analysis_blob(binary_img):
        # 2値画像のラベリング処理
        label = cv2.connectedComponentsWithStats(binary_img)
    
        # ブロブ情報を項目別に抽出
        n = label[0] - 1
        data = np.delete(label[2], 0, 0)
        center = np.delete(label[3], 0, 0)
    
        # 配列の次元数を取得
        dimensions = data.shape
    
        # dimensionsが空ではない
        if dimensions:
            # 2次元以上であること。※data[:,4]より2次元目のindex=4を参照しているため
            if len(dimensions) >= 2:
                # 2次元目の要素数を確認
                dim2nd = dimensions[1]
                # 2次元目の要素数5以上ならdata[:,4]の2次元目のindex=4の条件を満たす
                if dim2nd >= 5:
                    # ブロブ面積最大のインデックス
                    max_index = np.argmax(data[:, 4])
    
                    # 面積最大ブロブの情報格納用
                    maxblob = {}
    
                    # 面積最大ブロブの各種情報を取得
                    maxblob["upper_left"] = (data[:, 0][max_index],
                                             data[:, 1][max_index])  # 左上座標
                    maxblob["width"] = data[:, 2][max_index]  # 幅
                    maxblob["height"] = data[:, 3][max_index]  # 高さ
                    maxblob["area"] = data[:, 4][max_index]   # 面積
                    maxblob["center"] = center[max_index]  # 中心座標
    
                    return maxblob
    
        # 上記returnの行まで至らない場合は、条件を満たしていないため、自分で定義した例外を発生させる。
        raise UserException
    
    
    def main():
        videofile_path = "C:/github/sample/python/opencv/video/color_tracking/red_pendulum.mp4"
    
        # カメラのキャプチャ
        cap = cv2.VideoCapture(videofile_path)
    
        while(cap.isOpened()):
            # フレームを取得
            ret, frame = cap.read()
    
            # 赤色検出
            mask = red_detect(frame)
    
            # 例外エラーのキャッチ
            try:
                # マスク画像をブロブ解析（面積最大のブロブ情報を取得）
                target = analysis_blob(mask)
    
                # 面積最大ブロブの中心座標を取得
                center_x = int(target["center"][0])
                center_y = int(target["center"][1])
    
                # フレームに面積最大ブロブの中心周囲を円で描く
                cv2.circle(frame, (center_x, center_y), 30, (0, 200, 0),
                           thickness=3, lineType=cv2.LINE_AA)
    
                # 結果表示
                cv2.imshow("Frame", frame)
                cv2.imshow("Mask", mask)
            # ユーザー定義例外が発生したら、無視して続ける。
            except UserException:
                continue
    
            # qキーが押されたら途中終了
            if cv2.waitKey(25) & 0xFF == ord('q'):
                break
    
        cap.release()
        cv2.destroyAllWindows()
    
    
    if __name__ == '__main__':
        main()
    
    
[/code]


CC BY-SA 4.0
2022-05-25T00:38:51.910
89031
2022-05-25T00:38:51.910
32891
88985
answer