手把手教你使用LabVIEW OpenCV dnn實現圖像分類(含源碼)

来源:https://www.cnblogs.com/virobotics/archive/2022/10/08/16768570.html
-Advertisement-
Play Games

@(文章目錄) 前言 上一篇和大家一起分享瞭如何使用LabVIEW OpenCV dnn實現手寫數字識別,今天我們一起來看一下如何使用LabVIEW OpenCV dnn實現圖像分類。 一、什麼是圖像分類? 1、圖像分類的概念 圖像分類,核心是從給定的分類集合中給圖像分配一個標簽的任務。實際上,這意 ...


@

目錄

前言

上一篇和大家一起分享瞭如何使用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 os

import cv2
import numpy as np
import tensorflow as tf
from tensorflow.keras.applications import MobileNet
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2




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)


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


def get_imagenet_labels(labels_path):
    with open(labels_path) as f:
        imagenet_labels = [line.strip() for line in f.readlines()]
    return imagenet_labels


def 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/10yO72ewfGjxAg_f07wjx0A?pwd=8888
提取碼:8888

總結

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上一節說了Spring的事務配置,其中,聲明式事務配置里有5種配置方式, @Transactional註解應該是最為常用的一種方式了。這一節就說說@Transactional註解。 @Transactional註解可以放到類名或者方法名上面, 寫在類名上面,如下: @Transactional( p ...
  • 一、概念 委托的本質也是一種類型,類似於Class這樣。作用是將一個方法作為參數傳遞給另一個方法,關鍵字是delegate 二、委托的定義使用步驟 第一步聲明委托: public delegate int myDelegate(int a, int b); 1、聲明一個委托類型,可以用訪問修飾符修飾 ...
  • 大家好,先祝大家國慶快樂。不過大家看到這篇文章的時候估計已經過完國慶了 :)。 上一篇我們寫瞭如何通過 SelfContained 模式發佈程式(不安裝運行時運行.NET程式)達到不需要在目標機器上安裝 runtime 就可以運行 .NET 程式的目標。其實除了標準的 self-contained ...
  • .NET下資料庫的負載均衡(有趣實驗)這篇文章發表後,受到了眾多讀者的關註與好評,其中不乏元老級程式員。 讀者來信中詢問最多的一個問題是:它是否能支持“異種資料庫”的負載均衡?? 今天就在此統一回覆:能(暫時只能在.Net6版本下實現。.Net Framwork版本後續會再實現。) 下麵就通過一個例 ...
  • 一:背景 1.講故事 最近遇到一位朋友的程式崩潰,發現崩潰點在富編輯器 msftedit 上,這個不是重點,重點在於發現他已經開啟了 頁堆 ,看樣子是做了最後的掙扎。 0:000> !analyze -v EXCEPTION_RECORD: (.exr -1) ExceptionAddress: 8 ...
  • 一、keepalived是什麼 Keepalived 軟體起初是專為LVS負載均衡軟體設計的,用來管理並監控LVS集群系統中各個服務節點的狀態,後來又加入了可以實現高可用的VRRP功能。因此,Keepalived除了能夠管理LVS軟體外,還可以作為其他服務(例如:Nginx、Haproxy、MySQ ...
  • 大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是一種靈活的i.MXRT下多串列NOR Flash型號選擇的量產方案。 對於以 i.MXRT 這類沒有內部 NVM (Non-Volatile Memory) 的 MCU 為主控的項目來說,為其選配一顆 NVM 作為代碼存儲器是頭等大事, ...
  • 如何設計藝術字?如何進行圖標設計?Art Text 4 Mac版是一款藝術字體製作和圖標設計軟體,它支持多圖層,可以輕鬆創造複雜圖形。可將該程式創建的圖形應用於iWork,Microsoft office、BeLight等應用程式,以及各種其他文本編輯和網頁設計程式。使用Art Text 4 Mac ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...