深度學習卷積神經網絡項目實戰——超市商品分類

卷積神經網絡項目實戰

1.項目簡介

1.1項目名稱

? 基于CNN實現超市商品的混合顆粒度分類(500分類)

1.2 項目簡介

? 該項目旨在通過卷積神經網絡(CNN)實現超市商品的混合顆粒度分類,主要針對商品的不同種類進行分類,應用場景主要為大型超市的自助收銀臺,設備通過模型的嵌入快速識別商品種類并為顧客提供結賬操作,降低了超市的人力資源,以及提高人員流通性。

? 本項目引入深度學習中的CNN模型,構建一個專門用于超市常見商品分類的網絡架構,充分利用卷積層的局部特征提取能力以及深層網絡的高階特征融合能力,其包含了數據收集、數據預處理、模型訓練、模型評估、模型移植、可視化等步驟,使用RP2K數據集進行模型訓練,模型通過反復地特征學習提高分類精確度。同時,由于其中也包含部分細粒度難區分的類目(如不同水果、同種包裝的不同飲料),項目中使用了數據增強等技術手段提高模型的泛化能力,最終達到高精度地分類結果。

2.數據集

本次項目所使用的數據集為RP2K數據集

RP2K數據集

RP2K (Retail Product 2000K) 是一個用于零售場景的 大規模細粒度商品圖像分類數據集

提出背景:在超市、便利店等零售場景中,存在數千上萬種商品,很多商品的外觀極其相似(比如不同口味的可樂、不同包裝的方便面),這使得計算機視覺中的 細粒度圖像分類(Fine-grained Image Classification, FGIC)成為一個關鍵挑戰。

RP2K數據集包含了2000+商品類別,數據總量超過 200 萬張商品圖片,圖片來源于真實零售場景(貨架拍攝、收銀臺、監控視頻幀)以及部分網絡采集,覆蓋了多角度(正面、側面、傾斜)、不同分辨率與清晰度光照差異遮擋(部分商品被擋住)等環境。

本項目節選了其中的500類數據作為該項目的數據集。

下載

官網:RP2K鏈接 – 品覽科技

在這里插入圖片描述

下載的數據集已經被劃分好,無需自己手動進行數據清洗

在這里插入圖片描述

3.模型訓練

3.1加載訓練集數據/數據預處理

(1)設置數據增強:包含了改變圖片大小、隨機裁剪、隨機水平翻轉、顏色改變、隨機翻轉、歸一化操作

    transform = transforms.Compose([transforms.Resize((224, 224)), # 改變圖片大小transforms.RandomCrop((224, 224)), # 隨機裁剪transforms.RandomHorizontalFlip(), # 隨機水平翻轉transforms.ColorJitter(0.2, 0.2, 0.2, 0.1), # 改變顏色transforms.RandomRotation(10), # (-10°, 10°)隨機旋轉transforms.ToTensor(), # 歸一化transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])# 標準化

transforms.Compose()PyTorch torchvision 中用于組合多個圖像預處理/增強操作的工具。它的作用就是把多個 transform 按順序串起來,讓圖像數據在加載時依次經過這些操作。

詳細參數介紹參考pytorch官方文檔:Illustration of transforms — Torchvision 0.23 documentation

(2)使用pytorch框架的ImageFolder加載訓練數據

    data_train = ImageFolder(root='./data/train', transform=transform)

transform參數為(1)中的數據增強設置,即加載的每一張圖片都經過transform中的操作處理。

(3)使用數據加載器分批次加載數據

創建數據加載器對象:

train_loader = DataLoader(data_train, batch_size=32, num_workers=4, shuffle=True)

返回的train_loader是由數據包裝成的可迭代對象

batch_size為每批次數據的數量大小,根據個人電腦GPU性能進行設置,一般設置為2n2^n2n

num_workers數據加載的子進程數,>0 表示用多進程加載,能加快訓練速度,一般設置為 0 或小于 CPU 核數。

shuffle決定是否打亂數據順序,一般在訓練時設置為True,測試時設置為False。

3.2模型選擇

這里我選擇了googlenet模型。我們的訓練思路是使用已經訓練好的模型參數,只對最后的輸出層進行訓練,也就是參數更新,具體操作如下。

加載預訓練參數

    # 加載預訓練參數pretrained = googlenet(pretrained=True)pre_weights = pretrained.state_dict()pre_weights = {k: v.to(device) for k, v in pre_weights.items()} 

state_dict()是模型通用方法,作用是返回參數字典

字典推導式的作用為遍歷原字典的每個鍵值對 (k,v),對每個 tensor v 調用 .to(device) 方法,把它移動到指定設備,device一般設置為:

    device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

參數和模型默認存放在CPU中,使用to(device)可將其轉移至GPU。

清除預訓練參數的最后一層:

    # 清除預訓練參數最后一層數據pre_weights.pop('fc.weight')pre_weights.pop('fc.bias')

創建新模型:

    # 創建模型model = googlenet(pretrained=False)num_classes = 500 # 分類類別數model.fc = nn.Linear(model.fc.in_features, num_classes)model = model.to(device)

? model.fc = nn.Linear(model.fc.in_features, num_classes)的作用是將原本網絡結構中的最后一層輸出(即類別數)改為500。

更新模型參數:

    # 更新模型參數weigths = model.state_dict()weigths.update(pre_weights)model.load_state_dict(weigths)

將預訓練參數更新到模型中。

凍結層:

    # 凍結層for name, param in model.named_parameters():if name != 'fc.weight' and name != 'fc.bias':param.requires_grad = False

將模型最后一層之前的參數的梯度計算禁用。

model.named_parameters() 是一個 生成器(generator),它會遍歷模型中的所有參數,并返回 (參數名, 參數張量) 這樣的鍵值對。

設置優化器:

    # 優化器parameters = [x for x in model.parameters() if x.requires_grad]optimizer = opt.Adam(parameters, lr=1e-3)

優化器用于模型進行參數更新,這里我們只更新最后一層參數,并且使用的是Adam優化器。

設置損失函數:

    # 損失函數criterion = nn.CrossEntropyLoss(reduction='sum')

選擇交叉熵損失函數作為多分類損失函數。reduction 參數,它決定了 批次(batch)里多個樣本的損失要如何合并,這里選擇的是進行求和。

定義訓練輪次:

    epochs = 50

設置學習率調度器:

    # 學習率調度器scheduler = opt.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs, eta_min=1e-5)

這里選擇的是余弦學習率調度器,目的是對每輪訓練的學習率進行更新,讓學習率從 高學習率非線性地逐漸減小到低學習率

3.3訓練

    acc = []best_acc = 0# 訓練for epoch in range(epochs):acc_total = 0loss_total = 0for i, (data, target) in enumerate(train_loader):data, target = data.to(device), target.to(device)output = model(data)main_out = output[0]  # 主輸出aux1_out = output[1]  # 輔助輸出1aux2_out = output[2]  # 輔助輸出2# 選取最大值作為分類結果,返回的pred為標簽下標pred = torch.argmax(main_out, dim=1)acc_total += torch.sum(pred == target).item()# 梯度清零optimizer.zero_grad()# 計算綜合損失loss = criterion(main_out, target) + 0.3 * (criterion(aux1_out, target) + criterion(aux2_out, target))loss_total += loss# 反向傳播loss.backward()# 參數更新optimizer.step()# 學習率更新scheduler.step()# 將當前輪次模型準確率記錄在acc中acc.append(acc_total / len(data_train))current_acc = acc[epoch]# 判斷當前輪次參數準確率是否為最佳,若為最佳則保存該參數if current_acc > best_acc:# 更新最佳準確率best_acc = current_acctorch.save(model.state_dict(), './model/model.pth')# 打印每輪訓練結果print(f'epoch--->{epoch + 1},'f'loss---> {loss_total.item() / len(data_train):.4f},'f' acc---> {acc_total / len(data_train):.4f}')
  • acc用于保存每輪訓練后的參數,best_acc用于保存歷史最高準確率
  • 由于Googlenet模型內置有輔助選擇器,所以其輸出結果為一個元組,為一個主要輸出和兩個輔助輸出,在進行損失函數計算的過程中,需要考慮輔助分類的損失,通過分配不同權重比得到最終的損失函數。
  • 判斷當前準確率是否為歷史最佳準確率,若為最佳準確率則保存參數,方便后續進行模型遷移。

3.4訓練過程可視化

使用tensorboard模塊將訓練過程可視化:

from torch.utils.tensorboard import SummaryWriter

創建tensorboard對象:

    # 創建tensorboard對象writer = SummaryWriter()

SummaryWriter(log_dir=tbpath)log_dir為tensorboard日志保存路徑,未設置保存路徑會保存至當前文件夾下自動創建的runs文件夾下。

繪制過程曲線:

        writer.add_scalar('loss', loss_total, epoch)writer.add_scalar('acc', acc_total / len(data_train), epoch)

顯示數據增強后的圖片:

            if i % 100 == 0:img_grid = torchvision.utils.make_grid(data)writer.add_image(f'r_m_{epoch}', img_grid, i)

運行后會在runs文件夾內生成可視化的文件。

接下來打開終端,輸入命令:

tensorboard --logdir=runs   

也可將runs改為指定路徑。

隨后點擊生成的本地網站即可查看繪制的曲線圖以及圖片:

在這里插入圖片描述

4.模型評估

4.1加載預測集數據

同加載訓練集類似,只不過在數據增強時一般只進行重新設置圖片大小和標準化以及歸一化操作,因為模型預測是在真實數據分布下的表現,因此我們 不能引入隨機性,而resize圖片大小是為了讓數據的shape和模型的輸入shape一致。

# 加載預測數據集
transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
data_test = ImageFolder(root='./data/test', transform=transform)
test_loader = DataLoader(data_test, batch_size=32, shuffle=False)

4.2加載模型

加載之前訓練好的模型參數

# 加載訓練好的模型
model = googlenet(pretrained=False)
model.fc = nn.Linear(model.fc.in_features, 500)
model = model.to(device)
weights = torch.load('./model/model.pth')
model.load_state_dict(weights)

4.3結果預測

首先將模型切至驗證模式:

# 驗證模式
model.eval()  # 關閉 Dropout 和輔助分類器

注意:這一步至關重要,模型默認會處于訓練模式下,這會使得google網絡結構中的輔助分類和Dropout沒有關閉,dropout未關閉會導致預測時神經元丟失,影響最終結果。

進行驗證:

with torch.no_grad():acc = 0for data, label in test_loader:data, label = data.to(device), label.to(device)output = model(data)# 選取最大值作為分類結果,返回的pred為標簽下標pred = torch.argmax(output, dim=1)acc += torch.sum(pred == label).item()

with torch.no_grad():作用:關閉參數梯度計算,加速預測,節省內存。

4.4預測評估

打印結果:

acc = acc / len(data_test)
print(f"acc:{acc:.5f}")

4.5預測結果可視化

可引入numpy和pandas將預測的數據轉變成excel表格(csv格式文件),具體操作如下:

創建一個列數為502的numpy空二維數組:

data_csv = np.empty((0, 502))

因為模型的輸出為每個類別下所對應的輸出值,取最大的輸出值的類別作為分類結果,所以需要500列存放模型輸出值,1列存放預測標簽,1列存放實際標簽。

將每一批次訓練的數據存入numpy數組:

output_csv = output.cpu().detach().numpy()
pred_csv = np.expand_dims(pred.cpu().detach().numpy(), axis=1)
label_csv = np.expand_dims(label.cpu().detach().numpy(), axis=1)
batch_csv = np.concatenate((output_csv, pred_csv, label_csv), axis=1)
data_csv = np.concatenate((data_csv, batch_csv), axis=0)

取出標簽:

labels = data_test.classes

將結果轉換為Datafream再導出為csv文件:

# 將結果轉為csv文件
column = [*labels, 'pred', 'label']
data_csv = pd.DataFrame(data=data_csv, columns=column)
data_csv.to_csv('./data_pred_result/result.csv', index=False)

同時把標簽存為csv文件:

# 將標簽存為csv文件
df = pd.DataFrame({"index": list(range(len(labels))), "label": [*labels]})
df.to_csv('./labels.csv', index=False)

也可以將網絡結構進行可視化觀察網絡結構:

writer = SummaryWriter("./net_frame")
dummy_input = torch.randn(1, 3, 224, 224)
writer.add_graph(model, dummy_input.to(device))
writer.close()

同樣的用終端生成本地網站,進入網站查看可視化結果:

 tensorboard --logdir=文件絕對路徑

在這里插入圖片描述

4.6生成分類報告

導入matplotlib模塊和pandas模塊,讀到之前預測生成的csv文件,獲取標簽:

# csv文件地址
data_path = './data_pred_result/result.csv'
# 讀取csv數據
data = pd.read_csv(data_path)
# 獲取真實標簽
true_label = data["label"].values
# 獲取預測標簽
pred_label = data["pred"].values

接著導入sklearn.metrics模塊生成分類報告:

    # 生成分類報告report = classification_report(true_label, pred_label)print(report)acc = accuracy_score(true_label, pred_label)precision = precision_score(true_label, pred_label, average='macro')recall = recall_score(true_label, pred_label, average='macro')f1 = f1_score(true_label, pred_label, average='macro')print(f"準確度:{acc:.6f}\n"f"精確度:{precision:.6f}\n",f"召回率:{recall:.6f}\n",f"f1:{f1:.6f}\n")

用matlplotlib生成混淆矩陣(由于原始數據的混淆矩陣太大,500分類即500*500矩陣,這里只生成前十分類的混淆矩陣作為演示):

def vision_martix(true_label, pred_label, num_classes=10):labels = [x for x in range(num_classes)]matrix = confusion_matrix(true_label, pred_label)print(matrix)plt.figure(figsize=(8, 8))plt.matshow(matrix[:10, :10], cmap=plt.cm.Greens, fignum=1)# 顯示顏色條plt.colorbar()# 顯示具體的數字的過程for i in range(len(matrix)):for j in range(len(matrix)):plt.annotate(matrix[i, j],xy=(j, i),horizontalalignment="center",verticalalignment="center",)# 美化的東西plt.xlabel("Pred labels")plt.ylabel("True labels")plt.xticks(range(len(labels)), labels, rotation=45)plt.yticks(range(len(labels)), labels)plt.title("訓練結果混淆矩陣視圖")plt.show()

效果:

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

5.模型應用

首先讀取圖片,這里我導入了opencv模塊進行讀圖,并且將讀取到的圖片進行預處理操作:

    # 讀圖處理img = cv.imread(img_path)img = cv.resize(img, (224, 224))transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))])img = transform(img)img = torch.unsqueeze(img, 0).to(device)

加載訓練好的模型:

	    net = googlenet(pretrained=False)net.fc = nn.Linear(net.fc.in_features, 500)net.load_state_dict(torch.load("./model/model.pth"))net.to(device)

進行預測:

    # 預測net.eval()output = net(img)output = torch.argmax(output, dim=1)print(output)

可以用Imagefolder導入訓練集或輸出集獲取標簽映射表,將標簽映射轉換為下標映射:

idx_to_class = {v: k for k, v in data.class_to_idx.items()}
print(idx_to_class[pred])

最后得到結果:

在這里插入圖片描述

6.模型遷移

6.1導出onnx模型

首先需要提前在環境內安裝依賴包

pip install onnx
pip install onnxruntime

導入訓練好的模型:

# 導入訓練好的模型
net = googlenet(pretrained=False)
net.fc = nn.Linear(in_features=net.fc.in_features, out_features=500)
weight_path = "./model/model.pth"
net.load_state_dict(torch.load(weight_path))

創建一個實例輸入:

x = torch.randn(1, 3, 224, 224)

用torch.onnx.export導出onnx:

torch.onnx.export(net,x,onnx_path,verbose=True,input_names=['input'],output_names=['output']
)

6.2使用onnx推理

加載onnx模型:

# 加載onnx模型
onnx_path = './model_onnx/model.onnx'
session = rt.InferenceSession(onnx_path)

對要進行推理的圖片進行預處理:

def read_img(path):# 處理輸入圖片img = cv.imread(path)img = cv.resize(img, (224, 224))img = img.transpose((2, 0, 1))img = img.astype(np.float32) / 255.0  # 代替Totensor()操作img = np.expand_dims(img, axis=0)return imgimg_path = "./apply/1.jpg"
img1 = read_img(img_path)

進行推理:

# 獲取輸入輸出名
input_name = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name# 推理
result = session.run([output_name], {input_name: img1})

得到結果并且將結果從下標值映射為標簽名:

# 取出分類標簽下標
result = np.argmax(result[0], axis=1)
print(result)# 讀取保存好的標簽csv文件建立 index->label 映射表
df = pd.read_csv("labels.csv")
idx2label = dict(zip(df["index"], df["label"]))
print(f"img的分類為:{idx2label[result.item()]}")

項目源代碼倉庫:卷積神經網絡項目實戰: 卷積神經網絡個人實戰項目

注意:訓練集以及生成文件夾需要自己手動創建,具體文件夾已在file_expression文檔中說明。

ply/1.jpg"
img1 = read_img(img_path)


進行推理:```python
# 獲取輸入輸出名
input_name = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name# 推理
result = session.run([output_name], {input_name: img1})

得到結果并且將結果從下標值映射為標簽名:

# 取出分類標簽下標
result = np.argmax(result[0], axis=1)
print(result)# 讀取保存好的標簽csv文件建立 index->label 映射表
df = pd.read_csv("labels.csv")
idx2label = dict(zip(df["index"], df["label"]))
print(f"img的分類為:{idx2label[result.item()]}")

項目源代碼倉庫:卷積神經網絡項目實戰: 卷積神經網絡個人實戰項目

注意:訓練集以及生成文件夾需要自己手動創建,具體文件夾已在file_expression文檔中說明。

如果博主的文檔和源代碼對你有所幫助,也麻煩給博主點個收藏和贊噢,謝謝☆嚕~☆

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/94699.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/94699.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/94699.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網站如何被搜索引擎收錄(Google、Bing、百度等)

1. 【Google 收錄】注冊 Google Search Console: https://search.google.com/search-console添加網站(主域名、子域名都加)驗證所有權(用 DNS、HTML 文件、Meta Tag 都可以)提交 Sitemap(/sitemap.xml&…

JDK 8 → JDK 17 升級說明書(面向 Spring Boot / Spring Cloud / Spring )

自從 JDK 8 發布以來,Java 語言在持續進化,帶來了許多新的功能和性能改進。而 JDK 17 作為一個長期支持版本(LTS),在許多方面超越了 JDK 8,不僅提升了語言本身的能力,還進一步提高了性能、可維護…

【ElasticSearch】使用docker compose,通過編寫yml安裝es8.15和kibana可視化界面操作,go連接es

使用 Docker 安裝 Elasticsearch Docker 搭建 Elasticsearch Kibana 環境,并在過程中標注常見問題和解決方案。 1. 準備工作 在開始之前,請確認你本地已經安裝了: 工具版本建議檢查方式Docker≥ 20.xdocker -vDocker Compose≥ 2.xdocker …

《C 語言文件操作補充:字符串格式化與隨機讀寫全解析》

目錄 一. sprintf函數和sscanf函數 1.1 sprintf 函數:將格式化數據寫入字符串 1.2 sscanf 函數:從字符串中格式化讀取數據 二. 文件的隨機讀寫 2.1 fseek 函數:移動文件讀寫指針 2.2 ftell 函數:獲取當前指針位置 2.3 rew…

SOME/IP-SD報文中 Entry Format(條目格式)-理解筆記4

逐字段解析 AUTOSAR SOME/IP Service Discovery 中的 Entry 格式。我們將它拆解成幾個部分,并用清晰的排版和比喻來確保每個字段都得到解釋。📜 Entry 的完整結構:三層蛋糕 一條完整的 SD Entry 信息就像一塊三層蛋糕,從上到下分別…

在 vue3 和 vue2 中,computed 計算屬性和 methods 方法區別是什么

在 Vue 2 和 Vue 3 中,computed(計算屬性)和 methods(方法)都是處理數據邏輯的方式,但它們在緩存機制、使用場景、執行時機等方面有顯著區別,且這些區別在兩個版本中保持一致。 1. 緩存機制&…

android 改機系列之-虛擬攝像頭-替換相機預覽畫面

Android Native 層實現跨進程 YUV 視頻幀共享:基于抽象 Unix Socket 的高效通信方案。基于AOSP13源碼或者lineage20 或相近版本。非hook 或者lsp 等插件方案。 1.引言 在某些定制化 Android 應用場景中,我們可能需要動態替換系統相機的預覽畫面 —— 例…

SSM從入門到實戰:2.5 SQL映射文件與動態SQL

👋 大家好,我是 阿問學長!專注于分享優質開源項目解析、畢業設計項目指導支持、幼小初高的教輔資料推薦等,歡迎關注交流!🚀 12-SQL映射文件與動態SQL 📖 本文概述 本文是SSM框架系列MyBatis進…

vue+vite打包后的文件希望放在一個子目錄下

比如我們常規操作是打包的項目文件直接放在域名下面。如果我們希望把項目放在子域名下面應該怎么處理呢?需要兩個步驟vite.config.js里面指定base的路徑假設我們希望放在子目錄加做call那么我們可以這樣base:/call/,注意不是build目錄哈。return的最外層。如果本地和…

Java:Docx4j類庫簡介及使用

1.簡介 Docx4j 是一個功能強大的 Java 類庫,專門用于創建和操作 Microsoft Open XML 格式(如 Word DOCX、PowerPoint PPTX 和 Excel XLSX)的文件。它深受 Java 開發者喜愛,特別是在需要自動化處理 Office 文檔的場景下。 下面是一…

【機械故障】旋轉機械故障引起的振動信號調制效應概述

系列文章目錄 提示:學習筆記 機械故障信號分析 共振峰 旋轉機械故障引起的振動信號調制效應概述系列文章目錄一、研究背景與意義二、故障引起的調制效應分類三、非平穩信號分析方法3.1 時頻分析方法3.2 信號分解方法一、研究背景與意義 在工程實踐中,可…

密碼安全隱形基石:隨機數、熵源與DRBG核心解析與技術關聯

前言:密碼安全的 “隱形基石” 在數字化浪潮席卷全球的今天,從金融交易的密鑰生成到區塊鏈的共識機制,從量子通信的加密協議到智能汽車的身份認證,隨機數如同空氣般滲透在信息系統的每一個安全節點。然而,看似簡單的 …

Vue3 + Element Plus實現表格多行文本截斷與智能Tooltip提示

在實際開發中,我們經常需要在表格中展示較長的文本內容,但又希望保持界面的整潔美觀。本文將介紹如何在Vue3 和 Element Plus中實現表格多行文本截斷,并智能控制Tooltip的顯示——只有當文本被截斷時才顯示Tooltip,否則不顯示。 需…

使用powerquery處理數據,取時間或者日期之前的

Table.AddColumn(#"已更改列類型 1", "自定義 (2)", each letcleanText Text.Replace([備注], "#(lf)", " "),hasTime Text.Contains(cleanText, "時間:"),hasDate Text.Contains(cleanText, "日期&…

Java面試全棧技術解析:從Spring Cloud到Kafka的實戰演練

面試官:請簡單介紹一下Spring Cloud的核心組件? 謝飛機:嗯...Spring Cloud主要是基于Spring Boot的,然后有Eureka做服務發現,Feign做聲明式REST調用,還有Config做配置中心... 面試官:那在電商場…

極簡 useState:手寫 20 行,支持多次 setState 合并

不依賴 React,用 閉包 批處理隊列 實現可合并更新的 useState。一、20 行完整代碼 function createUseState(initialValue) {let state initialValue;let pending null; // 合并隊列let listeners [];const flush () > {if (pending ! null) {…

LabVIEW Vision視覺引導撐簧圈智能插裝

為解決人工插裝連接器撐簧圈時勞動強度大、效率低、一致性差的問題,例以 LabVIEW為開發平臺,結合 IMAQ Vision 機器視覺庫,搭配精密硬件搭建智能插裝系統。系統可適配 9 芯、13 芯、25 芯、66 芯、128 芯 5 種規格工件,經 100 只產…

【Lua】題目小練11

-- 題目1:-- 給定表 t {"apple", "banana", "apple", "orange", "banana", "apple"}-- 寫一個函數 countFreq(tbl) 返回一個新表,統計每個元素出現次數-- 例如:返回 {apple3, …

ElementUI之菜單(Menu)使用

文章目錄項目創建創建項目運行項目整理目錄刪除src/assets中的所有logo.png刪除src/components中的所有文件修改src/route/index.js刪除src/views中所有文件修改src/app.vue整理完目錄如下引入ElementUI安裝ElementUI引入ElementUI測試是否安裝成功編寫src/app.vue運行結果編寫…

Python訓練營打卡Day44-通道注意力(SE注意力)

知識點回顧: 不同CNN層的特征圖:不同通道的特征圖什么是注意力:注意力家族,類似于動物園,都是不同的模塊,好不好試了才知道。通道注意力:模型的定義和插入的位置通道注意力后的特征圖和熱力圖 內…