0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenCVのDNNモジュールでMNISTをする。(C++編)

Last updated at Posted at 2024-10-19

はじめに

OpenCVにはDNNモジュールという、ニューラルネットワークのランタイムライブラリがあります。
このDNNモジュールはいろいろなonnxファイルを読み込んで推論することができます。

OpenCVのMNISTのC++のサンプルコードがないか探してみたんですが、見つからなかったので、今回DNNモジュールの使い方の勉強も兼ねてOpenCVでMNISTをやってみたいと思います。

準備

OpenCVを使うには事前にcmakeやC++コンパイラ、OpenCVがインストールされていないといけません。

Linux

Linuxではapt-getでインストールできます。

apt-get install cmake make g++ gcc libopencv-dev

Windows

Windowsでビルドするには以下のサイトをみてcmakeやC++コンパイラやOpenCVを準備をしてください。

WindowsにCmakeを導入
https://qiita.com/matskeng/items/c466c4751e1352f97ce6

MinGW-w64のインストール
https://qiita.com/yomei_o/items/2e706a5fa3ac5ffc3a50

WindowsでOpenCVをMinGW-w64でビルド
https://qiita.com/yomei_o/items/4d794536e24ffc12e29d

Mac

macでも以下のような感じでインストールできます。
https://qiita.com/kai_kou/items/df335eb7ee78229ee46f

MNISTの学習済みONNXモデルの取得

MNISTの学習済みONNXモデルは以下のサイトからとってくることができます。
https://github.com/onnx/models/tree/main/validated/vision/classification/mnist

今回はmnist-8.onnxというものを使うことにしました。
https://github.com/onnx/models/blob/main/validated/vision/classification/mnist/model/mnist-8.onnx

プログラムの作成

適当なディレクトリに「CMakeLists.txt」と「opencv_mnist.cpp」のファイルを置きます。

opencv_mnist.cpp

#include<stdio.h>
#include<iostream>
#include<string>
#include<vector>

#include <opencv2/opencv.hpp>

int main()
{
 unsigned char* p;
 int x=-1, y=-1, n=-1;

 cv::Mat color = cv::imread("tegaki5.png");
 cv::Mat img;
 cv::cvtColor(color, img, cv::COLOR_BGR2GRAY);
 cv::resize(img, img, cv::Size(28, 28));
 img = ~img;

 cv::Mat inpBlob = cv::dnn::blobFromImage(img);
 cv::dnn::Net net = cv::dnn::readNetFromONNX("mnist-8.onnx");

 cv::imwrite("out.png",img);

 net.setInput(inpBlob);
 cv::Mat output = net.forward();

 int i;
 for (i = 0; i < 10; i++) {
  printf("%d : %f \n",i,output.at<float>(i));
 }

 return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.13)
project(test_cmake CXX C)

find_package(OpenCV REQUIRED)

add_executable(test opencv_mnist.cpp)

target_include_directories(test PRIVATE ${OpenCV_INCLUDE_DIRS})
target_link_libraries (test PRIVATE gdi32 comdlg32 ${OpenCV_LIBS})

画像は次のものを使用しました。
tegaki5.png
tegaki5.png

OpenCVのDNNモジュールの使い方は解説するまでもなくとてもシンプルです。
まず、以下のようにネットワークモデルを読み込みます。

net=cv::dnn::readNetFromONNX("mnist-8.onnx");

次に、イメージをfloatの配列に変換します。

blob=cv::dnn::blobFromImage(img);

データをネットにセットします。

net.setInput(blob);

そして、推論の実行をします。

cv::Mat output = net.forward();

ビルド

LinuxやMacでは先ほど使ったディレクトリでシェルから以下のコマンドを実行すればプログラムがビルドされます。

mkdir build
cd build
cmake ..
make

Windowsでビルドする場合はこんな感じでビルドします。

mkdir build
cd build
set OpenCV_DIR=C:\prog\opencv-4.10.0\build\install
cmake -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -G "MinGW Makefiles" ..
make

ビルドが成功すると以下のような感じになります。

make
Consolidate compiler generated dependencies of target test
[ 50%] Building CXX object CMakeFiles/test.dir/opencv_mnist.cpp.obj
[100%] Linking CXX executable test
[100%] Built target test```

プログラムの実行

それではビルドしたtestを実行してみます。

./test
0 : -1597.594116
1 : -2466.290771
2 : -1662.498535
3 : 727.113403
4 : -1446.075684
5 : 4535.136719
6 : 1075.813110
7 : -685.803711
8 : -195.729706
9 : 165.380707

「5」が一番確立が高く出ました。
このようにOpenCVのDNNモジュールはとても簡単にonnxを使うことができます。

おまけ

OpevCVでonnxが使えるようになると、Semantic Segmentationなども簡単にできるようになります。
Qualcomm社のサイトでは自動運転用のSemantic Segmentationのonnxモデルが公開されています。
s002.png
このモデルは最近リリースされたOpevCV4.10のDNNモジュールで動くようになりました。
これを使えばたった数十行で簡単な自動運転のプログラムを作れます。

DeepLabV3-Plus-MobileNet
https://aihub.qualcomm.com/compute/models/deeplabv3_plus_mobilenet

OpenCVのDNNモジュールを使ったMNISTでした。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?