ncnn環境のコンパイルとそのモデルの使用

ncnnコンパイルプロセスTencentGitHubに非常に明確記述していますが、2台のコンピューターを試したところ、環境を正常にコンパイルできませんでした。

だから私は探検し始めました

注:win10でコードを記述したいので、win10でコンパイルするためにここにいます。したがって、vs2019環境が必要です。

最初にprotobufをコンパイルし、zipダウンロードリンクを直接使用しますが、新しいビルドフォルダーを作成するプロセスは失敗します。これは、ビルドファイルが重複していることを示すプロンプトが表示されるため、新しく作成したtmpは実際には同じです。

その時点でncnnをコンパイルするときにパスを変更する必要があります

protobufのコンパイルプロセスは次のとおりです。

cd protobuf-3.4.0
mkdir tmp
cd tmp
cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF ../cmake
nmake
nmake install

コンパイルプロセスは簡単で、通常エラーはありません

次に、ncnnを直接コンパイルします。ここで、クローンncnnのソースコードが他のサブモジュールに関連付けられることを覚えています。ダイレクトgitクローンは完了せず、コンパイル中にエラーが発生します。

git clone https://github.com.cnpmjs.org/Tencent/ncnn
cd ncnn
git  submodule update --init

上記からわかるように、ここでもダウンロード速度を向上させるためにcnpmjs国内ミラーソースに変更されています

コンパイルプロセスは公式リンクに従ってコンパイルできますが、バグが発生し、cmakeが正常にコンパイルされず、1か所でスタックしていました。

GitHubで、最初は無視して、このバグをスキップするパラメーターを追加できると誰かが言っているのを見ました。

-DNCNN_BUILD_TOOLS = OFF

cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -DProtobuf_INCLUDE_DIR=C:/protobuf-3.4.0/protobuf-3.4.0/tmp/install/install/include -DProtobuf_LIBRARIES=C:/protobuf-3.4.0/protobuf-3.4.0/tmp/install/lib/libprotobuf.lib -DProtobuf_PROTOC_EXECUTABLE=C:/protobuf-3.4.0/protobuf-3.4.0/tmp/install/bin/protoc.exe -DNCNN_VULKAN=OFF -DNCNN_BUILD_TOOLS=OFF  ..

その後、あなたはうまくcmakeすることができます

残りはncnnが提供するインストールガイドに従うことができます

これまでのところ、vs2019でncnnをコンパイルすることは成功しています

見てみることができます

これで、vs2019を開いて環境を構成できます

(1)ディレクトリが含まれています

(2)ライブラリディレクトリ

(3)追加の依存関係

(4)追加のライブラリディレクトリ

これで、ncnnを直接使用できます

モデルファイルは使用前に準備する必要があります

モデルファイルは前の記事のモデルファイルのままであり、ncnnファイルはLinux環境のncnnで正常に変換されました

使用したonnxモデルファイルをncnnモデルファイルに変換します

ncnnモデルファイルは、caffeと同様に、2つの部分に分かれています。

変換コマンドは次のとおりです。

./tools/onnx/onnx2ncnn FashionMNIST.onnx FashionMNIST.param  FashionMNIST.bin

次に、ncnnoptimizeを使用してファイルを最適化します

tools/ncnnoptimize FashionMNIST.param FashionMNIST.bin FashionMNIST_OPT.param FashionMNIST_OPT.bin 1

結果は次のとおりです。

明らかに、最適化されたモデルファイルは小さくなり、主にfloat16が使用されています。ncnnoptimizeを使用するためのヘルプは次のとおりです。

usage: tools/ncnnoptimize [inparam] [inbin] [outparam] [outbin] [flag]

その中で、フラグは0または1で、0はfloat32を表し、1はfloat16を表します。

ここで使用するfloat16

モデルファイルを取得した後、vs2019でモデルを直接読み取ることができます

ただし、暗号化モードで読み取られます。ncnnは、モデルファイルをメモリに転送するためのncnn2memツールを提供します。

変換コードは次のとおりです。

ncnn2mem.exe FashionMNIST.param FashionMNIST.bin FashionMNIST.id.h FashionMNIST_de.mem.h

呼び出しは非常に簡単です。2つの.hファイルを直接含めるだけです。

完全な呼び出しコードは次のとおりです。

#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>
#include<ncnn/net.h>
#include "FashionMNIST.id.h"
#include "FashionMNIST_de.mem.h"

int main() {
	//读取模型文件
	ncnn::Net net;
	net.load_param(FashionMNIST_param_bin);
	net.load_model(FashionMNIST_bin);

	//ncnn::Mat in;
	ncnn::Mat out;
	cv::Mat m = cv::imread("C:\\123.jpg", CV_8U);
	ncnn::Mat in = ncnn::Mat::from_pixels(m.data, ncnn::Mat::PIXEL_GRAY, m.cols, m.rows);

	ncnn::Extractor ex = net.create_extractor();
	ex.set_light_mode(true);
	ex.input(FashionMNIST_param_id::BLOB_input, in);
	ex.extract(FashionMNIST_param_id::BLOB_output, out);
	 
	for (int j = 0; j < out.w; j++)
	{
		std::cout << out[j] << std::endl;
}	
	return 0;
}

演算結果:

同様に、最適化されたモデルも比較のために.hに転送されます。

ncnn2mem.exe FashionMNIST_OPT.param FashionMNIST_OPT.bin FashionMNIST_OPT.id.h FashionMNIST_OPT.mem.h

発信コード:

#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>
#include<ncnn/net.h>
#include "FashionMNIST_OPT.id.h"
#include "FashionMNIST_OPT.mem.h"

int main() {
	//读取模型文件
	ncnn::Net net;
	net.load_param(FashionMNIST_OPT_param_bin);
	net.load_model(FashionMNIST_OPT_bin);

	//ncnn::Mat in;
	ncnn::Mat out;
	cv::Mat m = cv::imread("C:\\123.jpg", CV_8U);
	ncnn::Mat in = ncnn::Mat::from_pixels(m.data, ncnn::Mat::PIXEL_GRAY, m.cols, m.rows);

	ncnn::Extractor ex = net.create_extractor();
	ex.set_light_mode(true);
	ex.input(FashionMNIST_OPT_param_id::BLOB_input, in);
	ex.extract(FashionMNIST_OPT_param_id::BLOB_output, out);
	 
	for (int j = 0; j < out.w; j++)
	{
		std::cout << out[j] << std::endl;
}	
	return 0;
}

操作の結果は次のとおりです。 

結果はほぼ同じであり、精度には間違いなく違いがあることがわかります。

おすすめ

転載: blog.csdn.net/zhou_438/article/details/112436476