用TensorFlow训练自己的第一个模型
现在学AI的一个优势就是:前人栽树后人乘凉,很多资料都已完善,而且有很多很棒的开源作品可以学习,感谢大佬们
项目
项目源码地址
视频教程地址
我在大佬的基础上基于此模型还加上了根据特征值缓存进行快速识别的方法,以应对超市某些未能正确识别的场景,针对项目中window.py文件进行修改和补充:
- 缓存查询方法
def query_cache(self, image_features):if not cache:return Nonemax_similarity = -1best_label = Nonefor image_id, (cached_features, label) in cache.items():similarity = self.cosine_similarity(image_features, cached_features)if similarity > max_similarity:max_similarity = similaritybest_label = labelif max_similarity >= 0.5:return best_labelelse:return None
- 余弦相邻计算
def cosine_similarity(self, features1, features2):dot_product = np.dot(features1.flatten(), features2.flatten())norm_features1 = np.linalg.norm(features1)norm_features2 = np.linalg.norm(features2)return dot_product / (norm_features1 * norm_features2)
- 缓存更新方法
def update_cache(self):input_text = self.input_box.text()self.label = input_text or self.labelself.result.setText(self.label)# 如果缓存已满,移除最久未使用的条目if len(cache) >= CACHE_CAPACITY:cache.popitem(last=False)# 添加新条目cache[self.image_id] = (self.image_features, self.label)self.input_box.clear()self.class_names.append(self.label)
- 获取图片哈希值
def get_image_id_from_hash(self, img):buffer = img.tobytes()return hashlib.md5(buffer).hexdigest()
- 预测图片
def predict_img(self):self.input_box.clear()img = Image.open('images/target.png') # 读取图片self.image_id = self.get_image_id_from_hash(img)img = np.asarray(img) # 将图片转化为numpy的数组start_time = time.time() # 记录开始时间outputs = self.model.predict(img.reshape(1, 224, 224, 3), batch_size=1, ) # 将图片输入模型得到结果end_time = time.time() # 记录结束时间elapsed_time = end_time - start_time # 计算时间差print("运行时间:", elapsed_time, "秒")self.image_features = outputsresult = self.query_cache(outputs)self.label = resultif result is None:result_index = int(np.argmax(outputs))result = self.class_names[result_index] # 获得对应的水果名称self.result.setText(result)self.label = resultelse:self.result.setText(result) # 在界面上做显示
- UI改造
def initUI(self):main_widget = QWidget()main_layout = QHBoxLayout()font = QFont('楷体', 15)# 主页面,设置组件并在组件放在布局上left_widget = QWidget()left_layout = QVBoxLayout()img_title = QLabel("样本")img_title.setFont(font)img_title.setAlignment(Qt.AlignCenter)self.img_label = QLabel()img_init = cv2.imread(self.to_predict_name)h, w, c = img_init.shapescale = 400 / himg_show = cv2.resize(img_init, (0, 0), fx=scale, fy=scale)cv2.imwrite("images/show.png", img_show)img_init = cv2.resize(img_init, (224, 224))cv2.imwrite('images/target.png', img_init)self.img_label.setPixmap(QPixmap("images/show.png"))left_layout.addWidget(img_title)left_layout.addWidget(self.img_label, 1, Qt.AlignCenter)left_widget.setLayout(left_layout)right_widget = QWidget()right_layout = QVBoxLayout()btn_change = QPushButton(" 上传图片 ")btn_change.clicked.connect(self.change_img)btn_change.setFont(font)btn_predict = QPushButton(" 开始识别 ")btn_predict.setFont(font)btn_predict.clicked.connect(self.predict_img)btn_update = QPushButton(" 更新缓存 ")btn_update.setFont(font)btn_update.clicked.connect(self.update_cache)label_result = QLabel(' 果蔬名称 ')self.result = QLabel("等待识别")label_result.setFont(QFont('楷体', 16))self.result.setFont(QFont('楷体', 24))self.input_box = QLineEdit()self.input_box.setPlaceholderText("请输入内容...")right_layout.addStretch()right_layout.addWidget(label_result, 0, Qt.AlignCenter)right_layout.addStretch()right_layout.addWidget(self.result, 0, Qt.AlignCenter)right_layout.addStretch()right_layout.addWidget(self.input_box)right_layout.addStretch()right_layout.addWidget(btn_change)right_layout.addWidget(btn_predict)right_layout.addWidget(btn_update)right_layout.addStretch()right_widget.setLayout(right_layout)main_layout.addWidget(left_widget)main_layout.addWidget(right_widget)main_widget.setLayout(main_layout)# 关于页面,设置组件并把组件放在布局上label_super = QLabel("作者:cpa") # todo 更换作者信息label_super.setFont(QFont('楷体', 12))# label_super.setOpenExternalLinks(True)label_super.setAlignment(Qt.AlignRight)# 添加注释self.addTab(main_widget, '主页')self.setTabIcon(0, QIcon('images/主页面.png'))
运行:
待完善:
- 缓存部分目前市面上是需要将缓存值存入本地sqllite之类的数据库进行保存的,这样下次开机缓存数据不会丢失,这里只展示思路
- 缓存除了保存在本地外还可以上传云端进行增强学习然后下发最新模型在本地进行更新,形成完美闭环
打包
pip install pyinstaller
pyinstaller -F -w (-i icofile) filename
说明:
filename表示你的Python程序文件名
-w 表示隐藏程序运行时的命令行窗口(不加-w会有黑色窗口)
括号内的为可选参数,-i icofile表示给程序加上图标,图标必须为.ico格式
icofile表示图标的位置,建议直接放在程序文件夹里面,这样子打包的时候直接写文件名就好
pyinstaller -F -w -i 'test.ico' window.py
- 将图片文件和模型文件等window.py中用到的资源在打包后一起移入dist目录中,不然会资源找不到的错
- 发给你的小伙伴看看效果吧
相关文章:

用TensorFlow训练自己的第一个模型
现在学AI的一个优势就是:前人栽树后人乘凉,很多资料都已完善,而且有很多很棒的开源作品可以学习,感谢大佬们 项目 项目源码地址 视频教程地址 我在大佬的基础上基于此模型还加上了根据特征值缓存进行快速识别的方法,…...

MySQL数据库入门基础知识 【1】推荐
数据库就是储存和管理数据的仓库,对数据进行增删改查操作,其本质是一个软件。 首先数据有两种,一种是关系型数据库,另一种是非关系型数据库。 关系型数据库是以表的形式来存储数据,表和表之间可以有很多复杂的关系&a…...

Anaconda下的 jupyter notebook安装及使用
安装 打开Anaconda Powershell Prompt或Anconda Prompt 输入命令conda install jupyter notebook进行安装 启动 切换到工作目录,输入命令jupyter notebook等待浏览器打开网页 命令行启动jupyter notebook的链接复制到浏览器同样可以打开jupyter notebook 在Ancon…...

C语言初阶(11)
1.结构体定义 结构体就是一群数据类型的集合体。这些数据类型被称为成员变量。结构的成员可以是标量、数组、指针,甚至是其他结构体。 2.结构体的声明和结构体变量命名与初始化 结构体声明由以下结构组成 struct stu {char name[12];int age; }; 结构体命名有两…...

Unity获取Animator动画播放完成事件
整理了一些在日常经验中处理动画播放完成事件的方法 方法: 1.Dotween配合异步实现 2.状态机计时方法实现 3.原生动画行为方法实现 方法一:Dotween异步方法 using UnityEngine; using System.Threading.Tasks; using DG.Tweening;public class PlayerAnimAsync : M…...
git submodule 使用
在Git中,子模块(submodule)是一种将一个Git仓库作为另一个Git仓库的子目录嵌入的方式。这使得主仓库能够跟踪和管理对外部依赖的更改。 添加子模块 初始化父仓库:如果你还没有创建父仓库,先创建它。 添加子模块&…...

【Jenkins未授权访问漏洞 】
默认情况下 Jenkins面板中用户可以选择执行脚本界面来操作一些系统层命令,攻击者可通过未授权访问漏洞或者暴力破解用户密码等进入后台管理服务,通过脚本执行界面从而获取服务器权限。 第一步:使用fofa语句搜索 搜索语句: port&…...
前端处理 Excel 文件
引入XLSX XLSX 是一个流行的 JavaScript 库,用于处理 Excel 文件(包括 .xls 和 .xlsx 格式)。它可以在 Node.js 环境和浏览器中运行,提供了丰富的 API 来读取、写入、修改 Excel 文件。当你使用 import * as XLSX from xlsx; 这行…...

(vue)el-cascader级联选择器按勾选的顺序传值,摆脱层级约束
(vue)el-cascader级联选择器按勾选的顺序传值,摆脱层级约束 需求:按勾选的顺序给后端传值 难点:在 Element UI 的 el-cascader 组件中,默认的行为是根据数据的层级结构来显示选项,用户的选择也会基于这种层级结构,el-…...

Redis进阶(四):哨兵
为了解决主节点故障,需要人工操作切换主从的情况;因此需要一种方法可以自动化的切换:哨兵的引入大大改变这种情况。 哨兵的基本概念 自动切换主从节点 哨兵架构 1、当一个哨兵节点发现主节点挂了的时候,还需要其他节点也去检测一…...
蓝屏事件:网络安全的启示
“微软蓝屏”事件暴露了网络安全哪些问题? 近日,一次由微软视窗系统软件更新引发的全球性“微软蓝屏”事件,不仅成为科技领域的热点新闻,更是一次对全球IT基础设施韧性与安全性的深刻检验。这次事件,源于美国电脑安全技…...
技术方案评审原则
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言技术方案评审原则1.理论突破阶段2.技术突破阶段3.工程化阶段自动驾驶行业的技术方案分析前言 认知有限,望大家多多包涵,有什么问题也希望能够与大…...

117页PPT埃森哲-物流行业信息化整体规划方案
一、埃森哲-物流行业信息化整体规划方案 资料下载方式,请看每张图片右下角信息 埃森哲在物流行业信息化整体规划项目中的核心内容,旨在帮助物流企业通过信息技术的应用实现业务流程的优化、运营效率的提升以及市场竞争力的增强。以下是埃森哲在此类项目…...

百度网盘不下载怎么直接打印文件?
在数字化时代,百度网盘作为我们存储和分享文件的重要工具,承载了大量的文档、图片和资料。然而,当需要打印这些文件时,很多用户会面临一个共同的问题:不想下载到本地再打印,既占用空间又浪费时间。那么&…...
设置了 robots.txt 禁止爬虫抓取,为什么还是能被百度搜索出来
虽然设置了 robots.txt 禁止爬虫抓取,但网页仍可能被百度搜索出来,主要有以下几个原因: robots.txt 只是一种建议性协议,并非强制性[2]。虽然大多数搜索引擎会遵守 robots.txt 的规则,但并不是所有爬虫都会严格遵守。 …...

DedeCMS-V5.7.82-UTF8织梦管理系统漏洞
将靶场环境放到www目录下——访问/dedecms/uploads 安装程序 - 织梦内容管理系统 V5.7 UTF8SP2 同意协议——继续 继续 配置后——点击继续 进入后台 登录后台——填写用户名密码。 方法一:上传shell文件 后台——核心——附件管理——上传新文件。 访问/dedecms…...

【Python】字符串练习题及代码示例
1、使用while循环实现对字符串中每个字符进行输出。 代码示例: 2、请将代码实现如下进制的转换。 (1)v1675,请将v1转换为二进制。 代码: 注意:将十进制数转换为二进制数的方法是:bin(a),a是整型&#x…...
fluent动网格profile udf 注意事项
案例一: ((profile_name transient 2 0) ....第一行 (time 0 15.0) ....第二行 (v_x 1.2 1.2)) …...

【doghead】mac构建 2: player 端 clion构建
准备工作 【doghead】mac构建 1 【doghead】mac: clion2024.1启动崩溃 mbp的 uv 构建ok zhangbin@zhangbin-mbp-2 ~/tet/Fargo/zhb-bifrost/Bifrost-202403/worker/third_party/libuv main clion使用lldb cmake构建 更...

论网络流(最大流篇)--新手入门超详解--包教包会
论网络流--新手入门超详解--包教包会 1 前言2 什么是最大流3最大流问题的求解(1)问题转化--增广路的引入(2)走回头路--EK算法(3)EK的弊端(4)化图为树--DINIC算法 4后记 1 前言 网络…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...

如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...