c++opencv調用tensorflow模型(以mnist爲例)

c++opencv調用tensorflow模型(以mnist爲例)

0. 環境

win10 + vs2019 + opencv(OpenCV_VERSION 3.4.6) + keras(tensorflow後端)

1. 準備數據

從http://yann.lecun.com/exdb/mnist/下載
“data/t10k-labels-idx1-ubyte.gz”;
“data/t10k-images-idx3-ubyte.gz”;
“data/train-labels-idx1-ubyte.gz”;
“data/train-images-idx3-ubyte.gz”;

用解壓文件直接解壓爲以下文件
“data/t10k-labels-idx1-ubyte”;
“data/t10k-images-idx3-ubyte”;
“data/train-labels-idx1-ubyte”;
“data/train-images-idx3-ubyte”;

2. 讀取mnist文件

使用C++和OpenCV讀取MNIST文件[https://blog.csdn.net/sheng_ai/article/details/23267039]
(代碼可以直接使用)

3. python下使用keras生成tensorflow pb模型

#%%
from keras.datasets import mnist
from keras.models import Model
from keras.layers import Conv2D, MaxPool2D, ReLU, Input, Softmax, Reshape
from keras import backend as K
import tensorflow as tf 

#%%
tf.reset_default_graph()
#%%

def net(input_size, optimizer):
    input_x = Input(input_size, name="x")
    conv1 = Conv2D(20, 5, padding = 'same', kernel_initializer = 'he_normal')(input_x)
    pool1 = MaxPool2D(2)(conv1)
    relu1 = ReLU()(pool1)

    conv2 = Conv2D(50, 5, padding = 'same', kernel_initializer = 'he_normal')(relu1)
    pool2 = MaxPool2D(2)(conv2)
    relu2 = ReLU()(pool2)

    conv3 = Conv2D(10, 5, padding = 'same', kernel_initializer = 'he_normal')(relu2)
    pool3 = MaxPool2D(7)(conv3)

    out = Reshape([10])(pool3)

    out = Softmax(name="output")(out)

    model = Model(inputs=input_x, outputs = out)
    model.compile(
        optimizer=optimizer,
        loss = "categorical_crossentropy",
        metrics=["accuracy"]
    )

    return model


(train_x, train_y), (test_x, test_y) = mnist.load_data()

train_x = train_x.reshape(train_x.shape[0], 28, 28, 1) / 255
test_x = test_x.reshape(test_x.shape[0], 28, 28, 1) / 255

train_y = np_utils.to_categorical(train_y, num_classes=10)
test_y = np_utils.to_categorical(test_y, num_classes=10)

rmsprop = keras.optimizers.RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0)
model = net([28, 28, 1], rmsprop)

#%%
print(model.summary())

#%%
print("Training --------------")
model.fit(train_x, train_y, epochs=4, batch_size=32)

print("Testing --------------")
loss, accuracy = model.evaluate(test_x, test_y)

print("test loss: ", loss)
print("test accuracy: ", accuracy)

# 查看所有節點
# tensor_name_list = [tensor.name for tensor in tf.get_default_graph().as_graph_def().node]
# print(tensor_name_list)

#%%
# 輸出Pb模型
sess = K.get_session()
frozen_graph = tf.compat.v1.graph_util.convert_variables_to_constants(
    sess,
    sess.graph_def,
    output_node_names=["output/Softmax"]
)

tf.train.write_graph(frozen_graph, "log/1.2", "mnist.pb", as_text=False)

輸出結果爲:

Epoch 1/4
60000/60000 [==============================] - 13s 216us/step - loss: 0.2229 - acc: 0.9322
Epoch 2/4
60000/60000 [==============================] - 10s 167us/step - loss: 0.0754 - acc: 0.9767
Epoch 3/4
60000/60000 [==============================] - 10s 167us/step - loss: 0.0550 - acc: 0.9828
Epoch 4/4
60000/60000 [==============================] - 10s 168us/step - loss: 0.0450 - acc: 0.9859
Testing --------------
10000/10000 [==============================] - 1s 62us/step
test loss:  0.05498976424507564
test accuracy:  0.9838

4. c++ + opencv讀取pb模型, 驗證測試集

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>

#include "MNIST.h"

std::vector<int> Argmax(cv::Mat x)
{
	std::vector<int> res;
	for (int i = 0; i < x.rows; i++)
	{
		int maxIdx = 0;
		float maxNum = 0.0;
		for (int j = 0; j < x.cols; j++)
		{
			float tmp = x.at<float>(i, j);
			if (tmp > maxNum)
			{
				maxIdx = j;
				maxNum = tmp;

			}
		}
		res.push_back(maxIdx);
	}

	return res;
}

float Accuracy(cv::Mat x, cv::Mat y, std::string pbfile)
{
	float count = 0.0;
	
	cv::dnn::Net net = cv::dnn::readNetFromTensorflow(pbfile);

    // blob輸入時需要至少dims爲3的數據, 其數據形狀爲(圖片數目, 寬度, 高度)
	int size[] = { x.rows, 28, 28 };
	cv::Mat imgs = cv::Mat(3, size, CV_8UC1, x.data);

	cv::Mat blob = cv::dnn::blobFromImages(imgs, 1.0 / 255.0, cv::Size(28, 28), cv::Scalar(), false, false);
	net.setInput(blob);
	cv::Mat pred = net.forward();

	std::vector<int> res = Argmax(pred);

	for (int i = 0; i < res.size(); i++)
	{
		if (*(y.ptr<int>(0) + i) == res[i])
			{
				count = count + 1;
			}
	}
	return count / x.rows;


}

int main()
{
	std::string testLableFile = "data/t10k-labels-idx1-ubyte";
	std::string testImageFile = "data/t10k-images-idx3-ubyte";

	std::string trainLableFile = "data/train-labels-idx1-ubyte";
	std::string trainImageFile = "data/train-images-idx3-ubyte";


	cv::Mat trainY = ReadLabels(trainLableFile);
	cv::Mat testY = ReadLabels(testLableFile);

	cv::Mat trainX = ReadImages(trainImageFile);	
	cv::Mat testX = ReadImages(testImageFile);
	

	testY.convertTo(testY, CV_32SC1);

	std::string pbfile = "mnist.pb";
	//testX.convertTo(testX, CV_32FC1, 1.0/255.0, 0);
	float acc = Accuracy(testX, testY, pbfile);
	std::cout << acc;
	return 0;
}

控制檯輸出爲:

[ INFO:0] Initialize OpenCL runtime...
0.9838
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章