MinGWでOpenCVを使う

# はじめに

WindowsでOpenCVを使いたいと思ったとき、公式（[https://opencv.org/releases/](https://opencv.org/releases/)）からビルド済みのインストーラをダウンロードして確認すると、vc++でビルドされたものであることがわかります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/4873ef80-700a-405d-a994-c432c25d6611.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/2f58fa5c-85a1-c2bf-c1d6-9dd5e03572be.png)

Visual Studioを使っているなら問題ないのですが、自分のように普段MinGWを使っている場合、このモジュールにパスを通してg++ビルドしようとするとリンカでエラーが発生してしまいます。

解決策としてMinGWでOpenCV本体からソースビルドする方法があるので、そちらを試しつつ、Windowsでの開発準備の過程をまとめてみます。

### 環境

- Windows10（Windows11でも同じ手順で成功しました）
- g++ 13.1.0
- make 3.81
- cmake 3.27.0 RC3

# ビルド

## インストール

### MinGW

https://github.com/niXman/mingw-builds-binaries/releases

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/51980415-9207-6c59-3173-ba22d274e645.png)

目的に合うものを選択する。よくわからなければ、試しに遊ぶだけなら大きな差はないので、一番上の「x86_64-13.2.0-release-posix-seh-msvcrt-rt_v11-rev0.7z」で問題ないかと。

### make

https://gnuwin32.sourceforge.net/packages/make.htm

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/4ac273cf-2f79-2a38-9582-2239ea2a7b06.png)

### cmake

https://cmake.org/download/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/8d89b6ed-17ac-cca5-8c17-e0bc2baf9dc1.png)

## 環境変数を設定

インストールした各binにパスを通します。自分の場合は以下のディレクトリを`PATH`に設定しました。

- C:\Users\hogehoge\mingw64\bin
- C:\Program Files (x86)\GnuWin32\bin
- C:\Program Files\CMake\bin

## OpenCVのソースコード入手

直接ダウンロードするか、GitHubからcloneするかしてソースコードを適当なディレクトリに配置する。自分の場合は「Sources」からダウンロードしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/dba55142-57b1-2881-f340-b1a3d36ef5f8.png)

## buildディレクトリを作る

ソースディレクトリ内に`build`ディレクトリを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/c0bc0121-6fb5-b164-b919-77ee5fdadf8a.png)

## cmake

CmakeGUIを開き、まずconfigureを行います。

CmakeGUIの「Where is the source code」にダウンロードしたOpenCVのトップディレクトリを指定します。次に、「Where to build the binaries」にOpenCVのトップディレクトリの下の`build`ディレクトリを指定します。最後に、Configureボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/2abbaf48-f399-1cff-3d89-d4b48957590f.png)

どのジェネレータを使用するか問われるので、「MinGW Makefiles」を指定し、Finishを押すとconfigureが走るので、しばらく待ちます（コンソール画面にエラーメッセージのようなものがチラチラ見えますが問題ないです）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/4dc1071d-1265-18de-7f18-59d6347f09a0.png)

## cmakeパラメータ設定

configureが終わると中央の表に赤い項目が沢山並びます。ここを1つずつ確認しながら、パラメータを決めていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/11f4611f-79cd-966f-a501-7027c76911d5.png)

自分の場合は、Javaは不要だったので`BUILD_JAVA`を外すなどしました。

## DOPENCV_ALLOCATOR_STATS_COUNTER_TYPEを追加

**ここが重要です。**「Add Entry」ボタンを押すと任意のパラメータを設定できるので、以下項目を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/e8d14d64-f03b-a045-e9d1-bf144205c5de.png)

- Name： DOPENCV_ALLOCATOR_STATS_COUNTER_TYPE
- Type： STRING
- Value： int64_t

参考
https://github.com/opencv/opencv/issues/16990

完了したら、再度「Configure」を押したあと、「Generate」でMakeFileを生成します。

## make

`build`ディレクトリにMakefileが生成されていることを確認し、ターミナルを開いてmakeを実行します。

```
make
make install
```

すべてエラーなく終了したら、ビルドは完了です。`build/install/`にincludeとlibがインストールされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/bec16712-c9b0-0e89-514c-e780fdbd600d.png)

# 動作確認

## 環境変数

以下の2つを`PATH`に追加しておきます。1つめの`bin`を登録しておくことで、実行時に必要なdll（`libopencv_world490.dll`など）をOSが見つけられるようになります。また2つめの`lib`を登録しておくことで、cmakeが`find_package`でOpenCVを検索できるようになります。

- `...\opencv-4.9.0\build\install\x64\mingw\bin`
- `...\opencv-4.9.0\build\install\x64\mingw\lib`

## 開発プロジェクトを作る

以下のディレクトリ構成で`opencv_test`プロジェクトを準備します。

```
opencv_test
├─src
│  └─main.cpp
├─build
└─CMakeLists.txt
```

## CMakeLists.txtを作成

```cmake
cmake_minimum_required(VERSION 3.21)
project(opencv_test CXX)

find_package(OpenCV REQUIRED)

file(GLOB MY_SOURCE src/*)

add_executable(${PROJECT_NAME} ${MY_SOURCE})

target_include_directories(
    ${PROJECT_NAME}
    PRIVATE
    ${OpenCV_INCLUDE_DIRS}
)

target_link_libraries(
    ${PROJECT_NAME}
    PRIVATE
    ${OpenCV_LIBS}
)
```

`find_package`で利用可能になるOpenCVの変数`${OpenCV_INCLUDE_DIRS}`や`${OpenCV_LIBS}`がわからなくなった場合は、`OpenCVConfig.cmake`の中を読めば一覧を確認できます。

```cmake
・・・（略）・・・
#    This file will define the following variables:
#      - OpenCV_LIBS                     : The list of all imported targets for OpenCV modules.
#      - OpenCV_INCLUDE_DIRS             : The OpenCV include directories.
#      - OpenCV_COMPUTE_CAPABILITIES     : The version of compute capability.
#      - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API.
#      - OpenCV_VERSION                  : The version of this OpenCV build: "4.9.0"
#      - OpenCV_VERSION_MAJOR            : Major version part of OpenCV_VERSION: "4"
#      - OpenCV_VERSION_MINOR            : Minor version part of OpenCV_VERSION: "9"
#      - OpenCV_VERSION_PATCH            : Patch version part of OpenCV_VERSION: "0"
#      - OpenCV_VERSION_STATUS           : Development status of this build: ""
・・・（略）・・・
```

## main.cppを作成

https://docs.opencv.org/3.0-beta/modules/videoio/doc/reading_and_writing_video.html

上記サンプルをそのままコピペして、USBカメラから`videoio`を使って画像を取得し、エッジ検出した結果を描画するプログラムを作ってみます。

```cpp
#include "opencv2/opencv.hpp"

using namespace cv;

int main(int, char**)
{
    VideoCapture cap(0); // open the default camera
    if(!cap.isOpened())  // check if we succeeded
        return -1;

    Mat edges;
    namedWindow("edges",1);
    for(;;)
    {
        Mat frame;
        cap >> frame; // get a new frame from camera
        cvtColor(frame, edges, COLOR_BGR2GRAY);
        GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
        Canny(edges, edges, 0, 30, 3);
        imshow("edges", edges);
        if(waitKey(30) >= 0) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}
```

## ビルド＆実行

```
cd build
cmake .. -G "MinGW Makefiles"    # -GでジェネレータにMinGWを指定しないとエラーになる
make
.\opencv_test.exe
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3302427/96817a4e-48cf-917c-1f62-c42fa19da1d0.png)

できた！！