Windows10でGoCVの環境構築

OpenCVを用いた録画ソフトを作ろうと思い立ちました。PythonでOpenCVを使ってプログラムを書く場合はpipでインストールするだけで割と簡単に導入できるのですが、今回はクロスコンパイルが可能なことに魅力を感じgo言語で書くことにしました。

Go言語では直接OpenCVを使用することはできないのですが、その代わりGoCVというものが利用できます。あまり詳細に理解してはいませんが、当初の私は「GoCV = OpenCVのGo言語版！」と言う認識でしたが、そうではなく「Go言語からOpenCVを使用できるようにしたラッパー」なようです。従ってGoCVをダウンロードするだけでなく、OpenCVそのものをソースコードからビルドして配置する必要があります。

Windows10 Home環境でGoCVの環境構築を行いましたが、主にOpenCVをソースビルドするために必要なコンポーネントである`MINGW-64`のバージョン選定に伴ってかなりハマりました。



# 環境
今回は`Parallels Desktop 19`を使ってMacBook Pro上に仮想マシンとしてWindows 10 Homeを用意した環境下で管渠構築を行っています。

- Windown 10 Home (Parallels Desktop 19 for mac Pro Edition) 64bit

# 環境構築完了後の各コンポーネントのバージョン

GoCVを使えるようにするには最低限下記のコンポーネントが必要です。先に、**最終的にGoCVが使えるようになった時点での各コンポーネントのバージョン情報**を下記に記載します。

- `Go` : go1.21.5 windows/amd64 (2024/1/1 時点最新)
- `CMake` : 3.28.1 (2024/1/1 時点最新)
- `MinGW-64`の`gcc`バージョン : 8.1.0
- `GoCV` : v0.35.0 (2024/1/1 時点最新)
  - `GoCV` v0.35.0 がサポートしている `OpenCV` のバージョンは4.8.1です 


# 環境構築手順

まず過去の自分に言ってあげたいこととしては **公式の提供しているビルド手順をちゃんと読め** ということです。GoCVの環境構築手順を紹介してくださっている記事もいくつかありましたが、記事の執筆時期が結構過去であったりするので`MinGW-64`などのコンポーネントのバージョン情報が微妙に合わずなかなかうまくいかないことが多かったです。**じゃあどこを読んで参考にすればいいの?** ということについての私なりの答えは **ダウンロードしてきたGoCVプロジェクトの中にあるReadme** です。後ほど説明します。

環境構築の手順は下記です。

1. Goのインストール
1. GoCVのダウンロード
1. MinGW-64のインストール
1. CMakeのインストール
1. OpenCVのビルド 
1. GoCVの動作確認 (サンプルコードの実行)

## Goのインストール

これは下記の記事を参考にどうぞ。GoSDKをインストールします

https://qiita.com/suke_masa/items/0c45c92934b9a2807ddb

今回は2024/1/1時点で最新のgoバージョンである`1.21.5`がインストールされました。インストールの際に環境変数へのPathは自動的に設定されるはずです。コマンドプロンプトを開き`go version`を実行します。下記の通りバージョン情報が表示されればインストールが完了しています。

```
> go version
go version go1.21.5 windows/amd64
```

## GoCVのダウンロード

まず適当な場所で(もし作業用ディレクトリを決めて入ればそこで)下記のコマンドを実行します。これにより今いるディレクトリ内にgo.modファイルが生成されます。これ自体にあまり意味は無いですが、後の`go get`を実行する上で必要です。

```
go mod init <好きな文字列>
```

この後に`go get -u -d gocv.io/x/gocv`を叩くとgocvのプロジェクトフォルダ一式がダウンロードされます。今いるディレクトリ内に go.mod ファイルが存在しなければ「go.modがないよ！」とエラーが出るはずです。

```
> go get -u -d gocv.io/x/gocv
go: downloading gocv.io/x/gocv v0.35.0
go: added gocv.io/x/gocv v0.35.0
```

では一体どこにダウンロードされるのか？と言うと`<GOPATH>\pkg\mod\gocv.io\x\gocv@v0.35.0`です。ここで`<GOPATH>`はGO言語のインストール時に設定され、前述したインストール時に何も意識しなければ `C:\Users\<ユーザ名>\go`になります。実際に`<GOPATH>`を確認したい場合は`go env`コマンドで確認できます。またパスの最後の`gocv@v0.35.0`は、ダウンロードしたGoCVのバージョンによって変わります。2024/1/1現在では0.35.0が最新でした。

```
> go env
・
・
（色々とGoに関する変数が表示される）
・
・
set GOPATH=C:\Users\hogehoge\go  # ココを確認する
・
・
・
```

この後最も重要なのはココです。ダウンロードしたGoCVのフォルダ(`<GOPATH>\pkg\mod\gocv.io\x\gocv@v0.35.0`)をファイルエクスプローラで開きます。その中に`Readme.md`があります。この中の`Windows`のセクションに**環境構築の方法や手順が明記されています**。これに従って作業をするとスムーズに環境構築ができるはずです。

...とココで記事を終わってしまうのはアレなので、それを踏まえて手順を説明してきます。



## CMakeのインストール

下記のリンクから Windowsのx64用のインストーラ `cmake-3.28.1-windows-x86_64.msi` (2024/1/1時点最新) をダウンロードします。おそらくCMakeのバージョンは神経質になる必要はないので、とりあえず最新版をインストールしました。

https://cmake.org/download/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/0c264195-d4eb-013c-54f7-c64f92419c64.png)

ダウンロードしたインストーラをダブルクリックで実行します。インストール中は基本デフォルトの設定でインストールを進めていきますが、途中「CMakeへのパスをシステム環境変数に追加するか」のチェックボックスがあるのでチェックしておきましょう（デフォルトは「パスを追加しない」にチェックがついている）。もしここでチェックし損ねても後で追加すればOKです。

一応下記のコマンドでCMakeが正常にインストールされていることと、パスが通っていることを確認しておきます。

```
>cmake --version
cmake version 3.28.1

CMake suite maintained and supported by Kitware (kitware.com/cmake).
```


## MinGW-64のインストール (どハマりポイント)

**ここが一番ハマりました「インストールするMinGWのバージョンなんてなんでもええやろ！」と思ってたらかなりハマりました。。。適当なMinGW-64をインストールしてしまうとOpenCVのビルド時にエラーが発生します。**

下記のSourceforgeのサイトから **MinGW-W64 GCC-8.1.0** から **x86-64-posix-seh** をダウンロードしてください。**x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z** という圧縮ファイルがダウンロードされます。

https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/8.1.0/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/e9cb0874-d43d-3d4f-6dc6-318e1516e259.png)

ダウンロードした圧縮ファイルを回答します。解凍するためにはフリーソフトの`7zip`のインストールが必要ですので、下記からダウンロード＆インストールしてください。

https://7-zip.opensource.jp

解凍後のフォルダをまるごと`C:\Program Files` 上にコピーして配置します。インストール自体はこれで完了です。この後、Windowsのシステム環境変数`Path`に`C:\Program Files\mingw64\bin`を新規追加します（このパスの値は解凍後のフォルダ名などに合わせて変更してください）。

この状態で下記のコマンドを叩いてgccのバージョンが 8.1.0 であればOKです。もしバージョン表示がされなかった場合はパスが正しく通ってないかもしれないので確認してください。

```
>gcc --version
gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```

### 【備忘録】 筆者が一体どこでどハマりしたのか

Readmeをロクに読もせず（というか存在を知らなかった）で推奨されているバージョンのMINGW-64ではなく、適当に[ココ](https://github.com/niXman/mingw-builds-binaries/releases)から最新版のMinGW-64をインストールすると、後段のOpenCVのビルドの段階でものすんごくエラーが出ます。`GCC-12.2.0`, `GCC-13.2.0`でOpenCVをビルドすると下記のようなエラーが発生してビルドが完了しませんでした。


```
C:\opencv\opencv-4.8.1\modules\videoio\src\cap_obsensor\obsensor_stream_channel_msmf.hpp:129:7: warning: base class 'struct IMFSourceReaderCallback' has accessible non-virtual destructor [-Wnon-virtual-dtor]
  129 | class MSMFStreamChannel : public IUvcStreamChannel, public IMFSourceReaderCallback
      |       ^~~~~~~~~~~~~~~~~
mingw32-make[2]: *** [modules\videoio\CMakeFiles\opencv_videoio.dir\build.make:241: modules/videoio/CMakeFiles/opencv_videoio.dir/src/cap_obsensor/obsensor_uvc_stream_channel.cpp.obj] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:4574: modules/videoio/CMakeFiles/opencv_videoio.dir/all] Error 2
mingw32-make: *** [Makefile:165: all] Error 2

C:\opencv\build>rmdir c:\opencv\opencv-4.8.1 /s /q 

C:\opencv\build>rmdir c:\opencv\opencv_contrib-4.8.1 /s /q 
```
また、これはその後にハマったのですが [GoCVの公式ページ](https://gocv.io/getting-started/windows/)ではMinGW-64のインストールについて下記のような記載があります。ここでは`GCC-7.3.0`をインストールするように指示があります。 

```
MinGW-W64

Download and run the MinGW-W64 compiler installer from https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/7.3.0/.

The latest version of the MinGW-W64 toolchain is 7.3.0, but any version from 7.X on should work.

Choose the options for “posix” threads, and for “seh” exceptions handling, then install to the default location c:\Program Files\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev2.

Add the C:\Program Files\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev2\mingw64\bin path to your System Path.
```

しかし**私の環境ではこの状態でOpenCVのビルドをするとエラーが発生しました。** 上述の手順でダウンロードしたGoCVフォルダにあるReadme.mdでは`8.1.0`をインストールするよう指示があったため、おそらく公式ページがメンテされてないのでしょう。具体的には下記のようなエラーです。

```
In file included from C:\opencv\opencv-4.8.1\3rdparty\protobuf\src\google\protobuf\arena.cc:42:0:
C:/opencv/opencv-4.8.1/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h: In constructor 'constexpr google::protobuf::internal::WrappedMutex::WrappedMutex()':
C:/opencv/opencv-4.8.1/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:124:29: error: temporary of non-literal type 'google::protobuf::internal::CallOnceInitializedMutex<std::mutex>' in a constant expression
   constexpr WrappedMutex() {}
                             ^
C:/opencv/opencv-4.8.1/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:98:7: note: 'google::protobuf::internal::CallOnceInitializedMutex<std::mutex>' is not literal because:
 class CallOnceInitializedMutex {
       ^~~~~~~~~~~~~~~~~~~~~~~~
C:/opencv/opencv-4.8.1/3rdparty/protobuf/src/google/protobuf/stubs/mutex.h:98:7: note:   'google::protobuf::internal::CallOnceInitializedMutex<std::mutex>' has a non-trivial destructor
mingw32-make[2]: *** [3rdparty\protobuf\CMakeFiles\libprotobuf.dir\build.make:91: 3rdparty/protobuf/CMakeFiles/libprotobuf.dir/src/google/protobuf/arena.cc.obj] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:3567: 3rdparty/protobuf/CMakeFiles/libprotobuf.dir/all] Error 2
mingw32-make[1]: *** Waiting for unfinished jobs....
mingw32-make: *** [Makefile:165: all] Error 2
```

どうやらこれは既知の不具合らしく、下記の記事によると、インストールしたgccバージョンが7.3以下の場合上記エラーが発生するらしいです、そのためここでも`8.1.0`以上を使用することが推奨されています。

https://www.appsloveworld.com/cplus/100/669/c-protocol-buffer-temporary-of-non-literal-type-googleprotobufinternalc




## OpenCVのソースのビルド 

ダウンロードしたGoCVのフォルダ(`<GOPATH>\pkg\mod\gocv.io\x\gocv@v0.35.0`)をファイルエクスプローラーで開き`win_build_opencv.cmd`をダブルクリックで実行します。このバッチファイルでは OpenCV-4.8.1 (2024/1/1現在) のソースをダウンロード＆解凍し、ソースコードのビルドを実行するように組まれています。ビルドの完了には1時間程度を要します。


ダブルクリックでの実行もできますが、筆者のおすすめはコマンドプロンプトを開いてGoCVフォルダに移動し`win_build_opencv.cmd > log.txt 2>&1`という形で実行することを強く推奨します。ダブルクリックで実行するとビルドがエラーで中断したときにウインドウが勝手に閉じてしまうため、何が原因でビルドが失敗したかの状況証拠が綺麗さっぱり消えてしまういます。更にビルドが完了したときにも勝手にウインドウが閉じるので、ビルドが正常に完了したかも確認しづらいです。

### ビルドの完了確認

ビルド中に結構な量のwarningが出ますが、最後までビルドが止まらず完了すればひとまずOKです。もし途中でビルドが失敗していればビルドパーセンテージが100%まで上がらず、`mingw32-make: *** [Makefile:165: all] Error 2`のようなエラーが記録されているはずです。下記のような出力がされていれば最後までビルドが通っています。


```
・
・
・
-- Installing: C:/opencv/build/install/etc/lbpcascades/lbpcascade_frontalface.xml
-- Installing: C:/opencv/build/install/etc/lbpcascades/lbpcascade_frontalface_improved.xml
-- Installing: C:/opencv/build/install/etc/lbpcascades/lbpcascade_profileface.xml
-- Installing: C:/opencv/build/install/etc/lbpcascades/lbpcascade_silverware.xml
-- Installing: C:/opencv/build/install/x64/mingw/bin/opencv_annotation.exe
-- Installing: C:/opencv/build/install/x64/mingw/bin/opencv_visualisation.exe
-- Installing: C:/opencv/build/install/x64/mingw/bin/opencv_interactive-calibration.exe
-- Installing: C:/opencv/build/install/x64/mingw/bin/opencv_version.exe
-- Installing: C:/opencv/build/install/x64/mingw/bin/opencv_version_win32.exe
-- Installing: C:/opencv/build/install/x64/mingw/bin/opencv_model_diagnostics.exe

C:\opencv\build>rmdir c:\opencv\opencv-4.8.1 /s /q 

C:\opencv\build>rmdir c:\opencv\opencv_contrib-4.8.1 /s /q 

C:\opencv\build>chdir /D C:\Users\hogehoge\go\src\gocv.io\x\gocv 

```

またビルド完了後は`C:\opencv\build\`にビルド後の成果物が出力されています。`C:\opencv\build\install\x64\mingw\bin`の配下に大量の `.dll` ファイルが出力されていればOKです。もしビルドに失敗していればそもそも`C:\opencv\build\install\x64\mingw\bin`のフォルダが存在しない状況になっています。

### OpenCVへのパスを通す

Windowsのシステム環境変数`Path`に`C:\opencv\build\install\x64\mingw\bin`を追加してください。






## GoCVのサンプルコードの実行

### gocvのバージョン表示用サンプル

`C:Users\hogehoge\go\src\gocv.io\x\gocv\cmd\version`に移動し、バージョン表示用のサンプルコードを実行する。なぜか初回は不安になるくらい表示までに時間がかかるが、下記のようにバージョンが表示されればOK。

```
> go run main.go
gocv version: 0.35.0
opencv lib version: 4.8.1
```
### カメラ映像表示用サンプル

`C:Users\hogehoge\go\src\gocv.io\x\gocv\cmd\hello`に移動し、サンプルコードを実行する。

```
> go run main.go
```

下記の画像のように`Hello`というタイトルのダイアログでカメラから取得した映像が表示されていればOK。ちなみに終了するときはコマンドプロンプト上で`Ctrl+C`を入力する必要がある。

![スクリーンショット 2023-12-17 004258.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290256/498c0a89-19ee-c53c-2532-10e853709578.png)



ここまでできれば環境構築は完了です！