Python实现技能记录系统

news2025/4/25 13:19:55

Python实现技能记录系统

来自网络,有改进。

技能记录系统界面如下:

具有保存图片和显示功能——允许用户选择图片保存,选择历史记录时若有图片可预览图片。

这个程序的数据保存在数据库skills2.db中,此数据库由用Python 自带的sqlite3数据库管理系统(不需要单独安装)管理,由程序自动维护(不需要用户操心),和程序文件在同一文件夹中。

“查看/编辑总结”的窗口上,有一个复选框 “允许编辑”,默认不选中 ,因此打开编辑总结的窗口时“保存”按钮处于不可用(灰色)状态,不能编辑文字,只有选中“允许编辑”复选框,方可编辑文字、保存。

此窗口设置为模态——确保用户完成编辑操作后才能返回主窗口。

本程序涉及如下模块/库

需要安装的库:Pillow (PIL)(通过 pip install pillow 安装)

Pillow (PIL) 是一个图像处理库,是第三方库,需要安装。用于处理图像文件。代码中使用了 Image 和 ImageTk,这些是 Pillow 的功能模块。

以下是 Python 标准库的一部分,通常不需要单独安装:

datetime:用于处理日期和时间。

io:用于处理输入输出流。

tkinter:用于创建图形用户界面。

sqlite3:用于操作 SQLite 数据库。

源码如下(部分代码参考自网络):

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import sqlite3
from datetime import datetime
from PIL import Image, ImageTk
import io

class SkillTracker:
    def __init__(self, root):
        self.root = root
        self.root.title("技能记录系统 v1.2.1")
        self.root.geometry("1500x760+0+0")

        self.conn = sqlite3.connect('skills2.db')
        self.c = self.conn.cursor()
        self.init_db()
        self.create_widgets()
        self.load_data()

        self.root.protocol("WM_DELETE_WINDOW", self.on_close)

    def init_db(self):
        try:
            self.c.execute('''CREATE TABLE IF NOT EXISTS skills
                (id INTEGER PRIMARY KEY, 
                 name TEXT NOT NULL, 
                 parent_id INTEGER,
                 path TEXT UNIQUE)''')
            self.c.execute('''CREATE TABLE IF NOT EXISTS records
                (id INTEGER PRIMARY KEY,
                 skill_path TEXT NOT NULL,
                 score INTEGER CHECK(score BETWEEN 1 AND 10),
                 date DATE DEFAULT CURRENT_DATE,
                 summary TEXT,
                 image BLOB)''')
            self.conn.commit()
        except sqlite3.Error as e:
            messagebox.showerror("数据库错误", f"初始化失败: {str(e)}")

    def add_category(self):
        """添加大类"""
        name = self.get_input("新建大类名称:")
        if name:
            try:
                self.c.execute(
                    "INSERT INTO skills (name, path) VALUES (?, ?)",
                    (name, name)
                )
                skill_id = self.c.lastrowid
                self.conn.commit()

                # 更新树形控件
                self.tree.insert("", "end", iid=skill_id, text=name, open=True)
                return True
            except sqlite3.IntegrityError:
                messagebox.showerror("错误", "技能名称已存在")
            except sqlite3.Error as e:
                messagebox.showerror("数据库错误", f"添加失败: {str(e)}")
        return False                

    def delete_item(self):
        """删除选中的技能项及其子项"""
        selected = self.tree.selection()
        if not selected:
            messagebox.showerror("错误", "请先选择要删除的项")
            return

        item_id = selected[0]
        item_name = self.tree.item(item_id)['text']

        # 确认对话框
        if not messagebox.askyesno("确认删除", f"确定要删除【{item_name}】及其所有子项吗?"):
            return

        # 递归删除数据库记录
        def delete_from_db(skill_id):
            self.c.execute("SELECT id FROM skills WHERE parent_id=?", (skill_id,))
            children = self.c.fetchall()
            for child in children:
                delete_from_db(child[0])
            self.c.execute("DELETE FROM skills WHERE id=?", (skill_id,))

        delete_from_db(item_id)
        self.conn.commit()

        self.tree.delete(item_id)
        messagebox.showinfo("成功", "删除完成")

    def delete_history(self):
        selected = self.history_tree.selection()
        if not selected:
            messagebox.showwarning("提示", "请先选择要删除的记录")
            return

        record_id = self.history_tree.item(selected[0], "values")[0]

        if not messagebox.askyesno("确认删除", "确定要删除这条记录吗?"):
            return

        try:
            self.c.execute("DELETE FROM records WHERE id=?", (record_id,))
            self.conn.commit()
            self.history_tree.delete(selected[0])
            messagebox.showinfo("成功", "记录已删除")
            
            # 清除图片预览
            self.image_preview.config(image="")
            self.image_preview.image = None
            self.image_data = None
            
        except sqlite3.Error as e:
            messagebox.showerror("数据库错误", f"删除失败: {str(e)}")

    def load_data(self):
        """加载初始数据"""
        self.load_skill_tree()
        self.load_history()

    def on_close(self):
        """统一的关闭处理"""
        try:
            self.conn.commit()
            self.conn.close()
        except Exception as e:
            pass
        finally:
            self.root.destroy()

    def create_widgets(self):
        # 左侧技能树面板
        left_frame = ttk.Frame(self.root)
        left_frame.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10)

        self.tree = ttk.Treeview(left_frame, show="tree")
        self.tree.pack(fill=tk.Y, expand=True)

        btn_frame = ttk.Frame(left_frame)
        ttk.Button(btn_frame, text="添加大类", command=self.add_category).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="添加子项", command=self.add_subskill).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="删除项", command=self.delete_item).pack(side=tk.LEFT, padx=2)
        btn_frame.pack(pady=5)

        # 中间输入面板
        center_frame = ttk.Frame(self.root)
        center_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10, pady=10)

        input_frame = ttk.LabelFrame(center_frame, text="今日录入")
        input_frame.pack(fill=tk.X, pady=5)

        ttk.Label(input_frame, text="当前技能:").grid(row=0, column=0, sticky=tk.W)
        self.selected_skill = ttk.Label(input_frame, text="未选择", foreground="blue")
        self.selected_skill.grid(row=0, column=1, sticky=tk.W)

        ttk.Label(input_frame, text="分数/等级 (1-10):").grid(row=1, column=0, sticky=tk.W)
        self.score_var = tk.IntVar()
        ttk.Spinbox(input_frame, from_=1, to=10, textvariable=self.score_var, width=5).grid(row=1, column=1)

        ttk.Label(input_frame, text="学习总结:").grid(row=2, column=0, sticky=tk.NW)
        self.summary_text = tk.Text(input_frame, height=8, width=40)
        self.summary_text.grid(row=2, column=1, pady=5)

        ttk.Button(input_frame, text="上传图片", command=self.upload_image).grid(row=3, column=0, pady=5)
        ttk.Button(input_frame, text="保存记录", command=self.save_record).grid(row=3, column=1, pady=5)

        # 图片预览区域(放在今日录入框下方)
        self.image_preview = ttk.Label(center_frame)
        self.image_preview.pack(pady=10)
        self.image_data = None

        # 右侧历史记录面板
        history_frame = ttk.Frame(self.root)
        history_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10, pady=10)

        btn_frame = ttk.Frame(history_frame)
        ttk.Button(btn_frame, text="删除记录", command=self.delete_history).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="查找记录", command=self.search_records).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="全部记录", command=self.load_history).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="查看/编辑总结", command=self.edit_record).pack(side=tk.LEFT, padx=5)
        btn_frame.pack(fill=tk.X, pady=5)

        columns = ("id", "date", "skill", "score", "summary")
        self.history_tree = ttk.Treeview(
            history_frame,
            columns=columns,
            show="headings",
            selectmode="browse"
        )

        # 配置可见列
        self.history_tree.heading("date", text="日期")
        self.history_tree.heading("skill", text="技能路径")
        self.history_tree.heading("score", text="评分/评级")
        self.history_tree.heading("summary", text="总结")

        # 配置列参数
        self.history_tree.column("date", width=120, anchor="center")
        self.history_tree.column("skill", width=200)
        self.history_tree.column("score", width=80, anchor="center")
        self.history_tree.column("summary", width=300)

        # 隐藏ID列
        self.history_tree.column("id", width=0, stretch=tk.NO)


        # 滚动条
        scrollbar = ttk.Scrollbar(history_frame, orient="vertical", command=self.history_tree.yview)
        self.history_tree.configure(yscrollcommand=scrollbar.set)

        # 布局
        self.history_tree.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 绑定选择事件
        self.history_tree.bind("<<TreeviewSelect>>", self.on_history_select)
        self.tree.bind("<<TreeviewSelect>>", self.on_skill_select)
        
    def upload_image(self):
        file_path = filedialog.askopenfilename(filetypes=[("Image files", "*.png *.jpg *.jpeg *.gif *.bmp")])
        if file_path:
            with open(file_path, "rb") as file:
                self.image_data = file.read()
            self.display_image(self.image_preview, self.image_data, (400, 400))  # 调整大小以适应您的布局

    def display_image(self, label, image_data, size):
        if image_data:
            image = Image.open(io.BytesIO(image_data))
            image.thumbnail(size)
            photo = ImageTk.PhotoImage(image)
            label.config(image=photo)
            label.image = photo
        else:
            label.config(image="")
            label.image = None


    def add_subskill(self):
        """添加子技能(修正后的版本)"""
        selected = self.tree.selection()
        if not selected:
            messagebox.showerror("错误", "请先选择父级技能")
            return

        parent_id = selected[0]
        name = self.get_input("新建子项名称:")
        if name:
            parent_path = self.get_skill_path(parent_id)
            new_path = f"{parent_path}/{name}"

            try:
                # 使用self.c和self.conn
                self.c.execute(
                    "INSERT INTO skills (name, parent_id, path) VALUES (?,?,?)",
                    (name, parent_id, new_path)
                )
                self.conn.commit()
                skill_id = self.c.lastrowid
                self.tree.insert(parent_id, "end", iid=skill_id, text=name)
            except sqlite3.Error as e:
                messagebox.showerror("数据库错误", f"添加失败: {str(e)}")
    def load_skill_tree(self):
        """技能树加载"""
        try:
            self.tree.delete(*self.tree.get_children())

            # 获取所有技能并按层级排序
            self.c.execute('''
                WITH RECURSIVE skill_tree(id, name, parent_id, depth) AS (
                    SELECT id, name, parent_id, 0
                    FROM skills WHERE parent_id IS NULL
                    UNION ALL
                    SELECT s.id, s.name, s.parent_id, st.depth + 1
                    FROM skills s
                    JOIN skill_tree st ON s.parent_id = st.id
                )
                SELECT * FROM skill_tree ORDER BY depth, parent_id
            ''')

            # 创建临时存储父节点的字典
            nodes = {}
            for skill_id, name, parent_id, _ in self.c.fetchall():
                if parent_id is None:
                    node = self.tree.insert("", "end", iid=skill_id, text=name)
                else:
                    parent = nodes.get(parent_id)
                    if parent:
                        node = self.tree.insert(parent, "end", iid=skill_id, text=name)
                nodes[skill_id] = skill_id  # 保存节点ID
        except sqlite3.Error as e:
            messagebox.showerror("数据库错误", f"加载技能树失败: {str(e)}")

    def save_record(self):
        skill_path = self.selected_skill['text']
        if skill_path == "未选择":
            messagebox.showerror("错误", "请先选择一个技能")
            return

        try:
            score = self.score_var.get()
            if not 1 <= score <= 10:
                raise ValueError
        except:
            messagebox.showerror("错误", "请输入1-10之间的整数")
            return

        summary = self.summary_text.get("1.0", tk.END).strip()
        date = datetime.now().strftime("%Y-%m-%d")

        try:
            self.c.execute(
                "INSERT INTO records (skill_path, score, date, summary, image) VALUES (?,?,?,?,?)",
                (skill_path, score, date, summary, self.image_data)
            )
            self.conn.commit()
            messagebox.showinfo("成功", "记录已保存!")

            self.summary_text.delete("1.0", tk.END)
            self.image_data = None
            self.image_preview.config(image="")
            self.image_preview.image = None
            self.load_history()
        except sqlite3.Error as e:
            messagebox.showerror("数据库错误", f"保存失败: {str(e)}")

    def load_history(self):
        try:
            self.history_tree.delete(*self.history_tree.get_children())
            self.c.execute("SELECT id, date, skill_path, score, summary FROM records ORDER BY date DESC, id DESC")
            for record in self.c.fetchall():
                self.history_tree.insert("", "end", values=record)
        except sqlite3.Error as e:
            messagebox.showerror("数据库错误", f"加载失败: {str(e)}")


    def on_history_select(self, event):
        selected = self.history_tree.selection()
        if selected:
            record_id = self.history_tree.item(selected[0], "values")[0]
            self.c.execute("SELECT image FROM records WHERE id=?", (record_id,))
            result = self.c.fetchone()
            if result:
                image_data = result[0]
                self.display_image(self.image_preview, image_data, (400, 400))
            else:
                self.image_preview.config(image="")
                self.image_preview.image = None

    def get_skill_path(self, item_id):
        """获取技能完整路径"""
        path = []
        while item_id:
            item = self.tree.item(item_id)
            path.append(item['text'])
            item_id = self.tree.parent(item_id)
        return '/'.join(reversed(path))
    

    def on_skill_select(self, event):
        selected = self.tree.selection()
        if selected:
            path = self.get_skill_path(selected[0])
            self.selected_skill.config(text=path)

            
    def get_input(self, prompt):
        """获取用户输入"""
        dialog = tk.Toplevel()
        dialog.title("输入")
        ttk.Label(dialog, text=prompt).pack(padx=10, pady=5)
        entry = ttk.Entry(dialog)
        entry.pack(padx=10, pady=5)
        result = []

        def on_ok():
            result.append(entry.get())
            dialog.destroy()

        ttk.Button(dialog, text="确定", command=on_ok).pack(pady=5)
        dialog.wait_window()
        return result[0] if result else None

    def search_records(self):
        search_window = tk.Toplevel(self.root)
        search_window.title("查找记录")

        ttk.Label(search_window, text="日期 (YYYY-MM-DD):").grid(row=0, column=0, padx=5, pady=5)
        date_entry = ttk.Entry(search_window)
        date_entry.grid(row=0, column=1, padx=5, pady=5)

        ttk.Label(search_window, text="技能路径:").grid(row=1, column=0, padx=5, pady=5)
        skill_entry = ttk.Entry(search_window)
        skill_entry.grid(row=1, column=1, padx=5, pady=5)

        def perform_search():
            date = date_entry.get()
            skill = skill_entry.get()
            
            query = "SELECT id, date, skill_path, score, summary FROM records WHERE 1=1"
            params = []
            
            if date:
                query += " AND date = ?"
                params.append(date)
            
            if skill:
                query += " AND skill_path LIKE ?"
                params.append(f"%{skill}%")
            
            query += " ORDER BY date DESC"
            
            try:
                self.c.execute(query, params)
                results = self.c.fetchall()
                
                self.history_tree.delete(*self.history_tree.get_children())
                for record in results:
                    self.history_tree.insert("", "end", values=record)
                
                search_window.destroy()
            except sqlite3.Error as e:
                messagebox.showerror("查询错误", str(e))

        ttk.Button(search_window, text="查找", command=perform_search).grid(row=2, column=0, columnspan=2, pady=10)

    def edit_record(self):
        selected = self.history_tree.selection()
        if not selected:
            messagebox.showwarning("提示", "请先选择要 查看/编辑 的记录")
            return

        record_id = self.history_tree.item(selected[0], "values")[0]
        
        # 获取当前记录信息
        self.c.execute("SELECT summary FROM records WHERE id=?", (record_id,))
        current_summary = self.c.fetchone()[0]

        edit_window = tk.Toplevel(self.root)
        edit_window.title(" 查看/编辑 记录")
        edit_window.geometry("400x300+360+280")

        ttk.Label(edit_window, text=" 查看/编辑 总结:").pack(padx=5, pady=5)
        summary_text = tk.Text(edit_window, height=8, width=40)
        summary_text.pack(padx=5, pady=5)
        summary_text.insert(tk.END, current_summary)
        summary_text.config(state='disabled')  # 初始状态设为禁用

        save_button = ttk.Button(edit_window, text="保存", state='disabled')
        save_button.pack(pady=10)

        def toggle_edit_state():
            if allow_edit_var.get():
                summary_text.config(state='normal')
                save_button.config(state='normal')
            else:
                summary_text.config(state='disabled')
                save_button.config(state='disabled')

        def save_edit():
            new_summary = summary_text.get("1.0", tk.END).strip()
            try:
                self.c.execute("UPDATE records SET summary=? WHERE id=?", (new_summary, record_id))
                self.conn.commit()
                messagebox.showinfo("成功", "记录已更新")
                edit_window.destroy()
                self.load_history()  # 刷新显示
            except sqlite3.Error as e:
                messagebox.showerror("数据库错误", f"更新失败: {str(e)}")

        # 添加允许编辑的复选框
        allow_edit_var = tk.BooleanVar()
        allow_edit_checkbox = ttk.Checkbutton(edit_window, text="允许编辑", variable=allow_edit_var, 
                                              command=toggle_edit_state)
        allow_edit_checkbox.pack(pady=5)

        save_button.config(command=save_edit)

        # 添加取消按钮
        ttk.Button(edit_window, text="取消", command=edit_window.destroy).pack(pady=5)

        # 使窗口成为模态窗口
        edit_window.transient(self.root)
        edit_window.grab_set()
        self.root.wait_window(edit_window)

if __name__ == "__main__":
    root = tk.Tk()
    app = SkillTracker(root)
    root.mainloop()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2342450.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux常见指令介绍下(入门级)

1. head head就和他的名字一样&#xff0c;是显示一个文件头部的内容&#xff08;会自动排序&#xff09;&#xff0c;默认是打印前10行。 语法&#xff1a;head [参数] [文件] 选项&#xff1a; -n [x] 显示前x行。 2. tail tail 命令从指定点开始将文件写到标准输出.使用t…

VIC-3D非接触全场应变测量系统用于小尺寸测量之电子元器件篇—研索仪器DIC数字图像相关技术

在5G通信、新能源汽车电子、高密度集成电路快速迭代的今天&#xff0c;电子元件的尺寸及连接工艺已进入亚毫米级竞争阶段&#xff0c;这种小尺寸下的力学性能评估对测量方式的精度有更高的要求&#xff0c;但传统应变测量手段常因空间尺寸限制及分辨率不足难以捕捉真实形变场。…

下篇:深入剖析 BLE GATT / GAP / SMP 与应用层(约5000字)

引言 在 BLE 协议栈的最上层,GAP 定义设备角色与连接管理,GATT 构建服务与特征,SMP 负责安全保障,应用层则承载具体业务逻辑与 Profile。掌握这一层,可实现安全可靠的设备发现、配对、服务交互和定制化业务。本文将详解 GAP、GATT、SMP 三大模块,并通过示例、PlantUML 时…

27、Session有什么重⼤BUG?微软提出了什么⽅法加以解决?

Session的重大BUG 1、进程回收导致Session丢失 原理&#xff1a; IIS的进程回收机制会在系统繁忙、达到特定内存阈值等情况下&#xff0c;自动回收工作进程&#xff08;w3wp.exe&#xff09;。由于Session数据默认存储在进程内存中&#xff0c;进程回收时这些数据会被清除。 …

云智融合普惠大模型AI,政务服务重构数智化路径

2025年是“十四五”收官之年&#xff0c;数字政府和政务数智化作为“数字中国”建设的重点&#xff0c;已经取得了显著成效。根据《联合国电子政务调查报告2024》&#xff0c;我国电子政务发展指数全球排名第35位&#xff0c;与2022年相比提升8个名次&#xff1b;其中&#xff…

UE5 调整字体、界面大小

文章目录 方案一 5.4 版本及以上&#xff08;推荐&#xff09;方案二 5.3 版本及以下&#xff08;推荐&#xff09;方案三 使用插件&#xff08;不推荐&#xff09; 方案一 5.4 版本及以上&#xff08;推荐&#xff09; 进入 编辑 > 编辑器偏好设置&#xff0c;如下图所示&…

抽象类相关

抽象类的定义 抽象类 是一种特殊的类&#xff0c;它不能被实例化&#xff0c;只能作为基类来派生出具体类。抽象类至少包含一个纯虚函数 。纯虚函数是在函数原型前加上 0 的虚函数&#xff0c;表示该函数没有具体实现&#xff0c;必须由派生类来实现。 抽象类的作用 提供统…

【UVM项目实战】异步fifo—uvm项目结构以及uvm环境搭建

本文章同步到我的个人博客网站&#xff1a;ElemenX-King&#xff1a;【UVM项目实战】异步fifo—uvm项目结构以及uvm环境搭建 希望大家能使用此网站来进行浏览效果更佳&#xff01;&#xff01;&#xff01; 目录 一、异步FIFO1.1 异步FIFO的定义1.2 亚稳态1.3 异步FIFO关键技术…

【通关函数的递归】--递归思想的形成与应用

目录 一.递归的概念与思想 1.定义 2.递归的思想 3.递归的限制条件 二.递归举例 1.求n的阶乘 2.顺序打印一个整数的每一位 三.递归与迭代 前言:上篇博文分享了扫雷游戏的实现&#xff0c;这篇文章将会继续分享函数的递归相关知识点&#xff0c;让大家了解并掌握递归的思…

【FAQ】针对于消费级NVIDIA GPU的说明

概述 本文概述 HP Anyware 在配备消费级 NVIDIA GPU 的物理工作站上的关​​键组件、安装说明和重要注意事项。 注意&#xff1a;本文档适用于 NVIDIA 消费级 GPU。NVIDIA Quadro 和 Tesla GPU 也支持 HP Anyware 在公有云、虚拟化或物理工作站环境中运行。请参阅PCoIP Graphi…

MyBatis操作数据库---从入门到理解

文章目录 关于MyBatis操作数据库MyBatis⼊⻔&#xff08;使用&#xff09;Mybatis操作数据库的步骤&#xff1a;配置数据库连接字符串使⽤MyBatis完成简单的增删改查操作注解xml 单元测试开启驼峰命名(推荐) 打印日志 关于MyBatis操作数据库 在之前的学习,我们了解到web应⽤程…

【HFP】蓝牙语音通话控制深度解析:来电拒接与通话终止协议

目录 一、来电拒接的核心流程与信令交互 1.1 拒接场景的分类与触发条件 1.2 HF 端拒接流程 1.3 AG 端拒接流程 二、通话终止流程&#xff1a;主动断开与异常中断 2.1 终止场景的界定 2.2 HF 端终止流程 2.3 AG 端终止流程 三、信令协议的核心要素&#xff1a;AT 命令与…

使用QML Tumbler 实现时间日期选择器

目录 引言相关阅读项目结构示例实现与代码解析示例一&#xff1a;时间选择器&#xff08;TimePicker&#xff09;示例二&#xff1a;日期时间选择器&#xff08;DateTimePicker&#xff09; 主窗口整合运行效果总结下载链接 引言 在现代应用程序开发中&#xff0c;时间与日期选…

智能吸顶灯/摄影补光灯专用!FP7195双通道LED驱动,高效节能省空间 !

一、双路调光技术背景与市场需求 随着LED照明技术的快速发展和智能照明需求的激增&#xff0c;双路调光技术正成为照明行业的重要发展方向。传统单路调光方案只能实现整体亮度的统一调节&#xff0c;而双路调光则能够实现对两个独立通道的精确控制。今天&#xff0c;由我来为大…

YOLOv11改进-双Backbone架构:利用双backbone提高yolo11目标检测的精度

一、引言&#xff1a;为什么我们需要双Backbone&#xff1f; 在目标检测任务中&#xff0c;YOLO系列模型因其高效的端到端检测能力而备受青睐。然而&#xff0c;传统YOLO模型大多采用单一Backbone结构&#xff0c;即利用一个卷积神经网络&#xff08;CNN&#xff09;作为特征提…

《逃离云端束缚,拥抱GPT本地部署》

《逃离云端束缚,拥抱GPT本地部署》 一、GPT 热潮与本地部署的兴起 自 OpenAI 推出 ChatGPT 以来,全球范围内掀起了一股人工智能的热潮,其强大的自然语言处理能力和广泛的应用场景,让人们对人工智能的未来充满了想象。GPT(Generative Pretrained Transformer)作为一种基于…

头歌之动手学人工智能-机器学习 --- PCA

目录 第1关&#xff1a;维数灾难与降维 第2关&#xff1a;PCA算法流程 任务描述 编程要求 测试说明 第3关&#xff1a;sklearn中的PCA 任务描述 编程要求 测试说明 第1关&#xff1a;维数灾难与降维 第2关&#xff1a;PCA算法流程 任务描述 本关任务&#xff1a;补充…

研0调研入门

一、Web of Science 使用教程 1. 访问与注册 访问入口&#xff1a;通过高校图书馆官网进入&#xff08;需IP权限&#xff09;&#xff0c;或直接访问 Web of Science官网。注册/登录&#xff1a;若机构已订阅&#xff0c;用学校账号登录&#xff1b;个人用户可申请试用或付费…

神经网络基础[ANN网络的搭建]

神经网络 人工神经网络&#xff08; Artificial Neural Network&#xff0c; 简写为ANN&#xff09;也简称为神经网络&#xff08;NN&#xff09;&#xff0c;是一种模仿生物神经网络结构和功能的计算模型。各个神经元传递复杂的电信号&#xff0c;树突接收到输入信号&#xf…

五、web自动化测试01

目录 一、HTML基础1、HTML介绍2、常用标签3、基础案例3.1 前端代码3.2 自动化测试 二、CSS定位1、css介绍2、案例3、代码优化 三、表单自动化1、案例2、元素属性定位 四、后台基础数据自动化1、登录1.1 id与class定位1.2 定位一组元素 2、商品新增 一、HTML基础 可参考学习 链…