Jetson Xavier NXの使い始め(初期セットアップ～OpenCVインストール～ひとまずUSBカメラ)

昨年春から、Jetson Nano開発者キットを使用して来ましたが、今回、同じくNVIDIAのJetsonシリーズで、その上位版と言えるJetson Xavier NXを購入してみました。

![IMG20210908083718.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/998321/09d172df-03a4-8367-0a73-352893223ba3.jpeg)


セットアップしましたというだけでは面白くないですし、折角、上位機種を購入したということで、そのパフォーマンスを感じてみたいということで、ひとまず、OpenCVをインストールして、USBカメラでも使って画像表示するぐらいまでをやってみて、この記事にまとめようと思います。

## 初期セットアップ

SDK Managerによるセットアップもあるが、microSDカードを用いたセットアップ方法をさらっと紹介する。

https://developer.nvidia.com/embedded/learn/get-started-jetson-xavier-nx-devkit

に従って、まず、セットアップ用のSDイメージをmicroSDカードに書き込み、それを開発者キットのSDカードスロットに挿入し、初めての電源投入を行って起動し、初期セットアップを行う。
(Windows環境にて)

### 最新のSDカードイメージをダウンロード

https://developer.nvidia.com/jetson-nx-developer-kit-sd-card-image

### SDカードのフォーマットとイメージの書き込み

Write Image to the microSD Cardの2.に従って、定番のSD Card Formatter を用いてSDカードをフォーマットし、Etcherというツールで、ダウンロードしておいたイメージをSDカードに書き込む。

### 初めてのブートとセットアップ

SDカードを、開発者キットのカードスロットに挿入し(Jetson Nanoよりもちょっと入れにくいような気が...)、USBキーボードのUSBドングルも挿入し、ディスプレイに接続されているHDMIケーブルも挿入した上で、ACアダプタ(Jetson Nanoでは別途購入しないといけなかったがXavier NXでは標準でついてくる)から電源を投入する。

初めてのブートからの初期セットアップは、画面に従って実施していけばよい。

その後は、、、NVIDIA DeveloperサイトのGetting Started With Jetson Xavier NX Developer Kitのページでは、

<b>Next Steps
Find Your Way Around</b>

* Read the Jetson Xavier NX Developer Kit User Guide, which includes:
    + Many more details about the developer kit hardware
    + Overview of NVIDIA JetPack, including developer tools with support for cross-compilation
    + Lists of all included samples and sample documentation

* Head to the NVIDIA Jetson Developer site for access to all Jetson platform information.
* Ask questions or share a project on the NVIDIA Jetson Forums.

という記述で終わっている。

初期セットアップ時に日本や日本語を選択し、今後、日本語メインで使いたいならば、日本語環境をセットアップしておくべきだろう。

画面右上の歯車アイコンから、

System Settings... → Language Support

を選択すると、「言語サポートが完全にはインストールされていません」などと
インストールを促されるので、そこで、インストールボタンを押す。

ここで、リブートする必要あり。リブートしないと、下記の入力ソースがリストに現れない。

リブートすると、確か、メニューなども日本語に切り替わったかと思うので、
また、右上歯車アイコンから、

システム設定... → テキスト入力設定

から、＋ボタンを押して、「追加する入力ソースを選択」から、「日本語
(Mozc)(IBus)」を選択して追加。これで、キー「半角/全角」が効くようになる。

## OpenCVのインストール

Xavier NXにOpenCV最新版をインストールしてみる。 Jetson Nanoでも、いっとき、OpenCVをセットアップして、カメラから得られる画像に対して画像処理するテスト動作まではやってみていた。今回、Xavier NXを購入したことを契機に、せっかくパフォーマンスが高いXavier NXなので、それを活かしてみたい、というところ。

NVIDIAのJetsonシリーズを折角使うので、NVIDIAのGPU (CUDA)を使いたい。 折角のOpenCVの環境なのに、内部的にCPUでしか処理されていない、っていうのはもったいない。 ということで、CUDAを使用するOpenCVをセットアップして使用する。

### OpenCVをソースコードからインストール

上で書いた、Jetson NanoでのOpenCVのセットアップでも参考にした、以下のサイトで公開されているスクリプトを使用する。

https://github.com/AastaNV/JEP/tree/master/script

他にも参考にできそうなサイトはあったが、OpenCVのバージョンも4.5.0と新しいし、更新は2020年12月、NVIDIAのコピーライトもあるので、こちらに準じておく。

install_opencv4.5.0_Jetson.shの中を再確認すると、インストール時のステップとしては、

 * OpenCVに必要なもの一式のインストール
 * OpenCV最新版のダウンロード(ソースコード一式)
 * ビルド(cmakeから)
 * インストール

というところ。

現在のOpenCVの最新版は4.5.3のようなので、折角なので、スクリプト内で定義されているversionを4.5.3と編集して実行。

結構時間がかかった。途中で、sudoのためか、パスワードを聞かれたぐらいか。最後に、

```
** Install opencv-4.5.3 successfully
** Bye :)
```

### インストール後の確認

ひとまず、ネット上でよくみられる、Pythonの環境で、ビルド時の情報を表示して確認する方法を紹介する。

```
$ python3 -c 'import cv2; print(cv2.getBuildInformation())' |grep NVIDIA
  NVIDIA CUDA:                   YES (ver 10.2, CUFFT CUBLAS)
    NVIDIA GPU arch:             53 62 72
    NVIDIA PTX archs:
```

## ひとまずUSBカメラを使ってみる

Windows PCでも時々使用しているUSBカメラを、Xavier NXのUSBポートに接続してみると、無事、/dev/video0が出現。cheeseアプリを実行してみると、問題なく、カメラから得られるリアルタイムな画像が表示された。

### まずは簡単なPythonのプログラムで

どこかから拾って来た簡単なPythonのプログラムを動かしてみる。

```
import cv2

capture = cv2.VideoCapture(0)
if capture.isOpened() is False:
  raise IOError

while(True):
  try:
    ret, frame = capture.read()
    if ret is False:
      raise IOError
    cv2.imshow('frame',frame)
    cv2.waitKey(1)
  except KeyboardInterrupt:
    # 終わるときは CTRL + C を押す
    break

capture.release()
cv2.destroyAllWindows()
```

### Cのプログラムでも

C++のプログラムでも、以下のようなものを用意して動かしてみた。

```
#include "opencv2/opencv.hpp"
#include "opencv2/core/utils/logger.hpp"

using namespace cv;

int main(int argh, char* argv[])
{
  //cv::VideoCapture cap(1);//デバイスのオープン
  //cap.open(0);//こっちでも良い．
  //cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_VERBOSE);
  cv::VideoCapture cap(0);//デバイスのオープン

  //cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
  //cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);
  //cap.set(cv::CAP_PROP_FPS, 10.0);
  
  //cap.set(cv::CAP_PROP_CONVERT_RGB, 0);

  if(!cap.isOpened()) {//カメラデバイスが正常にオープンしたか確認．
    //読み込みに失敗したときの処理
    return -1;
  }

  int width = cap.get(cv::CAP_PROP_FRAME_WIDTH);
  int height = cap.get(cv::CAP_PROP_FRAME_HEIGHT);
  int fps = cap.get(cv::CAP_PROP_FPS);
  
  std::cout << "VideoCapture is opened." << std::endl;

  //std::cout < "Width x Height = " << width << " x " << height << "\n";
  //printf("WIdth x Height = %d x %d\n", width, height);
  printf("WIdth x Height = %d x %d, fps = %d\n", width, height, fps);
  
  cv::Mat frame; //取得したフレーム

  while(cap.read(frame)) { //無限ループ
    cv::imshow("win", frame);//画像を表示．
    const int key = cv::waitKey(1);
    if (key == 'q'/*113*/) {//qボタンが押されたとき
      std::cout << "dims: " << frame.dims << ", depth(byte/channel): " << frame.elemSize1() << ", channels: " << frame.channels() << std::endl;
      break;//whileループから抜ける．
    } else if(key == 's'/*115*/) { //sが押されたとき
      //フレーム画像を保存する．
      cv::imwrite("img.bmp", frame);
    }
  }
  
  cv::destroyAllWindows();
  
  return 0;
}
```

LD_LIBRARY_PATHに/usr/local/libが設定されていない場合は設定する。
あと、

```
g++ sample.cpp `pkg-config --cflags --libs opencv4` -o sample
```

などとすれば、指定すべきオプションを実行時に取得できる。

<details><summary>昔話</summary><div>私が、大昔に、X11R5とかX ToolkitとかMotifとかでXプログラミングしていた頃は、自分で、Makefile内に、-Lとか-Iオプションを沢山記述していた。。。昔話を思い出したので書いてしまった。。。今や、これほどハイパフォーマンスなJetsonシリーズを組み込みに使用するという時代。動的に実行する必要がないことは、事前にやっておく、という、組み込みシステムならば当たり前の考え方が、もはや。。。</div></details>

## おわりに

ひとまず、Jetson Xavier NXをセットアップして、OpenCVを入れてみて、とりあえず、USBカメラを使ってライブビュー表示してみた、という記事でした。