nyanpyou Note

主な目的は調べたり作ったりしたプログラミング備忘録(予定)

Windowsのコマンドプロンプトで遊ぶ

コマンドプロンプトで船長を動かすやつ。
以下の記事をたまたま見たことがきっかけで自分でもやってみようと思って作った。
そういう衝動性って大事。

dev.classmethod.jp

#python3.8.1
import subprocess
import cv2
import numpy as np

def preview_by_console(img):

    # 読み込んだ画像を丁度いいサイズにトリミング
    trimmed_img = img[:,300:700]
    gray_img = cv2.cvtColor(trimmed_img, cv2.COLOR_BGR2GRAY)
    height = gray_img.shape[0]
    width = gray_img.shape[1]
    # 画素が多すぎると画面に入りきらないのでリサイズ
    resized_img = cv2.resize(gray_img, (int(width*0.7), int(height*0.4)))
    # 輝度に応じて以下の文字を割り当てる
    char_list = [" ", ".", "_", ":", "|", "+", "*", "#", "&", "$", "@"]

    # 配列をリストに変換
    list_img = resized_img.tolist()
    char_img = []

    # 輝度の値に応じて文字に変換する
    for i in range(len(list_img)):
        temp_list = []
        for s in list_img[i]:
            if 0 <= s <= 69:
                temp_list.append(char_list[0])
            elif 70 <= s <= 89:
                temp_list.append(char_list[1])
            elif 90 <= s <= 109:
                temp_list.append(char_list[2])
            elif 110 <= s <= 129:
                temp_list.append(char_list[3])
            elif 130 <= s <= 149:
                temp_list.append(char_list[4])
            elif 150 <= s <= 169:
                temp_list.append(char_list[5])
            elif 170 <= s <= 189:
                temp_list.append(char_list[6])
            elif 190 <= s <= 209:
                temp_list.append(char_list[7])
            elif 210 <= s <= 229:
                temp_list.append(char_list[8])
            elif 230 <= s <= 249:
                temp_list.append(char_list[9])
            elif 250 <= s <= 255:
                temp_list.append(char_list[10])
        char_img.append(temp_list)

    output_str = ""
    # 文字化した画像を全て1つの文字列に連結してコンソールに出力
    for i in char_img:
        output_str = output_str + " "*100 + "".join(i) + "\n"
    print("{}".format(output_str), end="")

def read_video():
    # 動画ファイルの読み込み
    cap = cv2.VideoCapture(読み込みたい動画ファイルのパス)
    while True:
        # 1フレーム読み込み
        ret, frame = cap.read()
        # 現在何フレーム目かを取得
        frame_Num = int(cap.get(cv2.CAP_PROP_POS_FRAMES))
        if ret:
            # subprocess.callが毎回1秒くらいかかって遅いのでコンソールに表示する際の
            # フレームレートを落とすことで無理矢理時間合わせ
            if frame_Num%6 == 0:
                # コマンドプロンプトをクリア
                subprocess.call("cls", shell=True)
                preview_by_console(frame)
            else:
                pass
        else:
            break

try:
    read_video()
except KeyboardInterrupt:
    print("stop")

subprocess.call()で時間を食っていることはわかったものの、改善方法がわからなかったため結局この形で投稿することに。
調べた結果cursesとかANSIエスケープシーケンスとかで改善できるのでは?と思ったものの、どちらもWindows非対応ということで悲しみを背負う結果に終わった。