電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>電子資料>帶有Seeed reTerminal的表面裂紋檢測(cè)和定位

帶有Seeed reTerminal的表面裂紋檢測(cè)和定位

2022-10-24 | zip | 0.05 MB | 次下載 | 2積分

資料介紹

描述

概述

2022 年 1 月 28 日,匹茲堡(賓夕法尼亞州)一座有 50 年歷史的橋梁倒塌。混凝土橋等堅(jiān)固結(jié)構(gòu)突然倒塌的原因只有一個(gè):磨損。

混凝土結(jié)構(gòu)通常在大約 40 到 50 年后開(kāi)始惡化。因此,忽視磨損跡象可能會(huì)導(dǎo)致嚴(yán)重事故,這就是為什么混凝土結(jié)構(gòu)的檢查和維修對(duì)于保護(hù)我們的生活方式至關(guān)重要。裂縫是用于診斷混凝土結(jié)構(gòu)劣化的重要標(biāo)準(zhǔn)之一。通常,專家會(huì)通過(guò)目視檢查裂縫、勾畫(huà)檢查結(jié)果,然后根據(jù)他們的發(fā)現(xiàn)準(zhǔn)備檢查數(shù)據(jù)來(lái)檢查此類結(jié)構(gòu)。像這樣的檢查方法不僅非常耗時(shí)和昂貴,而且不能準(zhǔn)確地檢測(cè)到裂縫。在這個(gè)項(xiàng)目中,我使用機(jī)器學(xué)習(xí)構(gòu)建了一個(gè)表面裂紋檢測(cè)應(yīng)用程序。

為什么要本地化?

為什么我們要使用圖像分類模型來(lái)定位檢測(cè)?我們不能使用對(duì)象檢測(cè)模型嗎?是的,我們可以使用對(duì)象檢測(cè)模型,但我們需要手動(dòng)將邊界框添加到數(shù)千個(gè)樣本中。現(xiàn)有的對(duì)象檢測(cè)模型可能不是自動(dòng)注釋這些裂縫的好選擇,因?yàn)樗鼈兪窃诖_定形狀的對(duì)象上訓(xùn)練的。重新利用分類模型來(lái)定位檢測(cè)可以節(jié)省大量精力,并且仍然能夠識(shí)別感興趣的區(qū)域。

它是如何工作的?

具有已針對(duì)分類任務(wù)訓(xùn)練的 GAP(全局平均池化)層的 CNN(卷積神經(jīng)網(wǎng)絡(luò))也可用于對(duì)象定位。也就是說(shuō),GAP-CNN 不僅可以告訴我們圖像中包含什么對(duì)象 - 它還可以告訴我們對(duì)象在圖像中的位置,并且無(wú)需我們進(jìn)行額外的工作!定位表示為熱圖(類激活圖),其中顏色編碼方案識(shí)別對(duì) GAP-CNN 執(zhí)行對(duì)象識(shí)別任務(wù)相對(duì)重要的區(qū)域。

硬件設(shè)置

由于我想要一個(gè)緊湊且便攜的硬件設(shè)置,我們將使用 Seeed reTerminal,它帶有一個(gè)緊湊形式的 LCD 和按鈕。它由具有 4 GB RAM 的 Raspberry Pi 4 Compute 模塊提供支持,這對(duì)于這個(gè)概念驗(yàn)證項(xiàng)目來(lái)說(shuō)已經(jīng)足夠了。我們需要 Raspberry Pi Camera V2 和一個(gè)亞克力支架。

poYBAGNR5cWADdo8AAeE6zMdI_E65.jpeg
?

我們需要打開(kāi) reTerminal 的后蓋才能訪問(wèn) 15 針 FPC 攝像頭連接器。請(qǐng)按照此處的分步說(shuō)明進(jìn)行操作:https://wiki.seeedstudio.com/reTerminal。

pYYBAGNR5ciACoG-AAR1HjRxUuQ11.jpeg
?

相機(jī)使用 FPC 帶狀電纜連接,并使用底座連接到重新終端。

poYBAGNR5cyAdWgyAAhnMYNXU_o21.jpeg
?

設(shè)置開(kāi)發(fā)環(huán)境

reTerminal 配備 32 位 Raspberry Pi 操作系統(tǒng),但我們將使用 64 位 Raspberry Pi 操作系統(tǒng)以獲得更好的性能。

要安裝我們將在推理代碼中使用的 python 包,請(qǐng)執(zhí)行以下命令。

$ sudo pip3 install seeed-python-reterminal
$ sudo apt install -y libhdf5-dev python3-pyqt5 libatlas-base-dev
$ pip3 install opencv-contrib-python==4.5.3.56
$ pip3 install matplotlib

數(shù)據(jù)采集

數(shù)據(jù)集是從 Mendeley Data (Concrete Crack Images for Classification) 下載的。數(shù)據(jù)集包含有裂縫和沒(méi)有裂縫的各種混凝土表面。數(shù)據(jù)是從多個(gè) METU 校園建筑中收集的。將數(shù)據(jù)集分為正反兩幅裂紋圖像進(jìn)行圖像分類。每個(gè)類有 20,000 張圖像,總共 40,000 張圖像,227 x 227 像素,RGB 通道。

pYYBAGNR5c-ANEu5AAN94qhIvOM219.png
?

為了將裂紋和非裂紋表面圖像與其他自然世界場(chǎng)景區(qū)分開(kāi)來(lái),下載了來(lái)自 COCO-Minitrain(COCO train2017 數(shù)據(jù)集的子集)的 80 個(gè)對(duì)象類別的 25,000 張隨機(jī)采樣圖像。可以從下面的鏈接訪問(wèn)數(shù)據(jù)。

  • 表面裂紋數(shù)據(jù)集:
  • COCO-Minitrain 數(shù)據(jù)集

將數(shù)據(jù)上傳到 Edge Impulse Studio

我們需要?jiǎng)?chuàng)建一個(gè)新項(xiàng)目來(lái)將數(shù)據(jù)上傳到 Edge Impulse Studio。

poYBAGNR5dKACjQbAADLJrcTCg0459.png
?

使用 Edge Impulse CLI 上傳數(shù)據(jù)。請(qǐng)按照說(shuō)明在此處安裝 CLI:

下載的圖像被標(biāo)記為 3 類,并保存到帶有標(biāo)簽名稱的目錄中。

  • 正面- 有裂紋的表面
  • 負(fù)片——表面無(wú)裂紋
  • 未知- 來(lái)自 80 個(gè)對(duì)象的圖像

執(zhí)行以下命令將圖像上傳到 Edge Impulse Studio。數(shù)據(jù)集會(huì)自動(dòng)拆分為訓(xùn)練和測(cè)試數(shù)據(jù)集。

$ edge-impulse-uploader --category split  --label positive positive/*.jpg
$ edge-impulse-uploader --category split  --label negative negative/*.jpg
$ edge-impulse-uploader --category split  --label unknown  unknown/*.jpg

我們可以在 Edge Impulse Studio 的數(shù)據(jù)采集頁(yè)面上看到上傳的數(shù)據(jù)集。

poYBAGNR5dSAXUwlAAFnXenQzgo443.png
?

訓(xùn)練

進(jìn)入Impulse Design > Create Impulse頁(yè)面,單擊Add a processing block ,然后選擇Image ,它對(duì)圖像數(shù)據(jù)進(jìn)行預(yù)處理和標(biāo)準(zhǔn)化,并可選擇降低顏色深度。此外,在同一頁(yè)面上,單擊Add a learning block ,然后選擇Transfer Learning (Images ),這會(huì)在數(shù)據(jù)上微調(diào)預(yù)訓(xùn)練的圖像分類模型。我們使用的是 160x160 的圖像尺寸。現(xiàn)在單擊保存脈沖按鈕。

pYYBAGNR5deAXGH1AAGKOxKpsMo538.png
?

接下來(lái),轉(zhuǎn)到Impulse Design > Image頁(yè)面并將顏色深度參數(shù)設(shè)置為 RGB,然后單擊Save parameters按鈕,該按鈕將重定向到另一個(gè)頁(yè)面,我們應(yīng)該單擊Generate Feature按鈕。完成特征生成通常需要幾分鐘。

pYYBAGNR5dmADmtjAAAnsPuDmvo526.png
?

我們可以在 Feature Explorer 中看到生成的特征的 2D 可視化。

pYYBAGNR5dyAYUyMAAEdAbUIRyw455.png
?

?

現(xiàn)在轉(zhuǎn)到Impulse Design > Transfer Learning頁(yè)面并選擇神經(jīng)網(wǎng)絡(luò)架構(gòu)。我們使用MobileNetV2 160x160 1.0遷移學(xué)習(xí)模型和 Edge Impulse Studio 提供的預(yù)訓(xùn)練權(quán)重。

poYBAGNR5d-AQSzAAAFPZMAZN0A945.png
?

預(yù)訓(xùn)練模型輸出類預(yù)測(cè)概率。要獲得類激活圖,我們需要修改模型并使其成為多輸出模型。要自定義模型,我們需要切換到Keras(專家)模式。

pYYBAGNR5eGAA2H0AACoM4IY5AA479.png
?

我們可以在文本編輯器中修改生成的代碼,如下所示。

pYYBAGNR5eSAVEp7AAHLJVThu44396.png
?

我們將使用 3 個(gè)神經(jīng)元(在我們的例子中為 3 個(gè)類)將作為 GAP 層的最后第二層連接到 Dense 層。稍后我們將使用這個(gè) Dense 層權(quán)重來(lái)生成類激活圖。

base_model = tf.keras.applications.MobileNetV2(
    input_shape = INPUT_SHAPE, alpha=1,
    weights = WEIGHTS_PATH
)
last_layer  = base_model.layers[-2].output
dense_layer = Dense(classes)
output_pred = Softmax(name="prediction")(dense_layer(last_layer))

對(duì)于類激活圖,我們需要計(jì)算最后一個(gè)卷積塊輸出和最終密集層權(quán)重的點(diǎn)積。Keras Dot 層不廣播具有動(dòng)態(tài)批量大小的乘數(shù)向量,因此我們不能使用它。但是我們可以利用Dense 層,它在內(nèi)部將內(nèi)核權(quán)重與輸入進(jìn)行點(diǎn)積。這種方法有一個(gè)副作用,密集層將偏置權(quán)重添加到每個(gè)點(diǎn)積。但是這個(gè)偏差權(quán)重非常小,不會(huì)改變類激活圖的最終歸一化值,所以我們可以毫無(wú)問(wèn)題地使用它。

conv_layer  = base_model.layers[-4].output
reshape_layer = Reshape((conv_layer.shape[1] * conv_layer.shape[2] , -1))(conv_layer)
dot_output = dense_layer(reshape_layer)

我們需要將點(diǎn)積輸出重新采樣到與輸入圖像(160x160)相同的大小,以便我們可以覆蓋熱圖。為此,我們使用UpSampling2D 層。

transpose = Permute((2, 1))(dot_output)
reshape_2_layer = Reshape((-1, conv_layer.shape[1] , conv_layer.shape[2]))(transpose)
SIZE = (int(INPUT_SHAPE[1] / conv_layer.shape[2]), 
 int(INPUT_SHAPE[0] / conv_layer.shape[1]))
output_act_map = UpSampling2D(size=SIZE, interpolation="bilinear", data_format="channels_first", name="activation_map")(reshape_2_layer)
model = Model(inputs=base_model.inputs, outputs=[output_pred, output_act_map])

此外,我們將從最后兩個(gè)卷積塊訓(xùn)練模型,并在此之前凍結(jié)所有層。

TRAINABLE_START_IDX = -12
for layer in model.layers[:TRAINABLE_START_IDX]:
    layer.trainable = False

下面給出了最后一個(gè)卷積塊之后的修改網(wǎng)絡(luò)架構(gòu)。這是一個(gè)多輸出模型,其中第一個(gè)輸出提供預(yù)測(cè)類概率,第二個(gè)輸出提供類激活圖。

poYBAGNR5eaATd69AACVXIe4IX4021.png
?

完整修改后的訓(xùn)練代碼如下。

import math
from pathlib import Path
import tensorflow as tf
from tensorflow.keras import Model
from tensorflow.keras.layers import Dense, UpSampling2D, Permute, Reshape, Softmax
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.losses import categorical_crossentropy

sys.path.append('./resources/libraries')
import ei_tensorflow.training

WEIGHTS_PATH = './transfer-learning-weights/keras/mobilenet_v2_weights_tf_dim_ordering_tf_kernels_1.0_160.h5'

INPUT_SHAPE = (160, 160, 3)

base_model = tf.keras.applications.MobileNetV2(
    input_shape = INPUT_SHAPE, alpha=1,
    weights = WEIGHTS_PATH
)

last_layer  = base_model.layers[-2].output
dense_layer = Dense(classes)
output_pred = Softmax(name="prediction")(dense_layer(last_layer))


conv_layer  = base_model.layers[-4].output
reshape_layer = Reshape((conv_layer.shape[1] * conv_layer.shape[2] , -1))(conv_layer)

dot_output = dense_layer(reshape_layer)
transpose = Permute((2, 1))(dot_output)
reshape_2_layer = Reshape((-1, conv_layer.shape[1] , conv_layer.shape[2]))(transpose)

SIZE = (int(INPUT_SHAPE[1] / conv_layer.shape[2]), 
 int(INPUT_SHAPE[0] / conv_layer.shape[1]))

output_act_map = UpSampling2D(size=SIZE, interpolation="bilinear", data_format="channels_first", name="activation_map")(reshape_2_layer)

model = Model(inputs=base_model.inputs, outputs=[output_pred, output_act_map])

TRAINABLE_START_IDX = -12
for layer in model.layers[:TRAINABLE_START_IDX]:
    layer.trainable = False

model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.0005),
      loss={'prediction': 'categorical_crossentropy', 'activation_map': None},
      metrics={'prediction': ['accuracy'], 'activation_map': [None]})
                
BATCH_SIZE = 32
EPOCHS=5

train_dataset = train_dataset.batch(BATCH_SIZE, drop_remainder=False)

validation_dataset = validation_dataset.batch(BATCH_SIZE, drop_remainder=False)

callbacks.append(BatchLoggerCallback(BATCH_SIZE, train_sample_count, epochs=EPOCHS))

model.fit(train_dataset, validation_data=validation_dataset, epochs=EPOCHS, verbose=2, callbacks=callbacks)

現(xiàn)在單擊“開(kāi)始訓(xùn)練”按鈕并等待大約 30 分鐘,直到訓(xùn)練完成。我們可以在下面看到訓(xùn)練輸出。量化的(int8)模型有 99.6% 的準(zhǔn)確率,相當(dāng)不錯(cuò)。

pYYBAGNR5emAaCsXAAB7xkIF5Xw504.png
?

模型部署

目前,Edge Impulse for Linux SDK 不支持多輸出模型,因此我們將使用編譯后的 TensorFlow Lite 運(yùn)行時(shí)進(jìn)行推理。這個(gè)僅解釋器的包是完整 TensorFlow 包大小的一小部分,并且包含使用 TensorFlow Lite 運(yùn)行推理所需的最少代碼。為了加速推理,TFLite 解釋器可以與 XNNPACK 一起使用,XNNPACK是針對(duì) ARM 和其他平臺(tái)的高度優(yōu)化的神經(jīng)網(wǎng)絡(luò)推理算子庫(kù)。要為 64 位 Raspberry Pi OS啟用XNNPACK ,我們需要從源代碼構(gòu)建 TFLite Runtime Python 包。我們需要在速度更快的 Debian/Ubuntu Linux 機(jī)器上使用 Docker 執(zhí)行以下命令來(lái)交叉編譯和構(gòu)建包。

$ git clone -b v2.9.0 https://github.com/tensorflow/tensorflow.git
cd tensorflow/

$ curl -L -o tensorflow/tools/ci_build/Dockerfile.pi-python37 https://github.com/tensorflow/tensorflow/raw/v2.8.0/tensorflow/tools/ci_build/Dockerfile.pi-python37

$ sed -i -e 's/FROM ubuntu:16.04/FROM ubuntu:18.04/g' tensorflow/tools/ci_build/Dockerfile.pi-python37

$ sed -i '30a apt-get update && apt-get install -y dirmngr' tensorflow/tools/ci_build/install/install_deb_packages.sh

$ sed -i -e 's/xenial/bionic/g' tensorflow/tools/ci_build/install/install_pi_python3x_toolchain.sh

為浮點(diǎn) (F32) 和量化 (INT8) 模型啟用XNNPACK ,請(qǐng)將以下行(以粗體顯示)添加到 tensorflow/lite/tools/pip_package/build_pip_package_with_bazel.sh 文件中。

aarch64)
BAZEL_FLAGS="--config=elinux_aarch64
--define tensorflow_mkldnn_contraction_kernel=0
--define=tflite_with_xnnpack=true
--define=tflite_with_xnnpack_qs8=true
--copt=-O3"
;;

執(zhí)行以下命令構(gòu)建 pip 包。

$ sudo CI_DOCKER_EXTRA_PARAMS="-e CI_BUILD_PYTHON=python3.7 -e CROSSTOOL_PYTHON_INCLUDE_PATH=/usr/include/python3.7"  tensorflow/tools/ci_build/ci_build.sh PI-PYTHON37  tensorflow/lite/tools/pip_package/build_pip_package_with_bazel.sh aarch64

將 pip 包復(fù)制到 reTerminal。

$ scp tensorflow/lite/tools/pip_package/gen/tflite_pip/python3.7/dist/tflite_runtime-2.9.0-cp37-cp37m-linux_aarch64.whl pi@raspberrypi.local:/home/pi

要安裝軟件包,請(qǐng)執(zhí)行以下命令。

$ pip3 install -U tflite_runtime-2.9.0-cp37-cp37m-linux_aarch64.whl

現(xiàn)在我們可以從 Edge Impulse Studio Dashboard 下載量化模型。

poYBAGNR5euAfOFrAAC9nCvTsNE790.png
?

下面是用于推理的完整 Python 腳本。

#!/usr/bin/python3

import sys
import signal
import time
import cv2
import numpy as np
import traceback
import threading
import logging
import queue
import collections
import matplotlib.pyplot as plt
from matplotlib import cm
from tflite_runtime.interpreter import Interpreter

def avg_fps_counter(window_size):
    window = collections.deque(maxlen=window_size)
    prev = time.monotonic()
    yield 0.0  # First fps value.

    while True:
        curr = time.monotonic()
        window.append(curr - prev)
        prev = curr
        yield len(window) / sum(window)

def sigint_handler(sig, frame):
    logging.info('Interrupted')
    sys.exit(0)

signal.signal(signal.SIGINT, sigint_handler)

def capture(queueIn):
    global terminate
    global zoom
    videoCapture = cv2.VideoCapture(0)

    if not videoCapture.isOpened():
        logging.error("Cannot open camera")
        sys.exit(-1)

    while True:
        if terminate:
            logging.info("Capture terminate")
            break

        prev = time.time()
        try:
            success, frame = videoCapture.read()
            if success:
                frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
                img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

                if zoom:
                    w, h = 320, 320
                    x = (img.shape[1] - w) / 2
                    y = (img.shape[0] - h)/ 2
                    img = img[int(y):int(y+h), int(x):int(x+w)]

                img = cv2.resize(img, (width, height))
                img = img / 255.0
                img = img.astype(np.float32)
                img_scaled = (img / input_scale) + input_zero_point
                input_data = np.expand_dims(img_scaled, axis=0).astype(input_details[0]["dtype"])

                if not queueIn.full():
                    queueIn.put((img, input_data))
                    logging.info('Image Captured')
            else:
                raise RuntimeError('Failed to get frame!')
        except Exception as inst:
            logging.error("Exception", inst)
            logging.error(traceback.format_exc())
            videoCapture.release()
            break

def inferencing(interpreter, queueIn, queueOut):
    global terminate
    global show_heatmap

    while True:
        if terminate:
            logging.info("Inferencing terminate")
            break
        start_time = time.time()
        try:
            if queueIn.empty():
                time.sleep(0.01)
                continue

            img, input_data = queueIn.get()
            interpreter.set_tensor(input_details[0]['index'], input_data)
            interpreter.invoke()

            output_0_tensor = interpreter.tensor(output_details[0]['index'])
            output_1_tensor = interpreter.tensor(output_details[1]['index'])

            output_1 = output_1_scale * ((output_1_tensor()).astype(np.float32) - output_1_zero_point)

            pred_class = np.argmax(np.squeeze(output_1))
            pred_score = np.squeeze(output_1)[pred_class]

            dp_out = None

            if pred_class == 1 and show_heatmap is True :
                dp_out = output_0_scale * (np.squeeze(output_0_tensor())[pred_class].astype(np.float32) - output_0_zero_point)

            if not queueOut.full():
                queueOut.put((img, pred_class, pred_score, dp_out))
        except Exception as inst:
            logging.error("Exception", inst)
            logging.error(traceback.format_exc())
            break
        
        logging.info('Inferencing time: {:.3f}ms'.format((time.time() - start_time) * 1000))

def display(queueOut):
    global show_heatmap
    global zoom
    global terminate

    dimension = (960, 720)
    ei_logo = cv2.imread('/home/pi/surface_crack_detection/ei_logo.jpg')
    ei_logo = cv2.cvtColor(ei_logo, cv2.COLOR_BGR2RGB)
    ei_logo = ei_logo / 255.0
    ei_logo = ei_logo.astype(np.float32)
    ei_logo = cv2.copyMakeBorder(ei_logo, 0, dimension[1] - ei_logo.shape[0], 70, 70, cv2.BORDER_CONSTANT, None, (255, 255, 255))  
    ei_logo = cv2.copyMakeBorder(ei_logo, 0, dimension[1] - ei_logo.shape[0], 70, 70, cv2.BORDER_CONSTANT, None, (255, 255, 255))  
    
    fps_counter = avg_fps_counter(30)

    while True:
        if queueOut.empty():
            time.sleep(0.2)
            continue

        start_time = time.time()
        img, pred_class, pred_score, dp_out = queueOut.get()

        if pred_class == 1:
            label = 'Crack'
            color = (0, 0, 255)

            if show_heatmap and dp_out is not None:
                heatmap = None
                heatmap = cv2.normalize(dp_out, heatmap, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
                colormap = plt.get_cmap('jet')
                img = cv2.addWeighted(img, 1.0, colormap(heatmap).astype(np.float32)[:,:,:3], 0.4, 0)
        else:
            if pred_class == 0:
                label = 'No Crack'
                color = (0, 0, 0)
            else:
                label = 'Unknown'
                color = (255, 0,  0)
        
        final_img = cv2.resize(img, dimension, interpolation=cv2.INTER_CUBIC) 

        font  = cv2.FONT_HERSHEY_SIMPLEX 
        final_img = np.hstack((final_img, ei_logo))
        final_img = cv2.cvtColor(final_img, cv2.COLOR_RGB2BGR)
        final_img = cv2.putText(final_img, label, (980, 200), font, 2, color, 3, cv2.LINE_AA)
        final_img = cv2.putText(final_img, f'({pred_score*100:0.1f}%)', (980, 280), font, 2, (0, 0, 0), 3, cv2.LINE_AA)

        fps = round(next(fps_counter))

        final_img = cv2.putText(final_img, f'Fps:{fps}', (980, 360), font, 2, (0, 0, 0), 3, cv2.LINE_AA)
        final_img = cv2.putText(final_img, f'Heat:{"On" if show_heatmap else "Off"}', (980, 440), font, 2, (0, 0, 0), 3, cv2.LINE_AA)
        final_img = cv2.putText(final_img, f'Crop:{"On" if zoom else "Off"}', (980, 520), font, 2, (0, 0, 0), 3, cv2.LINE_AA)

        window_name = "Edge Impulse Inferencing"
        cv2.imshow(window_name, final_img)


        key = cv2.waitKey(1)  
        if key == ord('a'):
            show_heatmap  = not show_heatmap
            logging.info(f"Heatmap: {show_heatmap}")

        if key == ord('s'):
            zoom  = not zoom
            logging.info(f"Zoom: {zoom}")

        if key == ord('f'):
            terminate = True
            logging.info("Display Terminate")
            break

        logging.info('Display time: {:.3f}ms'.format((time.time() - start_time) * 1000))
        

if __name__ == '__main__':
    log_fmt = "%(asctime)s: %(message)s"
    logging.basicConfig(format=log_fmt, level=logging.ERROR,)

    model_file = '/home/pi/surface_crack_detection/model/quantized-model.lite'
    interpreter = Interpreter(model_path=model_file, num_threads=2)
    interpreter.allocate_tensors()

    input_details  = interpreter.get_input_details()
    #logging.debug(input_details)
    output_details = interpreter.get_output_details()

    height = input_details[0]['shape'][1]
    width  = input_details[0]['shape'][2]
    input_scale, input_zero_point = input_details[0]['quantization']
    output_0_scale, output_0_zero_point = output_details[0]['quantization']
    output_1_scale, output_1_zero_point = output_details[1]['quantization']

    queueIn  = queue.Queue(maxsize=1)
    queueOut  = queue.Queue(maxsize=1)
    show_heatmap = False
    zoom = False
    terminate = False

    t1 = threading.Thread(target=capture, args=(queueIn,), daemon=True)
    t2 = threading.Thread(target=inferencing, args=(interpreter, queueIn, queueOut), daemon=True)
    t3 = threading.Thread(target=display, args=(queueOut,), daemon=True)

    t1.start()
    logging.info("Thread start: 1")
    t2.start()
    logging.info("Thread start: 2")
    t3.start()
    logging.info("Thread start: 3")

    t1.join()
    t2.join()
    t3.join()

申請(qǐng)工作流程圖

該應(yīng)用程序使用多線程來(lái)使用 Raspberry Pi 4 計(jì)算模塊上的所有可用 4 核,以實(shí)現(xiàn)低延遲和更好的 FPS。

pYYBAGNR5e2ATBdNAABPDeFM7go082.png
?

桌面應(yīng)用程序

通過(guò)單擊桌面應(yīng)用程序圖標(biāo)來(lái)執(zhí)行推理腳本,該圖標(biāo)是通過(guò)在 /home/pi/Desktop 目錄中添加 ei.desktop 文件而創(chuàng)建的。

[Desktop Entry]
Version=1.0
Comment=Run Inferencing Quantized Model
Terminal=false
Name=Surface Crack Detection
Exec=/home/pi/surface_crack_detection/surface_crack_detection_quant.py
Type=Application
Icon=/home/pi/surface_crack_detection/images/ei_logo.jpg
poYBAGNR5fKAVSTEAAoKtWob7TU83.jpeg
?

此外,reTerminal 前面板按鈕(在上圖中)用于以下功能。

  • F1按鈕:切換熱圖
  • F2按鈕:切換中心裁剪(放大)預(yù)覽圖像
  • O按鈕:關(guān)閉應(yīng)用程序

推理演示

?

結(jié)論

該項(xiàng)目展示了可用于預(yù)測(cè)性維護(hù)的表面裂紋檢測(cè)工業(yè)用例。該項(xiàng)目具有以下主要特點(diǎn)。

  • 在 Edge Impulse Studio 專家模式下自定義預(yù)訓(xùn)練的遷移學(xué)習(xí)模型
  • 演示如何使用使用 Edge Impulse 訓(xùn)練的多輸出模型
  • 運(yùn)行時(shí)熱圖可視化以定位檢測(cè)到的裂縫。
  • 多線程應(yīng)用程序以提高 FPS
  • 可擴(kuò)展的便攜式解決方案

盡管該項(xiàng)目是使用 Raspberry Pi 4 計(jì)算模塊創(chuàng)建的,但它可以輕松移植到更高規(guī)格的邊緣設(shè)備,以提高 FPS 和實(shí)時(shí)檢測(cè)。


下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評(píng)論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數(shù)據(jù)手冊(cè)
  2. 1.06 MB  |  532次下載  |  免費(fèi)
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費(fèi)
  5. 3TC358743XBG評(píng)估板參考手冊(cè)
  6. 1.36 MB  |  330次下載  |  免費(fèi)
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費(fèi)
  9. 5元宇宙深度解析—未來(lái)的未來(lái)-風(fēng)口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費(fèi)
  11. 6迪文DGUS開(kāi)發(fā)指南
  12. 31.67 MB  |  194次下載  |  免費(fèi)
  13. 7元宇宙底層硬件系列報(bào)告
  14. 13.42 MB  |  182次下載  |  免費(fèi)
  15. 8FP5207XR-G1中文應(yīng)用手冊(cè)
  16. 1.09 MB  |  178次下載  |  免費(fèi)

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費(fèi)
  3. 2555集成電路應(yīng)用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費(fèi)
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費(fèi)
  7. 4開(kāi)關(guān)電源設(shè)計(jì)實(shí)例指南
  8. 未知  |  21549次下載  |  免費(fèi)
  9. 5電氣工程師手冊(cè)免費(fèi)下載(新編第二版pdf電子書(shū))
  10. 0.00 MB  |  15349次下載  |  免費(fèi)
  11. 6數(shù)字電路基礎(chǔ)pdf(下載)
  12. 未知  |  13750次下載  |  免費(fèi)
  13. 7電子制作實(shí)例集錦 下載
  14. 未知  |  8113次下載  |  免費(fèi)
  15. 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德?tīng)栔?/a>
  16. 0.00 MB  |  6656次下載  |  免費(fèi)

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費(fèi)
  3. 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
  4. 78.1 MB  |  537798次下載  |  免費(fèi)
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費(fèi)
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費(fèi)
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費(fèi)
  11. 6電路仿真軟件multisim 10.0免費(fèi)下載
  12. 340992  |  191187次下載  |  免費(fèi)
  13. 7十天學(xué)會(huì)AVR單片機(jī)與C語(yǔ)言視頻教程 下載
  14. 158M  |  183279次下載  |  免費(fèi)
  15. 8proe5.0野火版下載(中文版免費(fèi)下載)
  16. 未知  |  138040次下載  |  免費(fèi)