質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.91%

抽出する画像の枚数を制限したい。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 177

Keiti

score 5

以下のコードは動画を読み込み、その動画内に写ったマスクをつけた人物の顔を切り取り、画像として抽出するコードになります。
実行自体は上手く行くのですが、動画のフレーム数を全て画像として抽出してしまうので、長い動画を読み込んだ際には必要以上に画像が生成されてしまいます(例えば、1000のフレームで構成された動画を読み込むと必要な写真は100枚にもかかわらず1000枚生成されてしまいます)。
そこで、生成する画像の枚数を制限したいのですがどのようにコードを書き換えればよいかわかりません。どうかご教示ください。

drive.mount('/content/drive')
from google.colab.patches import cv2_imshow
import paddlehub as hub
import cv2
from PIL import Image, ImageDraw, ImageFont
import numpy as np
import json
import os

module = hub.Module(name="pyramidbox_lite_server_mask", version='1.1.0')

def paint_chinese(im, chinese, position, fontsize, color_bgr):
    img_PIL = Image.fromarray(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
    font = ImageFont.truetype(
        'SourceHanSansSC-Medium.otf', fontsize, encoding="utf-8")
    color = color_bgr[::-1]
    draw = ImageDraw.Draw(img_PIL)
    draw.text(position, chinese, font=font, fill=color)
    img = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR)  
    return img


result_path = './result'
if not os.path.exists(result_path):
    os.mkdir(result_path)

name = "./result/1-mask_detection.mp4"
width = 1280
height = 720
fps = 30
fourcc = cv2.VideoWriter_fourcc('m','p','4', 'v') # changed *'vp90' -> 'm','p','4', 'v'
writer = cv2.VideoWriter(name, fourcc, fps, (width, height))

maskIndex = 0
index = 0
data = []

capture = cv2.VideoCapture('/content/drive/My Drive/sozai/5.mp4')  

while True:
    frameData = {}
    ret, frame = capture.read()  
    if ret == False:
        break

    frame_copy = frame.copy()
    input_dict = {"data": [frame]}
    results = module.face_detection(data=input_dict)

    maskFrameDatas = []
    for result in results:
        label = result['data']['label']
        confidence_origin = result['data']['confidence']
        confidence = round(confidence_origin, 2)
        confidence_desc = str(confidence)

        top, right, bottom, left = int(result['data']['top']), int(
            result['data']['right']), int(result['data']['bottom']), int(
                result['data']['left'])

        img_name = "avatar_%d.png" % (maskIndex)
        path = "/content/drive/My Drive/Face/A_face/" + img_name
        image = frame[top - 10:bottom + 10, left - 10:right + 10]
        cv2.imwrite(path, image, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])

        maskFrameData = {}
        maskFrameData['top'] = top
        maskFrameData['right'] = right
        maskFrameData['bottom'] = bottom
        maskFrameData['left'] = left
        maskFrameData['confidence'] = float(confidence_origin)
        maskFrameData['label'] = label
        maskFrameData['img'] = img_name

        maskFrameDatas.append(maskFrameData)

        maskIndex += 1

        color = (0, 255, 0)
        label_cn = "有口罩"
        if label == 'NO MASK':
            color = (0, 0, 255)
            label_cn = "无口罩"

        cv2.rectangle(frame_copy, (left, top), (right, bottom), color, 3)
        cv2.putText(frame_copy, label, (left, top-10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2)

    writer.write(frame_copy)

    frameData['frame'] = index
    frameData['data'] = maskFrameDatas

    data.append(frameData)
    print(json.dumps(frameData))

    index += 1

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

with open("./result/2-mask_detection.json", "w") as f:
    json.dump(data, f)

writer.release()

cv2.destroyAllWindows()

個人的にチャレンジしてみたことはindex,maskindex,fpsなどの値を変えてみたことです。frameData['frame']=index
などと書かれているので、indexの値を制限すれば取得するframe数も制限されると考えました。
ちなみにこのコードは以下のサイトから引用させていただきました。
(https://qiita.com/ebiflyyyyyyyy/items/4f8cc781a86c3f9d8700)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • can110

    2020/07/19 19:02 編集

    各フレームにおいて画像(.png)を保存すべきかどうかはどのようなルールで決めるのでしょうか?
    無条件に先頭の100フレームでよいでしょうか?
    あるいはマスクをつけた画像のみ保存ということでしょうか?

    キャンセル

  • Keiti

    2020/07/19 19:32

    実は欲を言えば無作為に保存したいんですよね・・・例えば1,34,56,78,,,,みたいな感じが理想的です!

    キャンセル

  • can110

    2020/07/19 19:37

    ソースコード上で画像ファイルを保存しているところ(行)はどこか分かりますでしょうか?

    キャンセル

回答 1

checkベストアンサー

+1

画像ファイル保存処理の部分を以下のようなif文で囲んで保存可否を切り替えればよいかと思います。

import random
        :
        if random.random() > 0.9: # 例えばこんな感じで無作為に
            img_name = "avatar_%d.png" % (maskIndex)
            path = "/content/drive/My Drive/Face/A_face/" + img_name
            image = frame[top - 10:bottom + 10, left - 10:right + 10]
            cv2.imwrite(path, image, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])

        maskIndex += 1

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/20 18:29

    遅くなってすみません!できました!ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る