schooldb代码实战:MySQL学生选课系统数据库设计全解析
搜“schooldb代码”的人十有八九都是同一类需求要么是数据库课设不知道从哪下手要么是公司里突然要接一个校园管理相关的数据层想找个偏教学向、能直接跑的库来抄作业。这个方向我帮不少人做过参考也接过不少来问“为什么我跑不起来”的求助今天干脆把这套东西从头到尾拆开讲清楚。schooldb不是某个官方开源项目它更像一类“约定俗成”的学校业务数据库示例核心是学生、课程、选课、成绩这几个绕不开的模块再加上配套的建表SQL、数据初始化脚本、增删改查和统计查询的代码。它能帮你搞懂一件事一张孤零零的表好建但几张表之间怎么关联、约束怎么设计、事务怎么保证不乱这才是数据库真正值钱的部分。适合刚学完SQL基础但不知道怎么做完整项目的新手、要做课设的学生小组也想给那些只写过单表增删改查、没接触过数据建模的程序员一个完整的参考样板。1. 内容整体设计与思路拆解1.1 先把学校业务拆成最小闭环做学校数据库最容易犯的错误是一上来就堆表专业表、班级表、宿舍表、教师表、请假表、社团表……最后建了二十多张表数据一填就乱外键一删就报错。我的建议是先跑通最小闭环再做横向扩展。学校业务最小闭环绕不开一条链路——学生能选课课程有人选选了要出成绩成绩要能查。所有校园系统不管做得再花哨最后落到数据库层面都逃不出这三张核心实体表和一张关联表学生表student记录学生的基本身份信息课程表course记录课程的基本信息和容量选课表enrollment学生和课程的多对多关系同时承载成绩字段为什么选课表要承载成绩而不是再单独建一张成绩表这是很多人想不明白的点。选课行为发生后的结果就是成绩成绩不是独立于选课过程之外的东西。一个人选了课这门课的最终状态就是成绩。单拆一张成绩表意味着你要维护“选课记录”和“成绩记录”两条链路还得分神去保证它们一一对应。倒不如让选课表里的状态字段管理生命周期已选、退选、已结课结课就填成绩。这样查询“某学生所有成绩单”本质就是按学生ID查选课表不需要额外的JOIN链条。1.2 技术选型为什么是MySQL Python技术栈的选择不需要追新关键是稳定、贴近实际、样例代码好抄。我建议的默认组合是MySQL 8.0 Python 3 PyMySQL理由很简单MySQL是教学场景最常见的关系型数据库讨论可移植性、索引、事务都有大量现成资料。PyMySQL是纯Python实现的驱动不用编译装完就能连比某些需要在系统层面装客户端库的方案省事得多。Python本身的写法也更接近自然语言新手除了看SQL外不用花大量精力去理解Java那套繁琐的连接管理。如果用Java那套JDBC做示例新手很容易被Class.forName、DriverManager、PreparedStatement这一堆样板代码带走注意力反而忘了真正的重点——SQL和表结构。用Python写CRUD核心逻辑几行代码就能看清楚这个优势在分享和教学场景里非常明显。提示如果你所在的环境只有SQL Server或PostgreSQL表结构思路完全通用只是语法细节如自增关键字、字符串拼接要做对应调整。设计思想比具体数据库产品更重要。2. 核心细节解析与实操要点2.1 四张核心表的设计取舍student学生表学生表的字段设计很能看出一个人做数据建模的水平。基础信息里最容易起争议的是主键选择。很多人第一反应是“拿学号做主键”学号唯一、业务上明确、查询方便。但学号是业务字段不是稳定的自然主键。学生可能转专业、复读、学号规则调整一旦学号发生变化所有关联表的外键都要跟着改这属于典型的“改一处牵连一片”的设计。正确姿势是使用无业务含义的自增代理主键id学号加上唯一索引做业务凭证。这个道理和网站的用户表一样你登录用的是用户名但系统内部所有关联都用user_id用户名可以改user_id不能变。性别字段的选择也值得一提——用ENUM(男,女)最省事但以后需求一变要加“保密”选项ALTER TABLE改枚举类型是一件很麻烦的事情。用CHAR(1)存M、F、U简单、直观、好扩展。如果更在意存储效率用TINYINT加注释也是一样的道理。course课程表课程表除了课程名称、学分、任课教师这些基础字段外一定要有**容量capacity和已选人数selected_count**这两个字段。为什么不能到了选课的时候现算“SELECT COUNT(*) FROM enrollment”因为性能。选课是高频操作每次选课都全表统计选课人数等数据量大了课程表本身只有几十行选课表可能有几万行每一次COUNT都要扫一遍。直接在课程表上维护一个计数器选课成功就1退选就-1这是典型的冗余字段优化——用空间换时间但冗余的前提是必须在同一个事务里维护保证两边的数字永远一致。enrollment选课表选课表是三张表里的灵魂。它的设计要点有三个学生和课程建立多对多关系所以核心字段就是student_id和course_id要记录选课状态我用status字段管理active已选、dropped已退选、finished已结课出成绩成绩字段score DECIMAL(4,2)直接放在选课表上只有statusfinished时才有意义这里最重要的一个设计是唯一约束UNIQUE KEY(student_id, course_id)。这个约束从数据库层面保证了一个学生同一门课只有一条选课记录哪怕你的应用层代码忘了判断数据库也会拒绝重复插入这是防止脏数据的最后一道防线。2.2 字段类型选择踩过的坑字段类型选得不对轻则浪费存储重则上生产就出事故。我把最常见的选择逻辑列一下字段推荐类型不推荐的做法原因主键IDBIGINT UNSIGNEDINTINT上限约21亿看似够用但一旦涉及分表、合并或对接其他系统的大ID很容易撞顶学号VARCHAR(20)INT学号有前导零、字母且不需要参与数学计算姓名VARCHAR(32)VARCHAR(255)中文姓名按字符数算32字符已经覆盖绝大多数场景255是浪费性别CHAR(1)ENUMENUM修改枚举值成本高扩展性差成绩DECIMAL(4,2)FLOAT/DOUBLE浮点数有精度问题0.10.7可能等于0.79999999创建时间DATETIMEVARCHARVARCHAR存时间无法做范围比较和排序成绩用DECIMAL(4,2)表示总长度4位整数部分2位小数部分2位最大能存99.99对百分制来说够用且精确。如果有些课程按等级制给成绩存字母用VARCHAR(2)也行但那就不能和百分制混在一个字段里了这是个业务规则问题不是数据类型问题做题的时候想清楚就行。2.3 外键到底建不建这是个被争论很久的问题我的立场很明确教学项目和中小型系统建外键。总有人说“外键影响性能、大厂都不用外键”但大厂不用外键是因为他们做了分库分表数据库层面已经无法维持跨库的引用完整性只能用应用层兜底。你的表都在同一个库里没有任何理由抛弃外键。外键的价值在于当有人手动删了一条学生记录而忘了删他的选课记录时数据库自己会报错或者触发级联处理不用等数据烂了再人工排查。建外键时要想清楚ON DELETE的行为。选课记录依附于学生和课程学生删了、课程删了选课记录自然没有存在的意义所以用ON DELETE CASCADE没问题。但如果你以后要保留学生历史选课存档就不能级联删而是要在学生表上做软删除。3. 实操过程与核心环节实现3.1 建库建表脚本可直接抄先把SQL脚本完整贴出来这是我反复调过多次、可以照抄的版本CREATE DATABASE IF NOT EXISTS schooldb DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci; USE schooldb; CREATE TABLE student ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, student_no VARCHAR(20) NOT NULL, student_name VARCHAR(32) NOT NULL, gender CHAR(1) NOT NULL DEFAULT U COMMENT M-男 F-女 U-保密, enroll_date DATE NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_student_no (student_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT学生表; CREATE TABLE course ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, course_name VARCHAR(64) NOT NULL, credit DECIMAL(3,1) NOT NULL DEFAULT 0.0, teacher_name VARCHAR(32) NOT NULL DEFAULT , capacity INT NOT NULL DEFAULT 0 COMMENT 课程容量, selected_count INT NOT NULL DEFAULT 0 COMMENT 已选人数, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT课程表; CREATE TABLE enrollment ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, student_id BIGINT UNSIGNED NOT NULL, course_id BIGINT UNSIGNED NOT NULL, score DECIMAL(4,2) NULL COMMENT 成绩结课后填写, status VARCHAR(10) NOT NULL DEFAULT active COMMENT active-已选 dropped-退课 finished-已结课, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_enroll_student_course (student_id, course_id), KEY idx_course_id (course_id), CONSTRAINT fk_enroll_student FOREIGN KEY (student_id) REFERENCES student (id) ON DELETE CASCADE, CONSTRAINT fk_enroll_course FOREIGN KEY (course_id) REFERENCES course (id) ON DELETE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT选课表;这里几个细节要说明一下字符集用utf8mb4而不是utf8。utf8在MySQL里最多支持3字节字符很多生僻字和emoji都是4字节用utf8存储会直接报错或被截断。utf8mb4是utf8的超集任何字符都能装。updated_at用ON UPDATE CURRENT_TIMESTAMP。这一行的作用是只要这一行的数据被修改updated_at字段会自动刷新不需要你手动在UPDATE语句里维护它。调试问题的时候看到“数据变了但是不知道什么时候变的”这个字段可以救命。主键全部用BIGINT UNSIGNED AUTO_INCREMENT。不解释业务含义纯粹当行标识用。最开始的版本里我用过INT后来模拟数据插到3万行没问题但想到如果对接微信这种大数字ID还是早点换成BIGINT更安心。3.2 初始化数据与连接参数表建好之后塞几行测试数据INSERT INTO student (student_no, student_name, gender, enroll_date) VALUES (20240001, A同学, M, 2024-09-01), (20240002, B同学, F, 2024-09-01), (20240003, C同学, M, 2024-09-01); INSERT INTO course (course_name, credit, teacher_name, capacity) VALUES (数据库原理, 3.0, 某老师, 2), (计算机网络, 2.5, 某老师, 3), (数据结构, 4.0, 某老师, 2);容量故意设置的很小方便测试选课满了之后的逻辑。Python连接代码import pymysql conn pymysql.connect( host127.0.0.1, port3306, userroot, passwordyour_password, databaseschooldb, charsetutf8mb4, cursorclasspymysql.cursors.DictCursor, autocommitFalse )autocommitFalse这条很重要——它让你手动控制事务边界。选课这种含两步操作改计数器插记录的场景必须让两步在一个事务里一起成功或一起失败。3.3 核心查询选课人数排行、成绩单、未选课名单选课人数排行。排行榜最核心的点是没人选的热门课程也要出现在结果里所以必须用LEFT JOINSELECT c.course_name, COUNT(e.id) AS active_count FROM course c LEFT JOIN enrollment e ON e.course_id c.id AND e.status active GROUP BY c.id, c.course_name ORDER BY active_count DESC;注意LEFT JOIN后面那个AND e.status active。如果把这个条件写在WHERE里LEFT JOIN就变成了INNER JOIN——没入选课记录的课程会被过滤掉。这是SQL新人最容易掉进去的坑。学生成绩单。选课表里只有statusfinished的记录才有成绩SELECT s.student_no, s.student_name, c.course_name, e.score, c.credit FROM enrollment e JOIN student s ON e.student_id s.id JOIN course c ON e.course_id c.id WHERE s.id %s AND e.status finished;未选任何课的学生。推荐用NOT EXISTS而不是NOT INSELECT s.* FROM student s WHERE NOT EXISTS ( SELECT 1 FROM enrollment e WHERE e.student_id s.id AND e.status active );用NOT IN的子查询结果如果包含NULL值整个查询会返回空结果集这是SQL标准里很反直觉的一个行为。NOT EXISTS和关联子查询不受这个影响稳妥得多。3.4 选课事务怎么写才是对的选课业务的关键在于并发情况下容量不能超卖。如果你写的是“先查一下人数有没有满没满再插”那在高并发下会出问题——两个请求同时查到剩余1个名额然后同时插入就超了。正确的做法是用一条原子的UPDATE来做容量校验def enroll_student(conn, student_id, course_id): with conn.cursor() as cur: # 原子操作更新成功且影响行数为1说明还有名额 cur.execute( UPDATE course SET selected_count selected_count 1 WHERE id %s AND selected_count capacity, (course_id,) ) if cur.rowcount ! 1: raise RuntimeError(课程不存在或名额已满) # 插入选课记录唯一约束防止重复选课 cur.execute( INSERT INTO enrollment (student_id, course_id, status) VALUES (%s, %s, active), (student_id, course_id) ) conn.commit()这段代码的精髓在UPDATE语句WHERE selected_count capacity是数据库在修改这行数据时立即做的判断如果名额不够这行更新失败影响行数为0。这比“SELECT再INSERT”的方式安全很多因为UPDATE和INSERT在同一个事务里被数据库引擎串行化处理不会出现选出旧数据再覆盖更新的问题。rowcount是PyMySQL中受影响行数的属性。注意这只是你作为调用方看到的结果底层MySQL用的是行锁来保证并发正确性——InnoDB存储引擎会在UPDATE时锁住这一行其他事务的UPDATE会等待或超时这是它保证原子性的机制。如果发现插入选课记录时违反唯一约束学生重复选同一门课需要回滚让计数器也还原try: conn.commit() except Exception: conn.rollback() raise不写rollback的话事务里第一步的selected_count 1就会残留在事务缓冲区里等下个事务提交时一起写进去造成计数器虚高这是很隐蔽的bug。4. 常见问题与排查技巧实录做了这么多轮参考和协助之后我把大家踩的频率最高的坑整理成一个速查表发现问题基本可以对号入座。4.1 中文乱码的三层排查中文乱码是最常见的入门问题也是三分钟能解决的问题。排查顺序很重要连接串、表结构、终端显示。第一层PyMySQL的charset参数没写或写了charsetutf8。改成utf8mb4绝大多数乱码问题消失。第二层表本身的字符集是不是utf8mb4。建表时用DEFAULT CHARSETutf8mb4就没问题如果建表时用的latin1哪怕连接串改了也白搭需要ALTER TABLE student CONVERT TO CHARACTER SET utf8mb4。第三层终端或IDE的显示编码。Windows自带的cmd默认GBK看到的中文乱码不一定是数据库存错了可能是显示层解码错了。用VS Code或直接用Python读取打印看结果可以区分是显示问题还是存储问题。4.2 外键删除报错Deletion of parent row很多人建了外键之后删学生记录时遇到Cannot delete or update a parent row: a foreign key constraint fails一脸懵。这个错误的含义是你要删的父表记录还有子表记录引用着它。比如删除一个还有选课记录的学生因为fk_enroll_student的存在数据库会拦下删除动作。解决方法是提前想好外键的ON DELETE行为。我在建表脚本里用的ON DELETE CASCADE——删学生时系统自动把他的选课记录一并删除。如果你不想自动删就要在应用层先删子记录再删父记录顺序不能反。4.3 连接数耗尽一个非常典型的隐性问题代码里反复打开数据库连接用完却不关闭一段时间后MySQL报Too many connections。尤其是新手用PyMySQL写个循环插入每跑一遍都pymysql.connect()一次循环万次后连接数直接打到上限。解决方式小项目也要有基本的连接管理习惯。最简单是在业务代码里用with conn.cursor()加finally时close()或者用contextlib.closing(conn)包住连接。但更优雅的方案是用连接池技术比如DBUtils.PooledDB把连接复用起来。4.4 自增主键会耗尽吗主键用INT确实有耗尽的风险但在小项目里基本不会碰到。真正值得注意的是自增主键不连续不等于有问题。删除一些行之后下次插入会继续从当前最大值1开始不会回填被删掉的ID这是正常行为不要试图去“修复”。BIGINT的上限大约是922亿亿对教学项目来说就是天文数字所以一开始就用BIGINT最省心。4.5 密码字段的最小底线如果你在项目里接入了学生登录功能密码存储有一条底线明文存储绝对不能出现用MD5也不行。MD5和SHA1这类快速哈希已经被硬件算力瓦解用它们存密码等于半明文。哪怕只是课设也应该用bcrypt这类慢哈希算法。from werkzeug.security import generate_password_hash, check_password_hash # 存密码 hashed generate_password_hash(student123) # 验证密码 check_password_hash(hashed, student123)注意这行的要点generate_password_hash每次生成的哈希值都不一样因为带了随机盐所以验证密码必须用专用的check_password_hash不能直接比对字符串。5. 扩展方向从课设到真实项目的距离跑通了上面这些内容说明你已经有能力做一个基本完整的小系统了。如果还想再往前一步这些方向值得尝试。5.1 分页查询的深水区列表分页最经典的写法是LIMIT offset, page_size但当偏移量到几万之后数据库会扫描并丢弃前面所有行性能断崖式下跌。优化手段是延迟关联SELECT s.id, s.student_name FROM student s JOIN ( SELECT id FROM student ORDER BY id LIMIT 100000, 20 ) tmp ON s.id tmp.id;先只查主键ID做深分页再回表查完整数据因为主键索引小而快回表只在最终20行发生。5.2 乐观锁与并发选课之前讲的UPDATE course SET selected_count selected_count 1 WHERE selected_count capacity是悲观锁思路——通过更新时的条件判断覆盖并发问题。还有一种办法是给课程表加一个version字段先读版本号更新时比对版本UPDATE course SET selected_count selected_count 1, version version 1 WHERE id %s AND version %s;影响行数为0就说明版本冲突需要重新查询再试。这个思路在分布式环境更通用因为它不依赖单库行锁用Redis也能做类似的事情。5.3 输出环境准备好再动手实际写代码之前建议先把环境准备好。MySQL 8.0安装、Python装好PyMySQL数据库工具用Navicat或VS Code扩展都可以。这部分和业务逻辑无关但卡住的人相当多。我的习惯是建一个schema.sql目录把建表脚本交给git管理。每个表都加上created_at和updated_at之后调试任何诡异的数据问题都能靠这两个时间字段缩小范围。这个习惯可以伴随你整个职业生涯。最后再分享一个我自己的体会写这套东西的过程里我踩过最大的坑就是“一开始没想清楚外键怎么删”导致某个演示项目的孤儿数据膨胀到了两万多行最后花了大半个晚上清洗。数据库设计里的每一个选择在没有数据的时候都显得无所谓一旦数据到了规模当初省的那点功夫都会加倍还回来。你把这篇文章里的表结构和事务逻辑理解透了至少在校期间所有带数据库的系统设计都能从容应对了。

相关新闻

学习打卡功能开发实战:从表结构设计到线上踩坑全记录

学习打卡功能开发实战:从表结构设计到线上踩坑全记录

前段时间接了一个学习类App的项目,需求池里躺着一个编号3.10的任务,名字就四个字:学习打卡。当时团队里不少人都觉得,这不就是给用户一个按钮,每天点一下签个到吗?结果真进入开发阶段才发现,这个…

2026/10/18 4:39:33 阅读更多 →
AI敏捷招聘引擎:用行为数据和预测模型重构2026人才决策

AI敏捷招聘引擎:用行为数据和预测模型重构2026人才决策

我做了六年多的人力资源数字化系统建设,从最初的ATS选型到如今基于行为数据的预测模型,一路踩坑一路迭代,发现一个残酷的现实:传统的招聘方式,已经撑不起2026年的人才竞争了。你可能还在用"简历关键词匹配面试官直…

2026/10/18 4:39:32 阅读更多 →
告别帐号限制,OpenAI Codex 零基础速通,配合 Codex++ 完美解锁 TaoToken 配置

告别帐号限制,OpenAI Codex 零基础速通,配合 Codex++ 完美解锁 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 4:39:32 阅读更多 →

最新新闻

律所案件管理系统设计与落地:角色权限、流程引擎与文书协同实践

律所案件管理系统设计与落地:角色权限、流程引擎与文书协同实践

1. 这个系统到底在解决什么问题做律师的朋友应该都有过这种体验:一个案子从收到材料到最终归档,中间要经过立案、排期、取证、文书起草、审核、盖章、送达、开庭、归档这么一串流程。传统做法是什么?微信群接龙、Excel表格、共享文件夹、Outl…

2026/10/18 5:36:42 阅读更多 →
YOLO固定翼无人机检测数据集实战:从目录结构到训练避坑指南

YOLO固定翼无人机检测数据集实战:从目录结构到训练避坑指南

简介:面向固定翼无人机视觉检测任务,这份YOLO格式数据集包含数百张真实场景图片,已按mq-20-drone单类别完成标注,适用于yolov5、yolov7、yolov8等主流目标检测算法。数据集目录已预先划分好train、val、test集合,并附带…

2026/10/18 5:36:42 阅读更多 →
基于UDP的自定义Socket封装:设计思路与踩坑实录

基于UDP的自定义Socket封装:设计思路与踩坑实录

做网络传输相关项目的时候,UDP往往是绕不开的一个选项。它比TCP轻量、不维持连接状态、没有握手过程,天然适合实时音视频、游戏同步、设备状态上报这类场景。可UDP真正用起来之后你就会发现,原生Socket虽然几行代码就能把数据发出去&#xff…

2026/10/18 5:36:42 阅读更多 →
无人机频射信号检测:YOLOv5目标检测实战与数据集解析

无人机频射信号检测:YOLOv5目标检测实战与数据集解析

简介:面向无人机频射信号检测与识别任务,这份数据集包含364张原始图像及配套的yolov5格式标注txt文件,平均正确识别率达到94.3%,适用于基于目标检测框架的模型训练与算法验证。资源包共729个文件,以jpg图像和txt标签为…

2026/10/18 5:36:42 阅读更多 →
2026年AI模型API聚合服务实力横评:词元之河与硅基流动的稳定性与落地适配对比

2026年AI模型API聚合服务实力横评:词元之河与硅基流动的稳定性与落地适配对比

中小技术团队部署大模型应用,普遍要过三道坎:其一,境外模型直连受网络策略、IP 信誉与额度审批限制,平均开通要等好几个工作日;其二,国产模型协议碎片化,Qwen、GLM、DeepSeek、Claude 各家的字段…

2026/10/18 5:36:42 阅读更多 →
GPS+INS组合导航:惯导漂移、误差状态卡尔曼滤波与工程避坑指南

GPS+INS组合导航:惯导漂移、误差状态卡尔曼滤波与工程避坑指南

简介:面向组合导航学习与研究者的Matlab实现资源,重点解决GPS信号在高楼密集区、树林或电磁干扰下易丢失,而惯导系统误差随运行时间不断累积的问题,通过两者优势互补实现连续稳定的高精度导航。资源适合导航专业学生、算法工程师及…

2026/10/18 5:35:42 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →