0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

特徴点の移動量が一定になるように動画を画像に分割する

Last updated at Posted at 2023-05-05

MarkDownがよくわかっていないので、あんまりきれいにはかけないかもです。
備忘録的に進めていければと思います。

①きっかけ
非GPS環境で飛ぶようなドローンを使ってSfM処理をしようとすると、必要なラップ率を満たすように画像を作成するのが難しいから。

②解決方法
特徴点の移動量を取得したすべてのフレームに対して計算して、各特徴点のマグニチュードを計算し、その平均値の変動量から計算すればいいのでは

③コーディング
がんばれ、ChatGPT君。

import cv2
import os
import numpy as np
from tqdm import tqdm
from multiprocessing import Process, cpu_count

def optical_flow_magnitude(gray1, gray2):
    flow = cv2.calcOpticalFlowFarneback(gray1, gray2, None, 0.5, 3, 15, 3, 5, 1.2, 0)
    mag, _ = cv2.cartToPolar(flow[..., 0], flow[..., 1])
    return np.mean(mag)

def process_video(video_file, input_dir, output_dir, threshold):
    video_path = os.path.join(input_dir, video_file)
    video = cv2.VideoCapture(video_path)

    frame_count = 0
    ret, prev_frame = video.read()
    prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
    cv2.imwrite(os.path.join(output_dir, f'frame{frame_count:04d}.png'), prev_frame)

    with tqdm(desc=f"Processing {video_file}", total=int(video.get(cv2.CAP_PROP_FRAME_COUNT))) as pbar:
        while video.isOpened():
            ret, frame = video.read()
            pbar.update(1)
            if not ret:
                break

            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            mag = optical_flow_magnitude(prev_gray, gray)

            if mag > threshold:
                frame_count += 1
                output_path = os.path.join(output_dir, f'frame{frame_count:04d}.png')
                cv2.imwrite(output_path, frame)
                prev_gray = gray

    video.release()

def main():
    input_dir = './input'
    output_dir = './output'
    threshold = 5

    os.makedirs(output_dir, exist_ok=True)

    video_files = [f for f in os.listdir(input_dir) if f.endswith('.MOV')]

    processes = []
    num_processes = min(cpu_count(), len(video_files))

    for i in range(num_processes):
        p = Process(target=process_video, args=(video_files[i], input_dir, output_dir, threshold))
        p.start()
        processes.append(p)

    for p in processes:
        p.join()

    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

カレントディレクトリのInputフォルダ内にmp4でデータを入れて、閾値を調整したら実行。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?