Compile MNN e implemente mnist en el entorno Ubuntu20.04

Compilar MNN en entorno Ubuntu20.04

Preparación del entorno de compilación

  • cmake (se recomienda la versión 3.10 o superior)
  • protobuf (usar 3.0 o superior)
  • gcc (usar 4.9 o superior)

1. instalación gcc

sudo apt actualizar
sudo apt install build-essential

2. hacer la instalación

  • Descargue cmake desde el sitio web oficial de cmake, seleccione la versión de Linux para descargar
    Dirección de descarga: cmakeinserte la descripción de la imagen aquí
  • Abra el terminal de comando en la carpeta donde se encuentra el código fuente de cmake y descomprima el archivo

tar -zxv -f cmake-3.23.0-rc3.tar.gz

  • Ingresa a la carpeta descomprimida y ejecuta

./oreja

Si ocurre el siguiente error, debe instalar libssl-dev y luego ejecutarlo nuevamente después de la instalación./bootstrap

sudo apt-get install libssl-dev

inserte la descripción de la imagen aquí

  • Compilar y construir cmake

hacer

  • instalar cmake

sudo hacer instalar

  • Después de la instalación, ingrese cmake --versionpara verificar si la instalación está completa

3. Instalar protobuf

  • instalar dependencias

sudo apt-get install autoconf automake libtool curl make g++ unzip libffi-dev -y

  • Descargar código fuente de protobuf
    Dirección de descarga: protobuf
  • Descomprimir el paquete comprimido

tar -zxv -f protobuf-cpp-3.20.0-rc-1.tar.gz

  • Ingrese a la carpeta descomprimida para generar el archivo de configuración

cd protobuf-3.20.0-rc-1/
./autogen.sh

  • Entorno de configuración

./configurar

  • Compilar el código fuente

hacer

  • Instalar

sudo hacer instalar

  • Actualizar biblioteca dinámica

sudo ldconfig

  • Ingrese protoc --versionpara ver si la instalación es exitosa

Compilar MNN

documento oficial

  • Descarga el código fuente de MNN y descomprímelo
    Link de descarga: MNN
  • descomprimir

descomprimir MNN-master.zip

  • Ingresa a la carpeta descomprimida y ejecuta

cd MNN
./esquema/generar.sh

  • Compilación local, una vez completada la compilación, la biblioteca dinámica de MNN aparece localmente

mkdir construir && cd construir && cmake … && hacer -j8

compilación de Android

  1. Descargue e instale NDK en https://developer.android.com/ndk/downloads/, se recomienda usar la última versión estable
  2. Configure las variables de entorno de NDK en .bashrc o .bash_profile, por ejemplo: export ANDROID_NDK=/Users/username/path/to/android-ndk-r14b
  3. cd /ruta/a/MNN
  4. ./esquema/generar.sh
  5. ./tools/script/get_model.sh (opcional, el modelo solo se requiere para proyectos de demostración). Tenga en cuenta que get_model.sh necesita compilar la herramienta de conversión de modelos por adelantado, consulte aquí.
  6. proyecto de cd/android
  7. Compile la biblioteca dinámica armv7: mkdir build_32 && cd build_32 && .../build_32.sh
  8. Compile la biblioteca dinámica armv8: mkdir build_64 && cd build_64 && .../build_64.sh

implementar mnist

Instalar la biblioteca opencv

La implementación de mnist también requiere la biblioteca opencv, por lo que debe instalar opencv. Puede
instalarlo clonando el código fuente de OpenCV de acuerdo con este artículo. Después de instalar
el blog
, escriba un programa simple de opencv para verificar si está disponible
. Cree un archivo main.cpp y use gcc compilar y ejecutar

g++ main.cpp -o salida `pkg-config --cflags --libs opencv4`
./salida

#include <opencv2/highgui.hpp>
#include "opencv2/imgcodecs/legacy/constants_c.h"
#include "opencv2/imgproc/types_c.h"
#include <iostream>
int main( int argc, char** argv ) {
    
    
    cv::Mat image;
    image = cv::imread("test.jpg" , CV_LOAD_IMAGE_COLOR);	      
    if(! image.data ) {
    
    
        std::cout <<  "Could not open or find the image" << std::endl ;
	    return -1;
    }

    std::cout << "image wide: "<< image.cols << ",image high: " << image.rows << ",image channels: "<< image.channels() << std::endl;
    /* display image
    cv::namedWindow( "Display window", cv::WINDOW_AUTOSIZE );
    cv::imshow( "Display window", image );		    
    cv::waitKey(0);
    */
    size_t y,x;// y is row, x is col
    int c;     // c is channel
    y = x = 250;
    c = 2;
    // row_ptr is the head point of y row
    unsigned char *row_ptr = image.ptr<unsigned char>(y);
    // data_ptr points to pixel data
    unsigned char *data_ptr = &row_ptr[x * image.channels()]; 
    unsigned char data =  data_ptr[c];

    // use cv::Mat::at() to get the pixel value
    // unsigned char is not printable
    // std::cout << std::isprint(data)<<std::isprint(image.at<cv::Vec3b>(y,x)[c]) << std::endl;
    std::cout << "pixel value at y, x ,c"<<static_cast<unsigned>(image.at<cv::Vec3b>(y,x)[c]) << std::endl;
    return 0;
}

Si ocurre la siguiente situación durante la operación, significa que la ruta de la biblioteca no está configurada correctamente
inserte la descripción de la imagen aquí
.

sudo vi /etc/ld.so.conf.d/opencv.conf
en el directorio /etc/ld.so.conf.d/ sudo vim /etc/ld.so.conf.d/opencv.conf

Escribe dos líneas:

/usr/local/lib
~/opencv_build/opencv/build/lib (aquí se refiere a la lib debajo de la ruta opencv que instaló)

Guarde y salga, ejecute sudo ldconfig, resuelva el problema
y vuelva a ejecutar ./outputpara generar la información correcta, lo que indica que la instalación de opencv se realizó correctamente

implementar mnist

Cree un archivo c ++, escriba el programa de acuerdo con el proceso de razonamiento del documento oficial de MNN, la dirección de descarga del modelo mnn

#include "Backend.hpp"
#include "Interpreter.hpp"
#include "MNNDefine.h"
#include "Interpreter.hpp"
#include "Tensor.hpp"
#include <math.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
using namespace MNN;
using namespace cv;

int main(void)
{
    
    
   // 填写自己的测试图像和mnn模型文件路径
    std::string image_name = "test.jpg";
    const char* model_name = "mnist.mnn";
    // 一些任务调度中的配置参数
    int forward = MNN_FORWARD_CPU;
    // int forward = MNN_FORWARD_OPENCL;
    int precision  = 2;
    int power      = 0;
    int memory     = 0;
    int threads    = 1;
    int INPUT_SIZE = 28;

    cv::Mat raw_image    = cv::imread(image_name.c_str());
    //imshow("image", raw_image);
    int raw_image_height = raw_image.rows;
    int raw_image_width  = raw_image.cols;
    cv::Mat image;
    cv::resize(raw_image, image, cv::Size(INPUT_SIZE, INPUT_SIZE));
    // 1. 创建Interpreter, 通过磁盘文件创建: static Interpreter* createFromFile(const char* file);
    std::shared_ptr<Interpreter> net(Interpreter::createFromFile(model_name));
    MNN::ScheduleConfig config;
    // 2. 调度配置,
    // numThread决定并发数的多少,但具体线程数和并发效率,不完全取决于numThread
    // 推理时,主选后端由type指定,默认为CPU。在主选后端不支持模型中的算子时,启用由backupType指定的备选后端。
    config.numThread = threads;
    config.type      = static_cast<MNNForwardType>(forward);
    MNN::BackendConfig backendConfig;
    // 3. 后端配置
    // memory、power、precision分别为内存、功耗和精度偏好
    backendConfig.precision = (MNN::BackendConfig::PrecisionMode)precision;
    backendConfig.power = (MNN::BackendConfig::PowerMode) power;
    backendConfig.memory = (MNN::BackendConfig::MemoryMode) memory;
    config.backendConfig = &backendConfig;
    // 4. 创建session
    auto session = net->createSession(config);
    net->releaseModel();

    clock_t start = clock();
    // preprocessing
    image.convertTo(image, CV_32FC3);
    image = image / 255.0f;
    // 5. 输入数据
    // wrapping input tensor, convert nhwc to nchw
    std::vector<int> dims{
    
    1, INPUT_SIZE, INPUT_SIZE, 3};
    auto nhwc_Tensor = MNN::Tensor::create<float>(dims, NULL, MNN::Tensor::TENSORFLOW);
    auto nhwc_data   = nhwc_Tensor->host<float>();
    auto nhwc_size   = nhwc_Tensor->size();
    ::memcpy(nhwc_data, image.data, nhwc_size);

    std::string input_tensor = "data";
    // 获取输入tensor
    // 拷贝数据, 通过这类拷贝数据的方式,用户只需要关注自己创建的tensor的数据布局,
    // copyFromHostTensor会负责处理数据布局上的转换(如需)和后端间的数据拷贝(如需)。
    auto inputTensor  = net->getSessionInput(session, nullptr);
    inputTensor->copyFromHostTensor(nhwc_Tensor);

    // 6. 运行会话
    net->runSession(session);

    // 7. 获取输出
    std::string output_tensor_name0 = "dense1_fwd";
    // 获取输出tensor
    MNN::Tensor *tensor_scores  = net->getSessionOutput(session, output_tensor_name0.c_str());

    MNN::Tensor tensor_scores_host(tensor_scores, tensor_scores->getDimensionType());
    // 拷贝数据
    tensor_scores->copyToHostTensor(&tensor_scores_host);

    // post processing steps
    auto scores_dataPtr  = tensor_scores_host.host<float>();

    // softmax
    float exp_sum = 0.0f;
    for (int i = 0; i < 10; ++i)
    {
    
    
        float val = scores_dataPtr[i];
        exp_sum += val;
    }
    // get result idx
    int  idx = 0;
    float max_prob = -10.0f;
    for (int i = 0; i < 10; ++i)
    {
    
    
        float val  = scores_dataPtr[i];
        float prob = val / exp_sum;
        if (prob > max_prob)
        {
    
    
            max_prob = prob;
            idx      = i;
        }
    }
    printf("the result is %d\n", idx);

    return 0;
}

Escriba CMakeLists.txt, preste atención para reemplazar la dirección de MNN dentro con la dirección de MNN compilada por usted mismo

cmake_minimum_required(VERSION 3.10)
project(mnist)

set(CMAKE_CXX_STANDARD 11)

find_package(OpenCV REQUIRED)
set(MNN_DIR /home/chen/MNN) 
include_directories(${MNN_DIR}/include)
include_directories(${MNN_DIR}/include/MNN)
include_directories(${MNN_DIR}/tools)
include_directories(${MNN_DIR}/tools/cpp)
include_directories(${MNN_DIR}/source)
include_directories(${MNN_DIR}/source/backend)
include_directories(${MNN_DIR}/source/core)

LINK_DIRECTORIES(${MNN_DIR}/build)
add_executable(mnist main.cpp)
target_link_libraries(mnist -lMNN ${OpenCV_LIBS})

compilar

cmake. Después de completar
la compilación de make
, aparecerá el archivo ejecutable mnist. Ingrese y ./mnistejecute, y podrá ver que los dígitos escritos a mano se pueden predecir con éxito.
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_40042726/article/details/123503544
Recomendado
Clasificación