M1 MacBook AirでOpenCVをビルドする

#はじめに
M1のMacにてARM64ネイティブでOpencvを利用するため、OpenCV（contribも）のソースコードを取得しビルド、簡単な画像処理のコードを走らせるまでをまとめます。

#環境
* マシン： MacBook Air (M1 / RAM 16GB / SSD 512GB)
* OS： macOS Big Sur 11.1

#やること
* 開発環境の準備
* OpenCVソースコードのダウンロード
* CMake.appでOpenCVのビルド環境の生成
* ビルド→インストール
* テストプログラムの実行

#開発環境の準備
OpenCVをビルドするため、次のソフトをインストール。
* [XCode](https://apps.apple.com/jp/app/xcode/id497799835?mt=12)
* [CMake](https://cmake.org/download/)　執筆時点では[cmake-3.19.2-macos-universal.dmg](https://github.com/Kitware/CMake/releases/download/v3.19.2/cmake-3.19.2-macos-universal.dmg)。

#OpenCVソースコードのダウンロード
OpenCVとOpenCV contribのソースコードをGitHubから取得。執筆時点ではver.4.5.1。

```Console:
$ mkdir ~/src
$ cd ~/src
$ mkdir _GitHub
$ cd _GitHub
$ git clone https://github.com/opencv/opencv.git
$ git clone https://github.com/opencv/opencv_contrib.git
$ cd opencv
$ mkdir build
```
#CMakeでビルド環境を生成
CMake.Appを立ち上げ、OpenCVのCMakeLists.txtがあるフォルダと、先ほど作ったbuildフォルダを指定。
![CMake1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355045/e3f02633-73bf-da61-94a2-0f9c62b5a852.png)
Configureボタンを押して、
* 生成するプロジェクト:「Unix Makefiles」
* コンパイラ:「Use default native compilers」
を選択。
![specify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355045/0b9f798f-be97-a111-da7e-03a510922213.png)
赤く表示される項目のうち、次を設定。
* OPENCV_EXTRA_MODULES_PATH： ~/src/_GitHub/opencv_contrib/modules
再びConfigureボタンを押す。赤い表示が無くなったら、Generateボタンを押してMakefileを生成。

#ビルド→インストール
buildフォルダに移動し、makeを実行。ビルドにかかる時間は約10分。
__ここで「make -j」とすると、SWAPが16GBくらいになり、途中でビルドがほぼ止まってしまうので注意。__

```Console:
$ cd ~/src/_GitHub/opencv/build
$ make -j4
```
ビルドが無事に終わったら、インストールを行う。

```Console:
$ sudo make install
```
（2021.01.04 追記）ビルドされたライブラリはARM64。

```Console:
$ file /usr/local/lib/libopencv_world.4.5.1.dylib 
/usr/local/lib/libopencv_world.4.5.1.dylib: Mach-O 64-bit dynamically linked shared library arm64
```

#テストプログラムの実行
##プログラム作成
簡単な２値化処理のプログラムを作成する。cmakeを使うのが何かと便利なので、main.cppと同じフォルダにCMakeLists.txtを作る。

```C++:main.cpp
#include <opencv2/opencv.hpp>
#include <chrono>

int main(int argc, char** argv) {
    cv::Mat img, imgThr;

    img = cv::imread(argv[1]);
    imgThr = cv::Mat(img.size(), img.type());

    cv::threshold(img,imgThr, 128,255,cv::THRESH_BINARY);

    cv::imshow("result", imgThr);
    cv::waitKey(0);

    return 0;
}
```

```CMAKELists:CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(OpenCvTest)

# Create Main project
set(SOURCES
    main.cpp
)

find_package(OpenCV REQUIRED) ##Load OpenCV environment
 
##OpenCV include paths
include_directories(
    ${OpenCV_INCLUDE_DIRS}
)
 
##executable name
add_executable(
    ${PROJECT_NAME} ${SOURCES}
)
 
##Library linkage
target_link_libraries(
    ${PROJECT_NAME} ${OpenCV_LIBRARIES}
)

```
##ビルド
main.cppと同じフォルダで以下のコマンドを実行。
cmakeがあるフォルダにパスを通してないので、フルパスで指定する。

```Console:
$ mkdir build
$ cd build
$ /Applications/CMake.app/Contents/bin/cmake ..
$ make
```
（2021.01.04 追記）ビルドされたアプリはARM64。

```Console:
$ file ./OpenCvTest              
src/OCVtest/build/OpenCvTest: Mach-O 64-bit executable arm64
```

##プログラム実行

```Console:
$ ./OpenCvTest ../lena_std.tif
```
![lena_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355045/8d472a2c-1db5-b898-1451-09ec8367d0c3.png)