網站首頁 編程語言 正文
需求:
小程序端拍照調用python訓練好的圖片分類模型。實現圖片分類識別的功能。
微信小程序端:
重點在chooseImage函數中,根據圖片路徑獲取到圖片傳遞給flask的url;
Page({
data: {
SHOW_TOP: true,
canRecordStart: false,
},
data: {
tempFilePaths:'',
sourceType: ['camera', 'album']
},
isSpeaking: false,
accessToken: "",
onLoad: function (options) {
console.log("onLoad!");
this.setHeader();
var that=this
wx.showShareMenu({
withShareTicket: true //要求小程序返回分享目標信息
});
var isShowed = wx.getStorageSync("tip");
if (isShowed != 1) {
setTimeout(() => {
this.setData({
SHOW_TOP: false
})
wx.setStorageSync("tip", 1)
}, 3 * 1000)
} else {
this.setData({
SHOW_TOP: false
})
};
},
},
//頭像點擊處理事件,使用wx.showActionSheet()調用菜單欄
buttonclick: function () {
const that = this
wx.showActionSheet({
itemList: ['拍照', '相冊'],
itemColor: '',
//成功時回調
success: function (res) {
if (!res.cancel) {
/*
res.tapIndex返回用戶點擊的按鈕序號,從上到下的順序,從0開始
比如用戶點擊本例中的拍照就返回0,相冊就返回1
我們res.tapIndex的值傳給chooseImage()
*/
that.chooseImage(res.tapIndex)
}
},
setHeader(){
const tempFilePaths = wx.getStorageSync('tempFilePaths');
if (tempFilePaths) {
this.setData({
tempFilePaths: tempFilePaths
})
} else {
this.setData({
tempFilePaths: '/images/camera.png'
})
}
},
chooseImage(tapIndex) {
const checkeddata = true
const that = this
wx.chooseImage({
//count表示一次可以選擇多少照片
count: 1,
//sizeType所選的圖片的尺寸,original原圖,compressed壓縮圖
sizeType: ['original', 'compressed'],
//如果sourceType為camera則調用攝像頭,為album時調用相冊
sourceType: [that.data.sourceType[tapIndex]],
success(res) {
// tempFilePath可以作為img標簽的src屬性顯示圖片
console.log(res);
const tempFilePaths = res.tempFilePaths
//將選擇到的圖片緩存到本地storage中
wx.setStorageSync('tempFilePaths', tempFilePaths)
/*
由于在我們選擇圖片后圖片只是保存到storage中,所以我們需要調用一次 setHeader()方法來使頁面上的頭像更新
*/
that.setHeader();
// wx.showToast({
// title: '設置成功',
// icon: 'none',
// // duration: 2000
// })
wx.showLoading({
title: '識別中...',
})
var team_image = wx.getFileSystemManager().readFileSync(res.tempFilePaths[0], "base64")
wx.request({
url: 'http://127.0.0.1:5000/upload', //API地址,upload是我給路由起的名字,參照下面的python代碼
method: "POST",
header: {
'content-type': "application/x-www-form-urlencoded",
},
data: {image: team_image},//將數據傳給后端
success: function (res) {
console.log(res.data); //控制臺輸出返回數據
wx.hideLoading()
wx.showModal({
title: '識別結果',
confirmText: "識別正確",
cancelText:"識別錯誤",
content: res.data,
success: function(res) {
if (res.confirm) {
console.log('識別正確')
} else if (res.cancel) {
console.log('重新識別')
}
}
})
}
})
}
})
},
});
flask端:
將圖片裁剪,填充,調用自己訓練保存最優的模型,用softmax處理結果矩陣,最后得到預測種類
# coding=utf-8
from flask import Flask, render_template, request, jsonify
from werkzeug.utils import secure_filename
from datetime import timedelta
from flask import Flask, render_template, request
import torchvision.transforms as transforms
from PIL import Image
from torchvision import models
import os
import torch
import json
import numpy as np
import torch.nn as nn
import matplotlib.pyplot as plt
import base64
app = Flask(__name__)
def softmax(x):
exp_x = np.exp(x)
softmax_x = exp_x / np.sum(exp_x, 0)
return softmax_x
with open('dir_label.txt', 'r', encoding='utf-8') as f:
labels = f.readlines()
print("oldlabels:",labels)
labels = list(map(lambda x: x.strip().split('\t'), labels))
print("newlabels:",labels)
def padding_black(img):
w, h = img.size
scale = 224. / max(w, h)
img_fg = img.resize([int(x) for x in [w * scale, h * scale]])
size_fg = img_fg.size
size_bg = 224
img_bg = Image.new("RGB", (size_bg, size_bg))
img_bg.paste(img_fg, ((size_bg - size_fg[0]) // 2,
(size_bg - size_fg[1]) // 2))
img = img_bg
return img
# 輸出
@app.route('/')
def hello_world():
return 'Hello World!'
# 設置允許的文件格式
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'JPG', 'PNG', 'bmp'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
# 設置靜態文件緩存過期時間
app.send_file_max_age_default = timedelta(seconds=1)
# 添加路由
@app.route('/upload', methods=['POST', 'GET'])
def upload():
if request.method == 'POST':
# 通過file標簽獲取文件
team_image = base64.b64decode(request.form.get("image")) # 隊base64進行解碼還原。
with open("static/111111.jpg", "wb") as f:
f.write(team_image)
image = Image.open("static/111111.jpg")
# image = Image.open('laji.jpg')
image = image.convert('RGB')
image = padding_black(image)
transform1 = transforms.Compose([
transforms.Resize(224),
transforms.ToTensor(),
])
image = transform1(image)
image = image.unsqueeze(0)
# image = torch.unsqueeze(image, dim=0).float()
print(image.shape)
model = models.resnet50(pretrained=False)
fc_inputs = model.fc.in_features
model.fc = nn.Linear(fc_inputs, 214)
# model = model.cuda()
# 加載訓練好的模型
checkpoint = torch.load('model_best_checkpoint_resnet50.pth.tar')
model.load_state_dict(checkpoint['state_dict'])
model.eval()
src = image.numpy()
src = src.reshape(3, 224, 224)
src = np.transpose(src, (1, 2, 0))
# image = image.cuda()
# label = label.cuda()
pred = model(image)
pred = pred.data.cpu().numpy()[0]
score = softmax(pred)
pred_id = np.argmax(score)
plt.imshow(src)
print('預測結果:', labels[pred_id][0])
# return labels[pred_id][0];
return json.dumps(labels[pred_id][0], ensure_ascii=False)//將預測結果傳回給前端
# plt.show()
# return render_template('upload_ok.html')
# 重新返回上傳界面
# return render_template('upload.html')
if __name__ == '__main__':
app.run(debug=False)
大致的效果:
但是在手機上測試的話,wx.request{}里的url的域名不規范,不能出現這種端口號,目前還在想解決辦法,有知道的大佬還望告知。
總結
原文鏈接:https://blog.csdn.net/m0_44946030/article/details/115557881
相關推薦
- 2022-06-21 Android實現登錄界面的注冊功能_Android
- 2021-12-17 Windows下Flutter+Idea環境搭建及配置_Android
- 2022-07-03 C#入門之定義類成員與接口實現_C#教程
- 2022-11-29 Rust?模式匹配示例詳解_Rust語言
- 2022-09-06 React封裝CustomSelect組件思路詳解_React
- 2023-01-19 Oracle查詢表空間大小及每個表所占空間的大小語句示例_oracle
- 2022-01-26 使用Guzzle拓展包請求接口失敗重試
- 2022-11-16 C++實現中綴轉后綴的示例詳解_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支