Ubuntu22.04上でTensorFlow Lite for C/C++をソースコードからx86_64(CPU)向けにビルドして、Native-Linux環境で実装したC++のプログラムからTensorFlow Liteを呼び出す

# TensorFlow Lite for C/C++を使ってみよう

みなさんはTensorFlow Liteをどのように利用されていますか？ネット上の記事をみると、かなり多くの方が **PythonからTensorFlow Liteを利用している** ように見受けられ、私のその一人です。ですが、 **TensorFlow LiteでAPUなどのアクセラレータを利用し、高速な推論を実現するためには「デリゲート」と呼ばれるソースコードを差し込む必要があります。** そのため、TensorFlow Lite for C/C++を使えるようになっておくことは非常に有益です。

https://mediatek.gitlab.io/genio/doc/tao/npu_acceleration.html

### 本記事の狙い

そこで本記事では、x86_64上のUbuntu22.04でTensorFlow Lite for C/C++を有効化する方法を紹介します。Raspberry Pi等、組み込みボード向けの提供手順は多いのですが、x86_64 x C/C++ の構成はほとんど見かけないため（需要がないのだと思います...）情報の整理も兼ねて記事にしました。 **やってみると、案外ハマります...** 以下は公式のドキュメントですがビルドする流れがかなり複雑になっていることが見て取れると思います。 **公式の記事はさておき、本記事はゼロからビルドして成功した全手順を掲載します。**

https://www.tensorflow.org/install/source?hl=ja

#### 本記事を作成する上で最も参考にした記事

https://qiita.com/iwatake2222/items/d998df1981d46285df62

https://daisuke20240310.hatenablog.com/entry/raspi2

## 開発環境を準備をする

まず、 **OSのインストールや開発に便利なツールなどのインストールを行い、** TensorFlow Lite for C/C++をインストールするための土台を組み上げていきます。

- Core i5-14600K (14cores, 20threads)
- RAM 64GB
- On-Board Graphics (CPU)
- Ubuntu 22.04 LTS
  - Yocto Linux等、併設する他の開発環境も考慮しました

### Ubuntu 22.04 LTSをインストールする

まず、PCに「Ubuntu22.04 LTS」をインストールします。以下のインストーラーを利用し、インストールしました。今回はGPUを搭載せず、マザーボード上のオンボードのHDMIポートを利用しました。

https://releases.ubuntu.com/jammy/

![ubuntu2204](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3919880%2F0b35301c-d7fd-4b4f-fdd8-d955714ce393.jpeg?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=455a0326e98c3c5154ae2e5530e4c1ca)

### 最低限必要な前準備を行う

日本語設定でインストールすると、ホームディレクトリ以下に日本語名のディレクトリが作成されてしまい、何かと不都合が生じるため **`xdg-user-dirs-gtk-update` を使ってディレクトリを英語名に変更します。** また、以降の手順にて sudo を利用することが多いため、 sudo 実行時にパスワードを求められないよう **`/etc/sudoers` に `shino ALL=(ALL:ALL) NOPASSWD:ALL` の設定を追記し、パスワード無しでsudoできるようにしました。** 設定した後、OSを再起動します。

```bash
### ホームディレクトリへ移動
$ cd ~

### ホームディレクトリ名から日本語を除外する
$ LANG=C xdg-user-dirs-gtk-update

### ユーザーからsudoをパスワード無しで実行できるようにする
$ sudo vi /etc/sudoers
# -->> 以下の行を追加する(ユーザー名がshinoの場合)
# shino   ALL=(ALL:ALL) NOPASSWD:ALL

### 再起動する
$ sudo reboot
```

### Ubuntuのパッケージをすべて更新する

続いて、Ubuntuのパッケージを最新の状態へと更新します。
また、エディタを追加します。

```bash
# リポジトリにアクセス
$ sudo apt update

# 更新可能なパッケージをすべてアップグレード
$ sudo apt upgrade

# 再起動
$ sudo reboot
```

### リモートから開発できるようにSSHサーバをインストールする

Ubuntuをリモートからも利用したいため openssh-server をインストールし、SSH接続ができるように設定を行います <font color="blue">**(必須の手順ではありませんが、操作が簡単にになります)。**</font> Visual Studio Codeや、Windowsのターミナルからパスワード入力すること無くSSH接続したい場合は、下記の記事をご参照ください。

```bash
### sshサーバをインストールします
$ sudo apt install openssh-server

### Ubuntu24.04からsshdでなくsshになっています 
# ... 起動時にサービスが開始されるように設定します
$ sudo systemctl start ssh
$ sudo systemctl enable ssh

### vimエディタをインストールします。
$ sudo apt install vim
$ sudo update-alternatives --config vi
# alternative vi (/usr/bin/vi を提供) には 2 個の選択肢があります。
# 
#   選択肢    パス              優先度  状態
# ------------------------------------------------------------
# * 0            /usr/bin/vim.basic   30        自動モード
#   1            /usr/bin/vim.basic   30        手動モード
#   2            /usr/bin/vim.tiny    15        手動モード
# 
# 現在の選択 [*] を保持するには <Enter>、さもなければ選択肢の番号のキーを押してください:
# -->> [Enter]

### Ubuntu上での操作
$ mkdir -p /home/shino/.ssh
$ touch /home/shino/.ssh/authorized_keys
$ sudo chmod 700 /home/shino/.ssh
$ sudo chmod 640 /home/shino/.ssh/authorized_keys

### 公開鍵を登録する
$ vi /home/shino/.ssh/authorized_keys
# -->> Windows上の "id_rsa.pub" の内容を書き込む

### 再起動する
$ sudo reboot
```

https://help.coreserver.jp/manual/hosts-win/

https://qiita.com/xtrizeShino/items/30dca87bc0789fcacfab

https://zenn.dev/kusaremkn/articles/21c21b3548092e

## TensorFlow for C/C++をビルドする準備をする

それでは TensorFlow Lite for C/C++ のビルドをはじめていきましょう。ビルドには **`bazel`** 、 **`clang`**、**`その他いくつかのパッケージ`** が必要になるため、事前にインストールします。

### ビルドに必要なパッケージをインストールする

`apt` コマンドで以下のパッケージをインストールしましょう。

```bash
$ sudo apt update
$ sudo apt install -y vim 
$ sudo apt install -y linux-headers-$(uname -r) build-essential wget git cmake clang lldb lld
$ sudo apt install -y python3-dev python3-pip python3.10-venv
$ python3 -m pip install -U --user pip
$ sudo apt install -y libopencv-dev ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libxml2 libstdc++6
```

### ビルドツール「bazel」をインストールする

続いて、TensorFlow Liteをビルドするための `bazel` をインストールしましょう。

https://bazel.build/install/ubuntu?hl=ja

```bash
$ sudo apt install -y apt-transport-https curl gnupg
$ curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor >bazel-archive-keyring.gpg
$ sudo mv bazel-archive-keyring.gpg /usr/share/keyrings
$ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/bazel-archive-keyring.gpg] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
$ sudo apt update && sudo apt install bazel
```

### ビルドツール「clang」をインストールする

加えて、TensorFlow Liteをコンパイルするための `clang` をインストールします。

```bash
$ wget https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.2/clang+llvm-17.0.2-x86_64-linux-gnu-ubuntu-22.04.tar.xz
$ tar -xvf clang+llvm-17.0.2-x86_64-linux-gnu-ubuntu-22.04.tar.xz
$ sudo cp -r clang+llvm-17.0.2-x86_64-linux-gnu-ubuntu-22.04/* /usr
$ clang --version
# clang version 17.0.2 (https://github.com/llvm/llvm-project b2417f51dbbd7435eb3aaf203de24de6754da50e)
# Target: x86_64-unknown-linux-gnu
# Thread model: posix
# InstalledDir: /usr/bin
```

**以上で、ビルドの準備は完了となります。**

## TensorFlow Lite for C/C++をビルドする

それでは、TensorFlow Lite for C/C++をビルドしてみましょう。

### GithubからTensorFlowの<font color="red">【v2.16.1】</font>を入手する。

まず、`tensorflow` のリポジトリから `git` コマンドを使ってソースコード一式を入手し、**`git checkout` コマンドで `v2.16.1` のソースコードへと切り替えます。** 私が試したところ、他のバージョンを利用するとエラーが発生してビルドの通らないことが頻発したため、下記の記事で実績のある `v2.16.1` を選択しました。

https://daisuke20240310.hatenablog.com/entry/raspi2

```bash
$ cd ~
$ git clone https://github.com/tensorflow/tensorflow.git
$ cd tensorflow
$ git checkout v2.16.1
```

### TensorFlow Lite for C/C++をビルドする

ビルドする前に **`./configure` を実行してビルドの構成を決定** します。今回はGPUアクセラレーションを利用しない、以下の構成としました。 `./configure` を行った後、 **`bazel build` コマンドでTensorFlow Lite for C/C++をビルド** します。なお、本手順には `bazel-6.5.0` が必要だったため、`apt` コマンドでバージョンを変更しました。

https://www.tensorflow.org/lite/guide/build_arm64?hl=ja

```bash
### 構成変更する
$ ./configure
# Please specify the location of python. [Default is /usr/bin/python3]:
# Please input the desired Python library path to use.  Default is [/usr/lib/python3/dist-packages]
# Do you wish to build TensorFlow with ROCm support? [y/N]: N
# Do you wish to build TensorFlow with CUDA support? [y/N]: N
# Do you want to use Clang to build TensorFlow? [Y/n]: Y
# Please specify the path to clang executable. [Default is /usr/bin/clang]:
# Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is -Wno-sign-compare]:
# Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]: N

### ビルドができるか試してみる
$ bazel build -c opt //tensorflow/lite/c:libtensorflowlite_c.so
# ERROR: The project you're trying to build requires Bazel 6.5.0 (specified in /home/shino/tensorflow/.bazelversion), but it wasn't found in /usr/bin.
# 
# You can install the required Bazel version via apt:
#   sudo apt update && sudo apt install bazel-6.5.0
# ...

### bazelのバージョンを指定してインストールしなおす
$ sudo apt update && sudo apt install bazel-6.5.0

### 再度ビルドする
$ bazel build -c opt //tensorflow/lite/c:libtensorflowlite_c.so
$ bazel build -c opt //tensorflow/lite:libtensorflowlite.so
```

----

### <font color="red">ビルドに失敗する環境があるようです</font>

<font color="red">**NVIDIAのSDK一式を入れた構成のUbuntu22.04で上記の手順を行うと以下のエラーが発生してしまいました。なにやらCUDAをインストールすると問題が発生するようです。何か心当たりのある方いらっしゃいましたら、教えていただければ嬉しいです。**</font>

![スクリーンショット 2025-02-17 143230.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3919880/71d860a8-cb84-47d0-a09b-abdac824516e.png)

https://qiita.com/xtrizeShino/items/46a3a10da6d12c65943d

----

### ビルド成果物とヘッダファイルを確認する

以下がビルドの成果物と、それらを利用する際に必要なヘッダファイルとなります。

```bash
$ ls bazel-bin/tensorflow/lite/libtensorflowlite.so
# bazel-bin/tensorflow/lite/libtensorflowlite.so
$ ls bazel-bin/tensorflow/lite/c/libtensorflowlite_c.so
# bazel-bin/tensorflow/lite/c/libtensorflowlite_c.so

$ ls tensorflow/lite/*.h
# tensorflow/lite/allocation.h                    tensorflow/lite/mutable_op_resolver.h
# tensorflow/lite/arena_planner.h                 tensorflow/lite/namespace.h
# tensorflow/lite/array.h                         tensorflow/lite/op_resolver.h
# tensorflow/lite/builtin_op_data.h               tensorflow/lite/optional_debug_tools.h
# tensorflow/lite/builtin_ops.h                   tensorflow/lite/portable_type_to_tflitetype.h
# tensorflow/lite/context.h                       tensorflow/lite/shared_library.h
# tensorflow/lite/context_util.h                  tensorflow/lite/signature_runner.h
# tensorflow/lite/create_op_resolver.h            tensorflow/lite/simple_memory_arena.h
# tensorflow/lite/error_reporter.h                tensorflow/lite/simple_planner.h
# tensorflow/lite/external_cpu_backend_context.h  tensorflow/lite/stateful_error_reporter.h
# tensorflow/lite/graph_info.h                    tensorflow/lite/stderr_reporter.h
# tensorflow/lite/interpreter.h                   tensorflow/lite/string_type.h
# tensorflow/lite/interpreter_builder.h           tensorflow/lite/string_util.h
# tensorflow/lite/interpreter_options.h           tensorflow/lite/tensorflow_profiler_logger.h
# tensorflow/lite/interpreter_test_util.h         tensorflow/lite/test_util.h
# tensorflow/lite/logger.h                        tensorflow/lite/tflite_with_xnnpack_optional.h
# tensorflow/lite/memory_planner.h                tensorflow/lite/type_to_tflitetype.h
# tensorflow/lite/minimal_logging.h               tensorflow/lite/util.h
# tensorflow/lite/model.h                         tensorflow/lite/version.h
# tensorflow/lite/model_builder.h

$ ls tensorflow/lite/c/*.h
# tensorflow/lite/c/builtin_op_data.h     tensorflow/lite/c/c_api_internal.h         tensorflow/lite/c/common.h
# tensorflow/lite/c/c_api.h               tensorflow/lite/c/c_api_opaque.h           tensorflow/lite/c/common_internal.h
# tensorflow/lite/c/c_api_experimental.h  tensorflow/lite/c/c_api_opaque_internal.h  tensorflow/lite/c/test_util.h
# tensorflow/lite/c/c_api_for_testing.h   tensorflow/lite/c/c_api_types.h
```

### TensorFlow Liteが利用するFlatBuffersをビルドする

**TensorFlow Liteはmodelを `FlatBuffers` と呼ばれるフレームワークで管理** します。そのため、FlatBuffersもビルドしておきましょう。なお、FlatBuffersはTensorFlowが必要とするバージョンと揃える必要があります。

#### TensorFlowが必要とするFlatBuffersのバージョンを確認する

まず `schema_generated.h` を開き、TensorFlowが必要とするFlatBuffersのバージョンを確認します。以下の例では、 **必要となるFlatBuffersは `v23.5.26`** であることがわかります。

```bash
$ find . -type f | xargs grep FLATBUFFERS_VERSION_MAJOR
# ./tensorflow/lite/schema/schema_generated.h:static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&
$ vim ./tensorflow/lite/schema/schema_generated.h
# ...
# static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&
#               FLATBUFFERS_VERSION_MINOR == 5 &&
#               FLATBUFFERS_VERSION_REVISION == 26,
#              "Non-compatible flatbuffers version included");
# ...
```

#### GitHubよりFlatBuffersを取得しビルドする

`git` コマンドにより、FlatBuffersのソースコードを入手し、 `git checkout` コマンドでTensorFlowの要求するFlatBuffersのバージョンにソースコードを切り替えます。その後 `cmake` を利用してFlatBuffersをビルドします。成果物は以下の箇所に格納されます。


https://github.com/google/flatbuffers/releases/tag/v23.5.26

```bash
### FlatBuffers 23.5.26を入手する
$ cd ~
$ git clone https://github.com/google/flatbuffers.git
$ cd flatbuffers
$ git checkout v23.5.26

### ビルドする
$ mkdir build
$ cd build/
$ cmake ..
$ make

### ビルド成果物を確認する
$ ls ./libflatbuffers.a
# ./libflatbuffers.a
$ ls ../include/flatbuffers/flatbuffers.h
# ../include/flatbuffers/flatbuffers.h
```

# TensorFlow Lite for C/C++を利用する

それでは実際に、ビルドしたTensorFlow Lite for C/C++を利用してみましょう。TensorFlow Lite for C/C++を呼び出すためのコードは、以下のサイトで非常にわかりやすく書かれていました。とても参考になりました、ありがとうございます。

https://qiita.com/iwatake2222/items/796ec8560563625ace34

https://qiita.com/iwatake2222/items/d63aa67e5c700fcea70a

https://qiita.com/iwatake2222/items/d998df1981d46285df62

https://www.tensorflow.org/lite/guide/inference?hl=ja

#### 以上のサイトを参考に収集したソースコード

以下のリポジトリが、以降の手順をまとめたソースコードとなります。

https://github.com/xtrizeShino/qiita_mnist_with_tflite_cpp/blob/main/README.md

### ビルドしたTensorFlow Lite for C++を参照するCMakeLists.txt

まず `CMakeLists.txt` を記述します。 `CMakeLists.txt` は `cmake` コマンドを実行した際に呼び出され、`Makefile` を自動的に生成するためのファイルです。 **ファイルパスに上記でビルドしたTensorFlow Lite for C/C++のフォルダ位置を記述してください。** 私の手順では `/home/shino/tensorflow` に `clone` したため、以下のような記述となりました。

https://qiita.com/iwatake2222/items/d998df1981d46285df62

```cmake
cmake_minimum_required(VERSION 2.8)
project(NumberDetector)

# Create Main project
add_executable(NumberDetector
	main.cpp
)

# For OpenCV
find_package(OpenCV REQUIRED)
if(OpenCV_FOUND)
	target_include_directories(NumberDetector PUBLIC ${OpenCV_INCLUDE_DIRS})
	target_link_libraries(NumberDetector ${OpenCV_LIBS})
endif()

# For Tensorflow Lite
target_link_libraries(NumberDetector /home/shino/tensorflow/bazel-bin/tensorflow/lite/libtensorflowlite.so)
target_include_directories(NumberDetector PUBLIC /home/shino/tensorflow)
target_include_directories(NumberDetector PUBLIC /home/shino/tensorflow/tensorflow)
target_include_directories(NumberDetector PUBLIC /home/shino/tensorflow/tensorflow/lite)
target_include_directories(NumberDetector PUBLIC  /home/shino/flatbuffers/include)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -std=c++17 -lstdc++")

# Copy resouce
file(COPY ${CMAKE_SOURCE_DIR}/resource/ DESTINATION ${PROJECT_BINARY_DIR}/resource/)
add_definitions(-DRESOURCE_DIR="${PROJECT_BINARY_DIR}/resource/")
```

### TensorFlow for C++を呼び出すソースコード

TensorFlowを呼び出すソースコードは、以下の記事よりお借りしました。実行には、**入力となる画像ファイル（ここでは `4.jpg`）** と **tflite形式のAIモデル** が必要になります。本ソースコードは、白地に黒で書かれた数字の画像が、0～9のうちいずれであるかを推論するプログラムです。実行には **画像ファイルとtflite形式のファイルが必要になります。**

https://qiita.com/iwatake2222/items/d998df1981d46285df62

```cpp
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/optional_debug_tools.h"

#define MODEL_FILENAME RESOURCE_DIR"conv_mnist.tflite"

#define TFLITE_MINIMAL_CHECK(x)                              \
    if (!(x)) {                                                \
        fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); \
        exit(1);                                                 \
    }

int main()
{
    /* 入力となる画像データを読み込む "4.jpg" */
    printf("input image path : %s\n", RESOURCE_DIR"4.jpg");
    cv::Mat image = cv::imread(RESOURCE_DIR"4.jpg");
    /* ディスプレイに出力する */
    cv::imshow("InputImage", image);
    /* 画面表示が閉じられるまで待機 */
    cv::waitKey(0);
    
    /* 入力画像をgrayscaleへと変換する */
    cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
    /* 28px x 28pxにリサイズする */
    cv::resize(image, image, cv::Size(28, 28));
    /* 背景が黒、文字色が白にする */
    image = ~image;
    /* ディスプレイに出力する */
    cv::imshow("InputImage for CNN", image);
    /* Normalize: 0.0 ~ 1.0 する */
    image.convertTo(image, CV_32FC1, 1.0 / 255);
    /* 画面表示が閉じられるまで待機 */
    cv::waitKey(0);

    /* tfliteモデルのパス */
    printf("model file name : %s\n", MODEL_FILENAME);
    /* tfliteのモデルをFlatBufferに読み込む */
    std::unique_ptr<tflite::FlatBufferModel> model = tflite::FlatBufferModel::BuildFromFile(MODEL_FILENAME);
    /* 開けたかチェック */
    TFLITE_MINIMAL_CHECK(model != nullptr);
    
	/* インタープリタを生成する */
	tflite::ops::builtin::BuiltinOpResolver resolver;
	tflite::InterpreterBuilder builder(*model, resolver);
	std::unique_ptr<tflite::Interpreter> interpreter;
	builder(&interpreter);
    /* 生成できたかチェック */
	TFLITE_MINIMAL_CHECK(interpreter != nullptr);

	/* 入出力のバッファを確保する */
	TFLITE_MINIMAL_CHECK(interpreter->AllocateTensors() == kTfLiteOk);
	printf("=== Pre-invoke Interpreter State ===\n");
	tflite::PrintInterpreterState(interpreter.get());

	/* 入力テンソルに読み込んだ画像を格納する */
	float* input = interpreter->typed_input_tensor<float>(0);
	memcpy(input, image.reshape(0, 1).data, sizeof(float) * 1 * 28 * 28 * 1);

	/* 推論を実行 */
	TFLITE_MINIMAL_CHECK(interpreter->Invoke() == kTfLiteOk);
	printf("\n\n=== Post-invoke Interpreter State ===\n");
	tflite::PrintInterpreterState(interpreter.get());

	/* 出力テンソルから結果を取得して表示 */
	float* probs = interpreter->typed_output_tensor<float>(0);
	for (int i = 0; i < 10; i++) {
		printf("prob of %d: %.3f\n", i, probs[i]);
	}

    /* 終了 */
	return 0;
}
```

### ビルドと実行結果

以上を格納したディレクトリを作成し、これに対して **`cmake` と `make` を使ってビルドを実施すると `NumberDetector` というバイナリが生成** されます。これを実行することにより画像から、そこに書かれた文字を認識することができます。

#### 実行結果（成功例）

```bash
### conda仮想環境から抜ける
$ conda deactivate

### ソースコードとCMakeLists.txtを準備する
$ ls
# CMakeLists.txt  main.cpp  resource

### resourceに画像とtfliteモデルを格納する
$ ls resource/
# 4.jpg  conv_mnist.tflite

### ビルドする
$ mkdir build
$ cd build
$ cmake ..
$ make 
# [ 50%] Building CXX object CMakeFiles/NumberDetector.dir/main.cpp.o
# [100%] Linking CXX executable NumberDetector
# [100%] Built target NumberDetector

### 実行する
$ ./NumberDetector 
# input image path : /home/shino/sandbox/sample_cv_tflite_cpp/build/resource/4.jpg
# model file name : /home/shino/sandbox/sample_cv_tflite_cpp/build/resource/conv_mnist.tflite
# INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
# ...
# prob of 0: 0.000
# prob of 1: 0.000
# prob of 2: 0.000
# prob of 3: 0.000
# prob of 4: 1.000
# prob of 5: 0.000
# prob of 6: 0.000
# prob of 7: 0.000
# prob of 8: 0.000
# prob of 9: 0.000
```

#### <font color="red">**【注意】**</font> conda activate tf-gpu-envをしている場合、起動に失敗する

`conda activate tf-gpu-env` を実行していると下記のエラーが発生します。 `conda` の仮想環境から `conda deactivate` コマンドを実行し、仮想環境から出て、再度 `cmake ..` と `make` を実行してください。

https://qiita.com/dekavit/items/a6a62044d91a05feccc8

https://github.com/pjreddie/darknet/issues/1959

```bash
### 実行できるか確認
(tf-gpu-env) $ ./NumberDetector 
# ./NumberDetector: /home/shino/anaconda3/envs/tf-gpu-env/lib/libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by /home/shino/tensorflow/bazel-bin/tensorflow/lite/libtensorflowlite.so)
### 対策のため以下をインストールする
$ conda install -c conda-forge gcc=12.1.0

### 再度実行できるか確認
(tf-gpu-env) $ ./NumberDetector 
# ./NumberDetector: error while loading shared libraries: libopencv_highgui.so.406: cannot open shared object file: No such file or directory  
# ./NumberDetector: error while loading shared libraries: libopencv_highgui.so.406: cannot open shared object file: No such file or directory
## -->> libopencv_highgui.so.406は存在しない...
```

```bash
######
### 最も簡単な回避方法
######
### conda環境から抜ける
$ conda deactivate

### 再度ビルドを実行する
$ cd build
$ cmake ..
$ make 
```

----

以上がx86_64向けのTensorFlow Lite for C/C++をビルドして
利用する手順となります。やや複雑な手順ですが、C/C++でTensorFlowを書くことは
勉強にもなると思いますので、是非お試しください！

**お疲れさまでした！**

----

### tfliteのモデルを取得するために利用したソースコード

https://qiita.com/iwatake2222/items/796ec8560563625ace34

https://qiita.com/iwatake2222/items/d63aa67e5c700fcea70a

https://qiita.com/iwatake2222/items/d998df1981d46285df62

### TensorFlow(h5)からtfliteモデルを生成するためのツールを準備する

TensorFlow(h5)形式のAIモデルからTFLiteのAIモデルを作成するために、Anacondaをインストールし、Pythonの仮想環境を作成した後、 **`TensorFlow-gpu`** をインストールしました。

#### Anacondaをインストールする

https://www.anaconda.com/download/success

https://qiita.com/sophytoeat/items/34d214c2d6036e2fa229

```bash
### Anaconda3をダウンロードする
$ cd ~/Downloads
$ wget https://repo.anaconda.com/archive/Anaconda3-2024.10-1-Linux-x86_64.sh

### インストーラに実行権限を付与する 
$ chmod +x ~/Downloads/Anaconda3-2024.10-1-Linux-x86_64.sh

### インストーラを実行する
$ ~/Downloads/Anaconda3-2024.10-1-Linux-x86_64.sh
# Welcome to Anaconda3 2024.10-1
# 
# In order to continue the installation process, please review the license
# agreement.
# Please, press ENTER to continue
# >>>
# ...
# [/home/shino/anaconda3] >>>
# ...
# Do you wish to update your shell profile to automatically initialize conda?
# This will activate conda on startup and change the command prompt when activated.
# If you'd prefer that conda's base environment not be activated on startup,
#    run the following command when conda is activated:
# 
# conda config --set auto_activate_base false
# 
# You can undo this by running `conda init --reverse $SHELL`? [yes|no]
# [no] >>>
# ...
# conda init
# 
# Thank you for installing Anaconda3!

### パスを通す
$ vi ~/.bashrc
# 最後に以下の1行を追加する
export PATH="$PATH:/home/shino/anaconda3/bin"

### 環境変数を読み込みなおす
$ source ~/.bashrc

### Anacondaの初期設定を実行する
$ conda init
# no change     /home/shino/anaconda3/condabin/conda
# no change     /home/shino/anaconda3/bin/conda
# no change     /home/shino/anaconda3/bin/conda-env
# no change     /home/shino/anaconda3/bin/activate
# no change     /home/shino/anaconda3/bin/deactivate
# no change     /home/shino/anaconda3/etc/profile.d/conda.sh
# no change     /home/shino/anaconda3/etc/fish/conf.d/conda.fish
# no change     /home/shino/anaconda3/shell/condabin/Conda.psm1
# no change     /home/shino/anaconda3/shell/condabin/conda-hook.ps1
# no change     /home/shino/anaconda3/lib/python3.12/site-packages/xontrib/conda.xsh
# no change     /home/shino/anaconda3/etc/profile.d/conda.csh
# modified      /home/shino/.bashrc
# 
# ==> For changes to take effect, close and re-open your current shell. <==


### bashrcに以下のコードブロックが増えていることを確認する
$ vi ~/.bashrc
# # >>> conda initialize >>>
# # !! Contents within this block are managed by 'conda init' !!
# __conda_setup="$('/home/shino/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
# if [ $? -eq 0 ]; then
#     eval "$__conda_setup"
# else
#     if [ -f "/home/shino/anaconda3/etc/profile.d/conda.sh" ]; then
#         . "/home/shino/anaconda3/etc/profile.d/conda.sh"
#     else
#         export PATH="/home/shino/anaconda3/bin:$PATH"
#     fi
# fi
# unset __conda_setup
# # <<< conda initialize <<<

### bash初期化スクリプトを再度読み込む
$ source ~/.bashrc

### Anacondaが有効になることを確認する
(base) $
```

#### Pythonの仮想環境を作成する

tfliteモデルは、PythonのTensorFlowパッケージに含まれている **`tflite_convert`** コマンドを利用しました。以下の手順でPythonの仮想環境を作成し、変換します。 

```bash
### Pythonの仮想環境を作成する
$ conda create --name tf-gpu-env tensorflow=*=gpu_*
$ conda activate tf-gpu-env
$ pip install tensorboard
$ pip install pandas
$ pip install matplotlib
$ pip install scikit-learn
$ pip install numpy
$ pip install ipykernel
$ conda install opencv

### h5 -> tfliteへの変換
$ conda activate tf-gpu-env
(tf-gpu-env) $ tflite_convert --output_file=conv_mnist.tflite --keras_model_file=conv_mnist.h5
(tf-gpu-env) $ ls ./conv*
# conv_mnist.h5  conv_mnist.tflite
```