手把手教你使用LabVIEW OpenCV DNN實現手寫數字識別(含原始碼)

virobotics發表於2022-09-30

@

前言

今天和大家一起來看一下在LabVIEW中如何使用OpenCV DNN模組實現手寫數字識別

一、OpenCV DNN模組

1.OpenCV DNN簡介

OpenCV中的DNN(Deep Neural Network module)模組是專門用來實現深度神經網路相關功能的模組。OpenCV自己並不能訓練神經網路模型,但是它可以載入別的深度學習框架(例如TensorFlow、pytorch、Caffe等等)訓練好的模型,然後使用該模型做inference(預測)。而且OpenCV在載入模型時會使用自己的DNN模組對模型重寫,使得模型的執行效率更高。所以如果你想在OpenCV專案中融入深度學習模型,可以先用自己熟悉的深度學習框架訓練好,然後使用OpenCV的DNN模組載入。

2.LabVIEW中DNN模組函式

DNN模組位於程式框圖-函式選板-Addons-VIRobotics-opencv_yiku中,如下圖所示:
在這裡插入圖片描述
Net選版中的函式與python中的函式對比如下:
在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

二、TensorFlow pb檔案的生成和呼叫

1.TensorFlow2 Keras模型(mnist)

注:本範例必須使用tensorflow 2.x版本

如下圖所示所示為資料集以及LabVIEW與Python推理和訓練程式碼,相關原始碼可在連結中下載。

在這裡插入圖片描述

2.使用Keras搭建cnn訓練mnist(train.py),訓練部分原始碼如下:

train_images = train_images.reshape(train_images.shape[0], 28, 28, 1)
test_images = test_images.reshape(test_images.shape[0], 28, 28, 1)
train_images = train_images / 255.0
test_images = test_images / 255.0

train_labels = to_categorical(train_labels, 10)
test_labels = to_categorical(test_labels, 10)

model = Sequential()  #建立一個Sequential模型
# 第一層卷積:6個卷積核, 大小:5*5, 啟用函式:relu
model.add(Conv2D(6, kernel_size=(5, 5), activation='relu', input_shape=(28, 28, 1)))
# 第二層池化:最大池化
model.add(MaxPooling2D(pool_size=(2, 2)))
# 第三層卷積:16個卷積核, 大小: 5*5, 啟用函式:relu
model.add(Conv2D(16, kernel_size=(5, 5), activation='relu'))
# 第四層池化:最大池化
model.add(MaxPooling2D(pool_size=(2, 2)))
# 進行扁平化
model.add(Flatten())
# 全連線層一:輸出節點為120個
model.add(Dense(120, activation='relu'))
# 全連線層二:輸出節點為84個
model.add(Dense(84, activation='relu'))
# 輸出層:用softmax啟用函式計算分類的機率
model.add(Dense(10, activation='softmax'))  # 最後是10個數字,10個分類
model.compile(optimizer=keras.optimizers.Adam(), loss=keras.metrics.categorical_crossentropy, metrics=['accuracy'])
model.fit(train_images, train_labels, batch_size=32, epochs=2, verbose=1)
loss, accuracy = model.evaluate(test_images, test_labels,verbose=0)
#model.save("A:\\code\\tensorflow\\course\\1_fashion_mnist\\mymodel")
print('損失:', loss)
print('準確率:', accuracy)

在這裡插入圖片描述

3.訓練結果儲存成凍結模型(pb檔案)(train.py),訓練結果儲存為凍結模型的原始碼如下:

注:無需安裝tensorflow也可以執行

#以下是生成pb的程式碼。注意:用model.save生成的pb檔案不能被opencv呼叫
# Convert Keras model to ConcreteFunction
full_model = tf.function(lambda x: model(x))
full_model = full_model.get_concrete_function(
    tf.TensorSpec(model.inputs[0].shape, model.inputs[0].dtype))

# Get frozen ConcreteFunction
frozen_func = convert_variables_to_constants_v2(full_model)
frozen_func.graph.as_graph_def()

layers = [op.name for op in frozen_func.graph.get_operations()]
print("-" * 50)
print("Frozen model layers: ")
for layer in layers:
    print(layer)

print("-" * 50)
print("Frozen model inputs: ")
print(frozen_func.inputs)
print("Frozen model outputs: ")
print(frozen_func.outputs)

# Save frozen graph from frozen ConcreteFunction to hard drive
tf.io.write_graph(graph_or_graph_def=frozen_func.graph,
                  logdir=datapath+r"\frozen_models",
                  name="frozen_graph.pb",
                  as_text=False)

執行之後可生成如下圖所示的pb模型:
在這裡插入圖片描述

4.python opencv呼叫凍結模型(cvcallpb.py)

import time
model_path = 'frozen_models\\frozen_graph.pb'
config_path = ''
#net = cv.dnn.readNetFromTensorflow(model_path, config_path)
import gzip
import os
import numpy as np
datapath=os.path.split(os.path.realpath(__file__))[0]
import cv2

def get_data():
    train_image = datapath+r"\train-images-idx3-ubyte.gz"
    test_image = datapath+r"\t10k-images-idx3-ubyte.gz"
    train_label = datapath+r"\train-labels-idx1-ubyte.gz"
    test_label = datapath+r"\t10k-labels-idx1-ubyte.gz" 
    paths = [train_label, train_image, test_label,test_image]

    with gzip.open(paths[0], 'rb') as lbpath:
        y_train = np.frombuffer(lbpath.read(), np.uint8, offset=8)

    with gzip.open(paths[1], 'rb') as imgpath:
        x_train = np.frombuffer(
            imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)

    with gzip.open(paths[2], 'rb') as lbpath:
        y_test = np.frombuffer(lbpath.read(), np.uint8, offset=8)

    with gzip.open(paths[3], 'rb') as imgpath:
        x_test = np.frombuffer(
            imgpath.read(), np.uint8, offset=16).reshape(len(y_test), 28, 28)

    return (x_train, y_train), (x_test, y_test)

(train_images, train_labels), (test_images, test_labels)=get_data()

def to_categorical(labels,number):
    a=np.zeros((labels.shape[0],number),dtype=labels.dtype)
    count=0
    for i in labels:
        a[count][i]=1
        count+=1
    return a
        
    
print(train_images.shape)
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1)
test_images = test_images.reshape(test_images.shape[0], 28, 28, 1)
train_images = train_images / 255.0
test_images = test_images / 255.0

train_labels = to_categorical(train_labels, 10)
test_labels = to_categorical(test_labels, 10)

# Load a model imported from Tensorflow
net = cv2.dnn.readNetFromTensorflow(model_path, config_path)
 

a=test_images[0].reshape(1,1,28,28)

net.setInput(a)
 
# Runs a forward pass to compute the net output
networkOutput = net.forward()
print(networkOutput)

在這裡插入圖片描述

三、LabVIEW OpenCV DNN實現手寫數字識別

1、實現手寫數字識別並實現MNIST資料簡單的視覺化(mnist_loadpb_simple.vi)

(1)讀取mnist測試資料集二進位制檔案
在這裡插入圖片描述
(2)載入pb神經網路模型
在這裡插入圖片描述
(3)從二進位制檔案裡讀取某一幅圖並顯示出來
在這裡插入圖片描述
(4)blobImage,並把blob的結果用強度圖顯示出來
在這裡插入圖片描述
(5)把blob的結果送入神經網路推理,獲取結果
在這裡插入圖片描述
(6)總體原始碼及效果如下:
在這裡插入圖片描述
在這裡插入圖片描述

2、實現手寫數字識別並實現MNIST資料高階的視覺化(mnist_loadpb.vi)

與簡單的視覺化區別僅僅有以下幾項:

(1)多了getLayerName讀出所有的網路層名字
在這裡插入圖片描述
(2)使用了多通道的forward(輸入為名稱陣列)
在這裡插入圖片描述(3)將前六層(兩次卷積——relu——池化用強度圖顯示出來)
在這裡插入圖片描述
總體原始碼如下:
在這裡插入圖片描述
執行效果如下:
在這裡插入圖片描述

四、原始碼下載

連結:https://pan.baidu.com/s/1NU_OcHgS0-5zNXQVkEt5uw
提取碼:8888

總結

Q:我該使用tensorflow 1還是tensorflow 2?
A:目前看tensorflow 1與opencv dnn模組、樹莓派等開源硬體相容性更好,且視覺物件檢測的模型暫時更豐富。Tesnroflow 2的Keras函式訓練神經網路非常方便,但對第三方軟硬體相容性還未做到最佳。估計隨著後續版本的推出,TF2會逐漸成為主流。有些新的神經網路運算元,慢慢地就不支援TF1了。同時opencv、開源硬體也會不斷更新適應最新版本的TF。
另外,訓練影像神經網路不用侷限於TF,pytorch也是很好的選擇。目前我們公司已逐漸從TF轉向pytorch了。

Q:LabVIEW的opencv及其dnn模組支援哪些硬體和神經網路模型?
A:提供多種框架模型匯入模組:包括tensorflow、pytorch、darknet、openvino等多個平臺的深度學習模型,官方的物體分類、物體檢測、語義分割、例項分割都支援(後續會講到),第三方的人臉識別、文字識別也已經透過驗證。少量的高精度例項分割模型暫時不支援,後續我們會給大家介紹ONNX工具包,支援市面上幾乎所有的模型。 支援的硬體方面,支援Nvidia GPU、Intel、TPU、NPU多種硬體加速。

更多關於LabVIEW與人工智慧技術,可新增技術交流群進一步探討。qq群號:705637299,請備註暗號:LabVIEW 機器學習

相關文章