🦋

OpenCV(C++)のVideoCaptureで動画ファイルが読み込めない

2023/01/11に公開

課題

OpenCV(C++)のVideoCaptureで動画ファイルが読み込めない

環境

Ubuntu 20.04 LTS
公式に従って、CMakeでOpenCVをBuildした。

解決策

FFmpegをインストールすれば良い。(関連するモジュールも含めて)

公式ドキュメントにある通り、OpenCVの動画の読み書きの機能(VideoCapture)はFFmpegというライブラリに依存している。

Essentially, all the functionalities required for video manipulation is integrated in the cv::VideoCapture C++ class. This on itself builds on the FFmpeg open source library. This is a basic dependency of OpenCV so you shouldn't need to worry about this. A video is composed of a succession of images, we refer to these in the literature as frames. In case of a video file there is a frame rate specifying just how long is between two frames. While for the video cameras usually there is a limit of just how many frames they can digitize per second, this property is less important as at any time the camera sees the current snapshot of the world.

Ubuntuには元々FFmpegはインストールされていない。
FFmpegの公式サイトの案内に従ってインストールすれば良い。

Ubuntuに関しては、これ。

実際、CMakeでのbuildの設定をのログを見ると、

-- Checking for modules 'libavcodec;libavformat;libavutil;libswscale'
--   No package 'libavcodec' found
--   No package 'libavformat' found
--   No package 'libavutil' found
--   No package 'libswscale' found

そして、CMakeのログに表示されるbuild予定の設定は下記のようになる。
なんかFFMPEG関連のモジュールが使えていませんね。

--   Video I/O:
--     DC1394:                      NO
--     FFMPEG:                      NO
--       avcodec:                   NO
--       avformat:                  NO
--       avutil:                    NO
--       swscale:                   NO
--       avresample:                NO
--     GStreamer:                   NO
--     v4l/v4l2:                    YES (linux/videodev2.h)

だから、上記のCMakeのログで足りないと言われているモジュールをインストールする。

要するに、ここから必要なのをインストールする。

sudo apt install ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev

これで下記の様になる。
なんかFFMPEG関連のモジュールが使えそうですね。

--   Video I/O:
--     DC1394:                      NO
--     FFMPEG:                      YES
--       avcodec:                   YES (58.54.100)
--       avformat:                  YES (58.29.100)
--       avutil:                    YES (56.31.100)
--       swscale:                   YES (5.5.100)
--       avresample:                NO
--     GStreamer:                   NO
--     v4l/v4l2:                    YES (linux/videodev2.h)

これで動画を読み込めるようになりました!

FFmpegをインストール後、OpenCVを再ビルドしなければならないのが面倒ですね。

実装例

一応、動く実装例を載せておきます。

#include <iostream>
#include <string>

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>

int main()
{
    // 動画を表示するウィンドウ
    cv::namedWindow("window", cv::WINDOW_AUTOSIZE);

    // 動画を読み込む
    const std::string filePath = "動画のパス.mp4";
    cv::VideoCapture cap(filePath, cv::CAP_FFMPEG);

    // 動画が読み込めるか確認
    if (!cap.isOpened())
    {
        std::cout << "動画を開けません" << std::endl;
        return -1;
    }

    // 動画を再生する
    cv::Mat frame;
    for(;;) {
        cap >> frame;
        if (frame.empty()) {
            break;
        }

        cv::imshow("window", frame);
        if ((char)cv::waitKey(33) >= 0) {
            break;
        }
    }
    return 0;
}

その他

そもそも、UbuntuでC++のOpenCVのチュートリアルが動かなくて、ビルドし直したりしました。

あと、FFmpegのライセンスが商用利用云々なので、商用利用したい人はそこら辺もよく読む必要がありそう。

Discussion