概要

  • 動画像処理において、カメラinput・mp4動画・1枚の画像を使いながらデバッグすることが多いと思う(特にロボット系は)
    • 画像処理は共通で扱わないとバグるので各々のインターフェイスに合わせて画像処理に食わせるまで実装することが多い
  • それらを共通のinterfaceで扱えるようにして、argとかで簡単に切り替えて使えるようにしたcrateを公開した

simple-image-interface-rs について

if args.len() < 2 || &args[1] == "pic" {
        interface = SimpleImageInterface::new_picture("./data/from_raw.png");
    } else if &args[1] == "video" {
        interface = SimpleImageInterface::new_video("./data/random_ball.mp4");
    } else {
        interface = SimpleImageInterface::new_camera("/dev/video0", 640, 360, 330);
        // width, height, fps
    }

    let mut frame_index = 0;
    loop {
        frame_index += 1;
        let input_image = interface.get_frame();
        if input_image.is_none() {
            break;
        }
        my_image_proc(&input_image.unwrap(), frame_index);
    }

利用するCrateのsurvey

rscam

  • https://crates.io/crates/rscam
  • https://docs.rs/rscam/0.5.5/rscam/
  • 最終的に採用したカメラ用crate
    • シンプルに使えそうだったので、採用
    • 正直メンテされてなさそうだけど全然使えたので利用
  • 画像処理に使うなら、initializeの時にformatをRGB3にすることに注意
    camera
        .start(&rscam::Config {
            interval: (1, 50), // fps.
            resolution: (width, height),
            format: b"RGB3",
            ..Default::default()
        })
        .unwrap();

  • 画像を取得するところ
    • 最初の方は速度が出ていないので注意
    let frame = camera.capture().unwrap();
  • frame to image::RGBImageにはto_vecを用いる
    let rgb_image_2 = image::RgbImage::from_vec(width, height, (&frame[..]).to_vec()).unwrap();

その他crate検討 for カメラ

rust-ffmpeg


        // ラムダ式
        let mut receive_and_process_decoded_frames =
            |decoder: &mut ffmpeg::decoder::Video| -> Result<(), ffmpeg::Error> {
                let mut decoded = Video::empty();
                // 有効フレームかどうか
                // 最初数フレームは落ちていることもある
                // frame : ffmpeg::util::frame::video::Video
                while decoder.receive_frame(&mut decoded).is_ok() {
                    let mut rgb_frame = Video::empty();
                    // frameの取り出し
                    scaler.run(&decoded, &mut rgb_frame)?;
                    save_file(&rgb_frame, frame_index).unwrap();
                    frame_index += 1;
                }
                Ok(())
            };

        let mut packet_index = 0;
        for (stream, packet) in ictx.packets() {
            packet_index += 1;
            println!("packet {}", packet_index);
            // ビデオの終わりかを判定
            if stream.index() == video_stream_index {
                decoder.send_packet(&packet)?;
                // ラムダ式に受け渡し
                receive_and_process_decoded_frames(&mut decoder)?;
            } else {
                println!("End of video");
            }
        }
        decoder.send_eof()?;
        receive_and_process_decoded_frames(&mut decoder)?;

その他crate検討 for 動画

作る時につまずいたところ

publishする時のアップロードサイズ制限

  • テスト用にサンプル動画を置いてあったんだけど、どうやら cargo publish のとき、10M以上のファイルがあるとエラーを吐く

error: failed to publish to registry at https://crates.io

Caused by:
  the remote server responded with an error: max upload size is: 10485760
  • ので動画の長さを1/5くらいにする必要があった
  • 2021/09/07 追記
include = ["src/lib.rs", "LICENSE", "README.md"]

最後に

  • crateの利用、PRお待ちしております