TelloPyのvideo_effect2.pyを改造して、Telloカメラの画像に色々な画像処理をかけた結果をリアルタイムにマルチウィンドウ出力した件


TelloPyに同梱されている__*video_effect2.py*__にコードを書き足して、Tello内蔵カメラから送られてくるフレーム画像に、複数の異なる画像編集処理をかけた結果を、リアルタイムにマルチウィンドウ表示する処理を付け足しました。

実行すると、複数のウィンドウが立ち上がって、書き加えた複数の画像処理パイプラインを通過したフレーム画像が、リアルタイムに表示されました。

####__（ 追加したウィンドウ ）__

- __'Mosaic_Low_Resolution'ウィンドウ__ ： OpenCV2で画像を30分の1に圧縮後、元のサイズに戻したフレーム画像
- __'Mosaic_High_Resolution'ウィンドウ__ ： OpenCV2で画像を15分の1に圧縮後、元のサイズに戻したフレーム画像
- __'bitwised_image'ウィンドウ__ ： OpenCV2のbitwise_notメソッドをかけたフレーム画像
- __'gaussian_image'ウィンドウ__ ： OpenCV2のGaussianBlurメソッドをかけたフレーム画像


####関連記事

- [TelloPyをMacbookで動かして、FPV1人称視点の腹画像と輪郭抽出モノクロ画像のリアルタイム受信に成功](https://qiita.com/electronics_diy721/items/67df0accbb99fc60824e)

####参考にしたサイト

- [OpenCVによる画像変換の効果](https://qiita.com/FujiedaTaro/items/2c270f2b8376fc0c4a35)
- [【Google Colab】OpenCVで画像をイラスト変換](https://qiita.com/shoku-pan/items/6ac95135b68731338624)
- [【Python/OpenCV】写真を漫画化、アニメ絵化、ドット絵化、ミニチュア化](https://algorithm.joho.info/programming/python/opencv-manga-filter-py/)

####コードを書き足した箇所 （「以下を追加」〜「ここまで」）

```Python3:video_effect2.py（TelloPy）
        # skip first 300 frames
        frame_skip = 300
        while True:
            for frame in container.decode(video=0):
                if 0 < frame_skip:
                    frame_skip = frame_skip - 1
                    continue
                start_time = time.time()
                image = cv2.cvtColor(numpy.array(frame.to_image()), cv2.COLOR_RGB2BGR)
                cv2.imshow('Original', image)
                cv2.imshow('Canny', cv2.Canny(image, 100, 200))
                #以下を追加
                resize_image_30 = cv2.resize(image, (image.shape[1] // 30, image.shape[0] // 10))
                mosaic_resolution_low_image = cv2.resize(resize_image_30, (image.shape[1], image.shape[0]))
                resize_image_15 = cv2.resize(image, (image.shape[1] // 15, image.shape[0] // 10))
                mosaic_resolution_high_image = cv2.resize(resize_image_15 ,(image.shape[1], image.shape[0]))                
                cv2.imshow('Mosaic_Low_Resolution', mosaic_resolution_low_image)
                cv2.imshow('Mosaic_High_Resolution', mosaic_resolution_high_image)
                
                bitwised_image = cv2.bitwise_not(image)
                cv2.imshow('Bitwised', bitwised_image)
                gaussian_image = cv2.GaussianBlur(image, (51, 51), 0)
                cv2.imshow('Gaussian Blur', gaussian_image)
                #ここまで
                cv2.waitKey(1)
```


###実行コード

```bash:Terminal
electron@diynoMacBook-Pro examples % python3 video_effect2.py   
```


###実行したスクリプトファイル

```Python3:video_effect2.py
import sys
import traceback
import tellopy
import av
import cv2.cv2 as cv2  # for avoidance of pylint error
import numpy
import time


def main():
    drone = tellopy.Tello()

    try:
        drone.connect()
        drone.wait_for_connection(60.0)

        retry = 3
        container = None
        while container is None and 0 < retry:
            retry -= 1
            try:
                container = av.open(drone.get_video_stream())
            except av.AVError as ave:
                print(ave)
                print('retry...')

        # skip first 300 frames
        frame_skip = 300
        while True:
            for frame in container.decode(video=0):
                if 0 < frame_skip:
                    frame_skip = frame_skip - 1
                    continue
                start_time = time.time()
                image = cv2.cvtColor(numpy.array(frame.to_image()), cv2.COLOR_RGB2BGR)
                cv2.imshow('Original', image)
                cv2.imshow('Canny', cv2.Canny(image, 100, 200))
                #以下を追加
                resize_image_30 = cv2.resize(image, (image.shape[1] // 30, image.shape[0] // 10))
                mosaic_resolution_low_image = cv2.resize(resize_image_30, (image.shape[1], image.shape[0]))
                resize_image_15 = cv2.resize(image, (image.shape[1] // 15, image.shape[0] // 10))
                mosaic_resolution_high_image = cv2.resize(resize_image_15 ,(image.shape[1], image.shape[0]))                
                cv2.imshow('Mosaic_Low_Resolution', mosaic_resolution_low_image)
                cv2.imshow('Mosaic_High_Resolution', mosaic_resolution_high_image)
                
                bitwised_image = cv2.bitwise_not(image)
                cv2.imshow('Bitwised', bitwised_image)
                gaussian_image = cv2.GaussianBlur(image, (51, 51), 0)
                cv2.imshow('Gaussian Blur', gaussian_image)
                #h, w, c = image.shape
                #M = cv2.getRotationMatrix2D((w/2, h/2), 90, 1)
                #imaga_rotated = cv2.warpAffine(image, M, (750, 750))
                #cv2.imshow('Rotated', cv2.cvtColor(imaga_rotated, cv2.COLOR_BGR2RGB))
                #ここまで
                cv2.waitKey(1)
                if frame.time_base < 1.0/60:
                    time_base = 1.0/60
                else:
                    time_base = frame.time_base
                frame_skip = int((time.time() - start_time)/time_base)
                    

    except Exception as ex:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        traceback.print_exception(exc_type, exc_value, exc_traceback)
        print(ex)
    finally:
        drone.quit()
        cv2.destroyAllWindows()

if __name__ == '__main__':
    main()
```

###今後の抱負

Telloから送られてくるフレームに、次の処理をかけた結果をウィンドウに表示させたい。

- 物体検出結果
- 人の骨格推定結果
- 人の視線方向（顔方向のロー、ピッチ、ヨー角度）
- 画像のキャプション文生成器から出力されたテキスト文を、原画像にテロップとして埋め込んだ画像
- MITとAdobeが論文発表した、画像内の被写体の物質素材を推定する処理を行った結果をラベル表示（石、木、プラスチックなど）
- MITとAdobeが論文発表した、画像を表現する音声をMacbookのスピーカーから鳴らす
- 人体や自動車などの一瞬先の推定移動先座標のBoxを、原画像に重畳表示させた画像