メモです

メモです

PythonでYouTubeの動画や音声を保存する

インストール

pip3 install youtube-dl

動画を保存

outtmplでファイル名指定(省略可)

from __future__ import unicode_literals
import youtube_dl

url = 'https://www.youtube.com/watch?v=ANbGAMsEwSg'

ydl_opts = {
     'outtmpl':'hoge',
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download([url])

音声のみを保存

outtmplでファイル名指定(省略可/拡張子必須)

from __future__ import unicode_literals
import youtube_dl

url = 'https://www.youtube.com/watch?v=ANbGAMsEwSg'

ydl_opts = {
    'format': 'bestaudio/best',
    'postprocessors': [{
        'key': 'FFmpegExtractAudio',
        'preferredcodec': 'mp3',
        'preferredquality': '192',
    }],
    'outtmpl':'hoge.mp3',
}

with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download([url])

example

・リストで一括ダウンロード
・音声だけを取り出す
・ファイル名は動画のタイトル

from __future__ import unicode_literals
import youtube_dl

url = ['https://youtu.be/TplaQhVNUKk','https://www.youtube.com/watch?v=CBKQoqTI2iE']

ydl_opts = {
    'format': 'bestaudio/best',
    'postprocessors': [{
        'key': 'FFmpegExtractAudio',
        'preferredcodec': 'mp3',
        'preferredquality': '192',
    }],
    'outtmpl':'%(title)s.mp3',
}

with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download(url)

exampl2

・動画のタイトルや再生回数などのメタデータだけ取得する
・extract_infoはurlのリストを受け付けないので注意

import youtube_dl

url = 'https://www.youtube.com/watch?v=2tA1rVKv4EE'


ydl_opts = {
    'writeautomaticsub': 'False',
}

with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    res = ydl.extract_info(url, download=False)

print(res['title'])  # タイトル
print(res['view_count'])  # 視聴回数
print(res['automatic_captions']['ja'])  # 自動生成の日本語字幕

MacでJISキーボードを使う

・Karabiner-Elementsをインストール

・Karabiner-Elementsを起動してsimple-modificationsでFrom Keyに「grave_accent_and_tilde」をTo keyに「F13」を設定する

・システム環境設定(歯車のアイコン)を起動し、キーボードを開く

・キーボードの種類を変更を押下し、指示に従う。

・次に「修飾キー」というボタンを押下。ControlキーをCommandに設定する。

 

以上で半角/全角キーでかな英字の切替が可能になると同時に、Ctrlキーが機能する様になる

 

が、普通にMacの純正キーボードを買え。そっちの方が楽。

1-stage-wsegのバグとかエラーの殴り書き

 

github.com

をやっとる。

 

pascal_vocのみに対応

pascal_voc.pyで学習データのフォーマットとかクラス数とかクラス名を定義しているっぽい。def __getitem__でクラスを取得している。

・backboneをresnet101にするときはvoc_resnet101.yamlの「LR_SCHEDULER: "none"」を消さないとエラーになる

・READMEには書いてないけど、画像のファイル名を書いたtrain_aug.txtが必要っぽい

COCO FormatからPascal VOC Formatに変換する

import cv2
import re
from PIL import Image
import io
import json
import os
import numpy as np
from tqdm import tqdm
import requests

#画像データのディレクトリ
IMG_DIR = "./img/"
#ラベル画像のディレクトリ
LBL_DIR = "./lbl/"

with open('input_coco_format.json') as f:
     jsn = json.load(f)

#私の環境だと、file_nameにファイル名入りのURLが入っていたので正規表現を使っている
pattern = '[a-zA-Z0-9]+\.[a-zA-Z]+$'
repatter = re.compile(pattern)

for t in tqdm(jsn["annotations"]):
    sg = t["segmentation"]
    category = t["category_id"]
    #リストをforループで回すと遅いのでsetとかで書き直した方がいい
    for j in jsn["images"]:
        if j["id"] == t["image_id"]:
            width = j['width']
            height = j['height']
            m = repatter.search(j['file_name'])
            img = Image.open(io.BytesIO(requests.get(j['coco_url']).content))

            img.save(IMG_DIR + m.group())

    # working file
 # cv2だとy,x,cの順なので注意
    mask = np.zeros((int(height), int(width), 3))  # (y, x, c)

    # segmentation data
    sg = np.asarray(sg[0])
    poly_number = int(len(sg) / 2)
    poly = np.zeros((poly_number, 2))
    for i in range(poly_number):
        poly[i][0] = sg[(i * 2) + 0]  # x
        poly[i][1] = sg[(i * 2) + 1]  # y

 #category_idをそのまま使っている
    mask = cv2.fillConvexPoly(mask, np.array(
        poly, 'int32'), color=(category, category, category))

    # generate src_img and mask_image
    cv2.imwrite(LBL_DIR + m.group(), mask)


大変参考にさせていただいた
Pythonでポリゴン(多角形)の領域を抽出する方法 - Qiita

Labelboxの出力をCOCO Formatに変換する

LabelBoxのアウトプットが独自フォーマットになったのとCOCOで出力できなくなったのと公式レポジトリの変換ツールが使えないので作った。正直いろんなサイトのやつを見て作ったのでオリジナリティはない。

なお、for文でlabelboxのデータにアクセスするとたまにtimeoutになるので元の画像とアノテーション画像をローカルに保存してからやる。
あとLaeblboxはRLE形式では出力せずにどんなときもpolygon形式で出力していたのでそれに合わせた

import json
import io
import logging
import datetime as dt
import os
import numpy as np
from skimage import measure
from PIL import Image
from pycocotools import mask
from tqdm import tqdm

def main():
    with open('input.json') as f:
        jsn = json.load(f)

    coco = make_coco_metadata("train", "John Dow")

    for data in tqdm(jsn):
        convert_data(coco, data['ID'], data['External ID'],
                         data['Labeled Data'], data['Label']['objects'])

    with open('output.json', 'w') as f:
        json.dump(coco, f, indent=4)

def convert_data(coco, id, file_name, image_url, labels):
    image = {
        "id": id,
        "file_name": file_name,
        "license": None,
        "flickr_url": image_url,
        "coco_url": image_url,
        "date_captured": None,
    }

    file_path = file_name
    image['width'], image['height'] = Image.open(file_path).size
    coco['images'].append(image)

    # labelがない場合、処理をスキップ
    if labels == []:
        return

    category_id = None

    for label_data in labels:
        for c in coco['categories']:
            if c['name'] == label_data['title']:
                category_id = c['id']

        if category_id == None:
            category_id = len(coco['categories']) + 1
            category = {
                # supercategoryがある場合はここを修正する
                'supercategory': label_data['title'],
                'id': category_id,
                'name': label_data['title']
            }
            coco['categories'].append(category)

        #conert("L")でアルファチャンネルを消して、2D画像化
        binary_mask=np.array(Image.open(file_name).convert("L"))

        create_annotation_info(coco=coco, image_id=id, category_id=category_id, binary_mask=binary_mask)

def create_annotation_info(coco, image_id, category_id, binary_mask, tolerance=2):
    binary_mask_encoded = mask.encode(
        np.asfortranarray(binary_mask.astype(np.uint8)))

    area = mask.area(binary_mask_encoded)
    bounding_box = mask.toBbox(binary_mask_encoded)
    polygons = get_polygons(binary_mask)

    #labelboxが出力するcocoはiscrowd:0で固定されていたのでこうしている
    annotation = {
        "id": len(coco['annotations']) + 1,
        "image_id": image_id,
        "category_id": category_id,
        "iscrowd": 0,
        "area": area.tolist(),
        "bbox": bounding_box.tolist(),
        "segmentation": polygons
    }

    coco['annotations'].append(annotation)

def get_polygons(binary_mask):
    polygons = []
    # pad mask to close contours of shapes which start and end at an edge
    padded_binary_mask = np.pad(
        binary_mask, pad_width=1, mode='constant', constant_values=0)
    contours = measure.find_contours(padded_binary_mask, 0.5)
    contours = np.subtract(contours, 1)
    for contour in contours:
        contour = close_contour(contour)
        contour = measure.approximate_polygon(contour, tolerance=5)
        if len(contour) < 3:
            continue
        contour = np.flip(contour, axis=1)
        segmentation = contour.ravel().tolist()
        # after padding and subtracting 1 we may get -0.5 points in our segmentation
        segmentation = [0 if i < 0 else i for i in segmentation]
        polygons.append(segmentation)

    return polygons

def close_contour(contour):
    if not np.array_equal(contour[0], contour[-1]):
        contour = np.vstack((contour, contour[0]))
    return contour

def make_coco_metadata(project_name, created_by):
    return {
        'info': {
            'year': dt.datetime.now(dt.timezone.utc).year,
            'version': None,
            'description': project_name,
            'contributor': created_by,
            'url': 'labelbox.com',
            'date_created': dt.datetime.now(dt.timezone.utc).isoformat()
        },
        'images': [],
        'annotations': [],
        'licenses': [],
        'categories': []
    }

if __name__ == '__main__':
    main()

参考:
Labelbox/coco_exporter.py at master · Labelbox/Labelbox · GitHub
pycococreator/pycococreatortools.py at master · waspinator/pycococreator · GitHub

tf-pose-estimationをGoogleColaboratoryでやる

準備

tf-pose-estimation/run.py at master · ildoonet/tf-pose-estimation · GitHub
をダウンロードする。ファイル名はrun.pyにする。
run.pyをエディタで開いて88行目付近を

plt.colorbar()
plt.savefig('output.png')
plt.show()

に編集して保存する。

実行

!git clone https://www.github.com/ildoonet/tf-pose-estimation
cd tf-pose-estimation
pip install tqdm==4.29.0
!pip install -r requirements.txt
!bash models/graph/cmu/download.sh
!sudo apt install swig
!swig -python -c++ tf_pose/pafprocess/pafprocess.i
cd tf_pose/pafprocess
!python setup.py build_ext --inplace
cd ../../
rm run.py
from google.colab import files
files.upload()
!python run.py --model=cmu --resize=432x368 --image=./images/p1.jpg
from IPython.display import Image,display_png
display_png(Image('output.png'))

uploadのところで準備で編集したrun.pyをアップロードする。