Go言語を使用して、RaspberryPiのカメラを操作する。

# はじめに
Go言語でカメラ操作するプログラムを作りたかったので、調べてみた。
Go言語でOpenCVのライブラリーを使用すれば、操作できそうなので、そのライブラリをインストールしてテストする
あと、テスト環境は以下の通り

||名称|
|--|--|
|本体|RaspberryPi4 8G|
|OS|Raspberrypi OS 64bit|

# OpenCVのインストール
調べていたら、32bitのRaspberryPi OSではうまくいかなかったので、64bitのやり方だと以下の通りになる

```:bash
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.5.3.zip
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.5.3.zip

unzip opencv.zip
unzip opencv_contrib.zip
mv opencv-4.5.3 opencv
mv opencv_contrib-4.5.3 opencv_contrib

rm opencv.zip
rm opencv_contrib.zip

cd ~/opencv
mkdir build
cd build

cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
-D ENABLE_NEON=ON \
-D WITH_OPENMP=ON \
-D WITH_OPENCL=OFF \
-D BUILD_TIFF=ON \
-D WITH_FFMPEG=ON \
-D WITH_TBB=ON \
-D BUILD_TBB=ON \
-D WITH_GSTREAMER=OFF \
-D BUILD_TESTS=OFF \
-D WITH_EIGEN=OFF \
-D WITH_V4L=ON \
-D WITH_LIBV4L=ON \
-D WITH_VTK=OFF \
-D WITH_QT=OFF \
-D OPENCV_ENABLE_NONFREE=ON \
-D INSTALL_C_EXAMPLES=OFF \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D BUILD_opencv_python3=TRUE \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D BUILD_EXAMPLES=OFF ..

make -j4

sudo make install
sudo ldconfig
```

インストール後以下のファイルを作成する

```bash
sudo mkdir -p /user/local/lib/pkgconfig
sudo vi /usr/local/lib/pkgconfig/opencv4.pc
```

```:/usr/local/lib/pkgconfig/opencv4.pc
prefix=/usr/local
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib

Name: opencv4
Description: The opencv library
Version: 4.0.0
Cflags: -I${includedir}/opencv4
Libs: -L${libdir} -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_calib3d -lopencv_ccalib -lopencv_core -lopencv_datasets -lopencv_dnn -lopencv_dnn_objdetect -lopencv_dpm -lopencv_face -lopencv_features2d -lopencv_flann -lopencv_fuzzy -lopencv_gapi -lopencv_hfs -lopencv_highgui -lopencv_img_hash -lopencv_imgcodecs -lopencv_imgproc -lopencv_line_descriptor -lopencv_ml -lopencv_objdetect -lopencv_optflow -lopencv_phase_unwrapping -lopencv_photo -lopencv_plot -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_shape -lopencv_stereo -lopencv_stitching -lopencv_structured_light -lopencv_superres -lopencv_surface_matching -lopencv_text -lopencv_tracking -lopencv_video -lopencv_videoio -lopencv_videostab -lopencv_xfeatures2d -lopencv_ximgproc -lopencv_xobjdetect -lopencv_xphoto
```
以下のコマンドを起動時に実行するようにする。`~/.bashrc`

```bash
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH"
```


# Go言語のプログラムを作る
[キャプチャテスト用のサンプルコード](https://github.com/hybridgroup/gocv/blob/release/cmd/captest/main.go)をベースにちょっといじった

```go:main.go
package main

import (
	"fmt"
	"os"

	"gocv.io/x/gocv"
)

func imagesnap(deviceID, saveFile string, webcam *gocv.VideoCapture) {
	img := gocv.NewMat()
	defer img.Close()

	if ok := webcam.Read(&img); !ok {
		fmt.Printf("cannot read device %v\n", deviceID)
		return
	}
	if img.Empty() {
		fmt.Printf("no image on device %v\n", deviceID)
		return
	}

	gocv.IMWrite(saveFile, img)
}

func main() {
	if len(os.Args) < 3 {
		fmt.Println("How to run:\n\tsaveimage [camera ID] [image file]")
		return
	}

	deviceID := os.Args[1]
	saveFile := os.Args[2]

	webcam, err := gocv.OpenVideoCapture(deviceID)
	if err != nil {
		fmt.Printf("Error opening video capture device: %v\n", deviceID)
		return
	}
	defer webcam.Close()
	imagesnap(deviceID, saveFile, webcam)

}
```
以下のコマンドで初期化

```
go mod init camera
go mod tiddy
```

ライブラリーの追加

```
go get gocv.io/x/gocv
```

以下のコマンドでビルドをする

```
go build ./
```

`./camera 0 test.jpg`で写真が撮れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425374/d51b5daf-e130-cc00-3d45-900c15df5e00.png)

# おわりに
とりあえず、raspberypi4 64bit OS上で、カメラで写真を撮るだけのプログラムがかけた。
また、サンプルには、カメラ動画を配信するためのプログラムも作れる
これから、センサーと組み合わせて写真を撮ったり、色々と遊ぶ予定


# 参考サイト
[Install OpenCV 4.3.0 on Raspberry 64 OS
](https://qengineering.eu/install-opencv-4.3-on-raspberry-64-os.html)
[GoCV](https://gocv.io/computer-vision/)