前言

上一篇和大家一起分享了如何应用LabVIEW OpenCV dnn实现手写数字辨认,明天咱们一起来看一下如何应用LabVIEW OpenCV dnn实现图像分类

一、什么是图像分类?

1、图像分类的概念

图像分类,外围是从给定的分类汇合中给图像调配一个标签的工作。实际上,这意味着咱们的工作是剖析一个输出图像并返回一个将图像分类的标签。标签总是来自预约义的可能类别集。
示例:咱们假设一个可能的类别集categories = {dog, cat, eagle},之后咱们提供一张图片(下图)给分类零碎。这里的指标是依据输出图像,从类别集中调配一个类别,这里为eagle,咱们的分类零碎也能够依据概率给图像调配多个标签,如eagle:95%,cat:4%,panda:1%

2、MobileNet简介

MobileNet:根本单元是深度级可拆散卷积(depthwise separable convolution),其实这种构造之前曾经被应用在Inception模型中。深度级可拆散卷积其实是一种可分解卷积操作(factorized convolutions),其能够合成为两个更小的操作:depthwise convolution和pointwise convolution,如图1所示。Depthwise convolution和规范卷积不同,对于规范卷积其卷积核是用在所有的输出通道上(input channels),而depthwise convolution针对每个输出通道采纳不同的卷积核,就是说一个卷积核对应一个输出通道,所以说depthwise convolution是depth级别的操作。而pointwise convolution其实就是一般的卷积,只不过其采纳1x1的卷积核。图2中更清晰地展现了两种操作。对于depthwise separable convolution,其首先是采纳depthwise convolution对不同输出通道别离进行卷积,而后采纳pointwise convolution将下面的输入再进行联合,这样其实整体成果和一个规范卷积是差不多的,然而会大大减少计算量和模型参数量。

MobileNet的网络结构如表所示。首先是一个3x3的规范卷积,而后前面就是沉积depthwise separable convolution,并且能够看到其中的局部depthwise convolution会通过strides=2进行down sampling。而后采纳average pooling将feature变成1x1,依据预测类别大小加上全连贯层,最初是一个softmax层。如果独自计算depthwise convolution和pointwise convolution,整个网络有28层(这里Avg Pool和Softmax不计算在内)。

二、应用python实现图像分类(py_to_py_ssd_mobilenet.py)

1、获取预训练模型

  • 应用tensorflow.keras.applications获取模型(以mobilenet为例);
from tensorflow.keras.applications import MobileNet    original_tf_model = MobileNet(        include_top=True,        weights="imagenet"    )
  • 把original_tf_model打包成pb
def get_tf_model_proto(tf_model):    # define the directory for .pb model    pb_model_path = "models"    # define the name of .pb model    pb_model_name = "mobilenet.pb"    # create directory for further converted model    os.makedirs(pb_model_path, exist_ok=True)    # get model TF graph    tf_model_graph = tf.function(lambda x: tf_model(x))    # get concrete function    tf_model_graph = tf_model_graph.get_concrete_function(        tf.TensorSpec(tf_model.inputs[0].shape, tf_model.inputs[0].dtype))    # obtain frozen concrete function    frozen_tf_func = convert_variables_to_constants_v2(tf_model_graph)    # get frozen graph    frozen_tf_func.graph.as_graph_def()    # save full tf model    tf.io.write_graph(graph_or_graph_def=frozen_tf_func.graph,                      logdir=pb_model_path,                      name=pb_model_name,                      as_text=False)    return os.path.join(pb_model_path, pb_model_name)

2、应用opencv_dnn进行推理

  • 图像预处理(blob)
def get_preprocessed_img(img_path):    # read the image    input_img = cv2.imread(img_path, cv2.IMREAD_COLOR)    input_img = input_img.astype(np.float32)    # define preprocess parameters    mean = np.array([1.0, 1.0, 1.0]) * 127.5    scale = 1 / 127.5    # prepare input blob to fit the model input:    # 1. subtract mean    # 2. scale to set pixel values from 0 to 1    input_blob = cv2.dnn.blobFromImage(        image=input_img,        scalefactor=scale,        size=(224, 224),  # img target size        mean=mean,        swapRB=True,  # BGR -> RGB        crop=True  # center crop    )    print("Input blob shape: {}\n".format(input_blob.shape))    return input_blob
  • 调用pb模型进行推理
def get_tf_dnn_prediction(original_net, preproc_img, imagenet_labels):    # inference    preproc_img = preproc_img.transpose(0, 2, 3, 1)    print("TF input blob shape: {}\n".format(preproc_img.shape))    out = original_net(preproc_img)    print("\nTensorFlow model prediction: \n")    print("* shape: ", out.shape)    # get the predicted class ID    imagenet_class_id = np.argmax(out)    print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id]))    # get confidence    confidence = out[0][imagenet_class_id]    print("* confidence: {:.4f}".format(confidence))

3、实现图像分类 (代码汇总)

import osimport cv2import numpy as npimport tensorflow as tffrom tensorflow.keras.applications import MobileNetfrom tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2def get_tf_model_proto(tf_model):    # define the directory for .pb model    pb_model_path = "models"    # define the name of .pb model    pb_model_name = "mobilenet.pb"    # create directory for further converted model    os.makedirs(pb_model_path, exist_ok=True)    # get model TF graph    tf_model_graph = tf.function(lambda x: tf_model(x))    # get concrete function    tf_model_graph = tf_model_graph.get_concrete_function(        tf.TensorSpec(tf_model.inputs[0].shape, tf_model.inputs[0].dtype))    # obtain frozen concrete function    frozen_tf_func = convert_variables_to_constants_v2(tf_model_graph)    # get frozen graph    frozen_tf_func.graph.as_graph_def()    # save full tf model    tf.io.write_graph(graph_or_graph_def=frozen_tf_func.graph,                      logdir=pb_model_path,                      name=pb_model_name,                      as_text=False)    return os.path.join(pb_model_path, pb_model_name)def get_preprocessed_img(img_path):    # read the image    input_img = cv2.imread(img_path, cv2.IMREAD_COLOR)    input_img = input_img.astype(np.float32)    # define preprocess parameters    mean = np.array([1.0, 1.0, 1.0]) * 127.5    scale = 1 / 127.5    # prepare input blob to fit the model input:    # 1. subtract mean    # 2. scale to set pixel values from 0 to 1    input_blob = cv2.dnn.blobFromImage(        image=input_img,        scalefactor=scale,        size=(224, 224),  # img target size        mean=mean,        swapRB=True,  # BGR -> RGB        crop=True  # center crop    )    print("Input blob shape: {}\n".format(input_blob.shape))    return input_blobdef get_imagenet_labels(labels_path):    with open(labels_path) as f:        imagenet_labels = [line.strip() for line in f.readlines()]    return imagenet_labelsdef get_opencv_dnn_prediction(opencv_net, preproc_img, imagenet_labels):    # set OpenCV DNN input    opencv_net.setInput(preproc_img)    # OpenCV DNN inference    out = opencv_net.forward()    print("OpenCV DNN prediction: \n")    print("* shape: ", out.shape)    # get the predicted class ID    imagenet_class_id = np.argmax(out)    # get confidence    confidence = out[0][imagenet_class_id]    print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id]))    print("* confidence: {:.4f}\n".format(confidence))def get_tf_dnn_prediction(original_net, preproc_img, imagenet_labels):    # inference    preproc_img = preproc_img.transpose(0, 2, 3, 1)    print("TF input blob shape: {}\n".format(preproc_img.shape))    out = original_net(preproc_img)    print("\nTensorFlow model prediction: \n")    print("* shape: ", out.shape)    # get the predicted class ID    imagenet_class_id = np.argmax(out)    print("* class ID: {}, label: {}".format(imagenet_class_id, imagenet_labels[imagenet_class_id]))    # get confidence    confidence = out[0][imagenet_class_id]    print("* confidence: {:.4f}".format(confidence))def main():    # configure TF launching    #set_tf_env()    # initialize TF MobileNet model    original_tf_model = MobileNet(        include_top=True,        weights="imagenet"    )    # get TF frozen graph path    full_pb_path = get_tf_model_proto(original_tf_model)    print(full_pb_path)    # read frozen graph with OpenCV API    opencv_net = cv2.dnn.readNetFromTensorflow(full_pb_path)    print("OpenCV model was successfully read. Model layers: \n", opencv_net.getLayerNames())    # get preprocessed image    input_img = get_preprocessed_img("yaopin.png")    # get ImageNet labels    imagenet_labels = get_imagenet_labels("classification_classes.txt")    # obtain OpenCV DNN predictions    get_opencv_dnn_prediction(opencv_net, input_img, imagenet_labels)    # obtain TF model predictions    get_tf_dnn_prediction(original_tf_model, input_img, imagenet_labels)if __name__ == "__main__":    main()

三、应用LabVIEW dnn实现图像分类(callpb_photo.vi)本博客中所用实例基于LabVIEW2018版本,调用mobilenet pb模型1、读取待分类的图片和pb模型

2、将待分类的图片进行预处理

3、将图像输出至神经网络中并进行推理

4、实现图像分类

5、总体程序源码:依照如下图所示程序进行编码,实现图像分类,本范例中应用了一分类,分类出置信度最高的物体。

如下图所示为加载药瓶图片失去的分类后果,在前面板能够看到图片和label:


四、源码下载链接:https://pan.baidu.com/s/10yO7...
提取码:8888 总结更多对于LabVIEW与人工智能技术,可增加技术交换群进一步探讨。qq群号:705637299,请备注暗号:LabVIEW 机器学习