USB存储设备识别:从描述符到系统块设备的完整判定指南

判断一个USB设备到底是不是存储设备,这个需求在驱动开发、系统工具、安全管控软件里太常见了。你会遇到各种怪事:一个U盘插上去,文件管理器能正常打开,但你写脚本枚举USB设备,按网上教程只看bDeviceClass,结果发现一堆设备全对不上号;一个多合一读卡器明明插着SD卡,系统也弹出了盘符,可你用同样判据对比,发现它和U盘的描述符长得完全不一样。

核心原因是,USB设备并不是靠“一个标签”来声明自己是存储设备的,而是靠一组标准描述符逐层告诉系统自己是什么。更麻烦的是,不同设备可能会在不同层级上报自己的类型,甚至同一设备里面同时挂着好几套功能。这篇笔记写给两类人:一类是写应用层工具、需要准确识别插到机器上的U盘、移动硬盘、读卡器的开发者;另一类是写驱动或固件、需要理解USB存储类设备在枚举阶段到底怎么被发现的人。

  1. 先搞清楚USB设备是怎么“自报家门”的

1.1 设备描述符那一层只说了一半真话

USB设备在插入后,主机会发起枚举流程,设备会依次返回多组描述符。最顶层的是设备描述符,里面有两个关键字段:bDeviceClass、bDeviceSubClass、bDeviceProtocol。很多新手按教程去读设备描述符,发现我的U盘bDeviceClass等于0x08,就以为只要判断这个字段就行了。

实际上,大把U盘的设备描述符里bDeviceClass是0x00。0x00的含义是“设备的功能类型由各接口自己去声明”,也就是说主控芯片在生产固件时没有在设备级上报“我是大容量存储”,它把这个责任下沉到了接口描述符。你只看设备描述符,就会漏掉一大票真实U盘。

反过来,有些复合设备会在设备描述符里写0xEF,表示“多功能混合设备”,比如同时带读卡器、蓝牙、音频的USB设备。还有一类写0xFF,表示“厂商自定义”,常见于一些老式主控或者需要专用驱动的设备。这三个值都跟“是不是存储设备”没有直接关系,真正的答案藏在接口描述符。

正确理解是:USB规范允许设备在两级上报类型,设备级和接口级。对于现代U盘、移动硬盘、读卡器,绝大部分情况下起决定作用的是接口级。所以判断逻辑的第一步,永远是遍历配置描述符里的所有接口,而不是只盯设备描述符。

1.2 Mass Storage Class 的标准长相

当一个USB接口的bInterfaceClass等于0x08时,它就是USB Mass Storage Class,也就是USB大容量存储类设备。这个类下面还分了子类bInterfaceSubClass,用来定义命令集:

子类值命令集常见用途
0x01RBC闪存盘、移动硬盘、读卡器
0x02SFF-8020i / MMC-2CD-ROM、DVD-ROM
0x03QIC-157磁带机
0x04UFU软盘
0x05SFF-8070i部分光驱兼容模式
0x06SCSI transparent通过SCSI标准命令访问

再往下还有bInterfaceProtocol,最常见的是0x50,对应Bulk-Only Transport,也就是BOT协议,绝大多数U盘走的都是这个。0x62是UAS协议,也就是USB Attached SCSI,新一代移动固态硬盘常用,速度更快。判断的时候除了看0x08,最好把协议一起读出来,因为这决定了后续访问存储介质时用哪一套传输层。

这里给出一个经常被忽略的点:USB大容量存储类设备,在系统里最终映射为SCSI设备,然后再映射为块设备。所以从内核视角看,一次完整的识别链路是“USB接口描述符bInterfaceClass=0x08 -> usb-storage或uas驱动绑定 -> SCSI设备注册 -> 块设备生成”。任何一个环节断了,都不算真正可用的存储设备。

  1. Linux下判定:从一条命令到一段脚本

2.1 先用lsusb和sysfs直接把class读出来

Linux下最快的方法是用lsusb -t,它会以树状形式打印USB拓扑,并在接口后面标注Class:

lsusb -t /: Bus 01.Port 1: Dev 1, Class=root_hub ... |__ Port 2: Dev 3, If 0, Class=Mass Storage, Driver=usb-storage, 5000M

看到Class=Mass Storage,同时Driver=usb-storage或uas,基本可以确认是存储设备。但这一步只适合人工排查,写脚本需要走sysfs。

sysfs里每个USB接口都对应一个目录,命名格式是总线地址:配置号.接口号,比如1-1:1.0。每个接口目录下面有bInterfaceClass、bInterfaceSubClass、bInterfaceProtocol三个文件,直接读它们就行:

cat /sys/bus/usb/devices/1-1:1.0/bInterfaceClass 08

如果想一条命令扫完所有接口,可以这样:

for d in /sys/bus/usb/devices/*:*/; do c=$(cat "$d/bInterfaceClass" 2>/dev/null) if [ "$c" = "08" ]; then echo "$d is USB Mass Storage" fi done

路径里的*:*是匹配包含冒号的接口目录,要点是不要漏掉同一个物理设备下的多个接口。

2.2 用一段Python脚本做批量判断

命令行适合临时用,真要集成到工具里,我建议用Python直接读sysfs。下面这段脚本会遍历所有USB接口,把MSC接口的父设备、VID、PID和协议一起打出来:

import os import glob def is_storage_interface(intf_path): def read_val(name): try: with open(os.path.join(intf_path, name)) as f: return f.read().strip() except OSError: return '' return read_val('bInterfaceClass') == '08' def usb_device_info(intf_path): # 接口路径类似 /sys/bus/usb/devices/1-1:1.0 # 去掉冒号后面的接口段,得到设备目录 dev_path = intf_path.split(':')[0] vid = pid = '' for name in ('idVendor', 'idProduct'): try: with open(os.path.join(dev_path, name)) as f: val = f.read().strip() except OSError: val = '' if name == 'idVendor': vid = val else: pid = val return vid, pid for intf in sorted(glob.glob('/sys/bus/usb/devices/*:*')): if not os.path.isdir(intf): continue if is_storage_interface(intf): vid, pid = usb_device_info(intf) print(f'{intf} VID={vid} PID={pid}')

注意,接口路径里的1-1:1.0,冒号前半段是“设备路径”,冒号后半段是“配置.接口编号”。上面脚本直接对它做了字符串分割,可读性一般,但胜在不用引入额外依赖。

更稳妥的做法是结合内核已经生成的块设备信息。Linux在USB存储驱动绑定成功后,会产生类似/sys/class/block/sda这样的目录。判断一个USB接口是否真的有介质,可以看它下面有没有对应的SCSI磁盘设备,也可以直接查块设备:

lsblk -d -o NAME,TRAN,SIZE,MODEL

TRAN列如果是usb,说明这个块设备来自USB总线;如果TRAN为空,可能是SATA或NVMe,就不是USB存储。

2.3 用udev规则在插入瞬间识别存储设备

如果你需要在U盘插入那一刻触发脚本,正确姿势是写udev规则,而不是定时轮询。在/etc/udev/rules.d/下新建一个规则文件,比如99-usb-storage.rules:

ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb", RUN+="/usr/local/bin/usb-storage-handler.sh"

这里的关键是SUBSYSTEM表示当前事件的子系统是block,SUBSYSTEMS表示父设备链里存在usb。换句话说,只有当内核把USB存储设备注册成块设备时,这条规则才触发。相比直接在USB接口事件上判断,这个写法已经把“能不能当作块设备使用”这个条件带进去了,误报率低很多。

需要注意:规则里不要加DRIVER=="usb-storage"这种条件,因为UAS设备绑定的驱动是uas,你只匹配usb-storage会漏掉移动固态硬盘。也不要依赖ENV{ID_FS_TYPE}判断,因为设备可能没有分区表,但依然是存储设备。

  1. Windows和跨平台场景又该怎么做

3.1 Windows下最快的确认方式

Windows上如果只是人工确认,打开设备管理器,展开“磁盘驱动器”,看到厂商和型号就知道是不是USB存储。但写程序判断就需要查设备实例ID。

标准USB大容量存储设备的实例ID通常是USBSTOR\DISK&VEN_...&PROD_...,而一个还没被识别为存储设备的普通USB设备是USB\VID_xxxx&PID_xxxx\...。所以最省事的判断方法是:用枚举函数拿到PNP设备ID,看前缀是不是USBSTOR,或者设备类是不是DiskDrive。

PowerShell一行就能做到:

Get-PnpDevice -PresentOnly | Where-Object { $_.InstanceId -like 'USBSTOR*' }

如果要看是不是USB总线上的磁盘,可以查:

Get-Disk | Where-Object BusType -eq 'USB'

老系统没有Get-Disk时,用WMI:

Get-CimInstance Win32_DiskDrive | Where-Object { $_.InterfaceType -like 'USB*' }

需要说明一下,这类API拿到的已经是操作系统USB存储驱动栈处理之后的结果,所以它们不会回答“底层接口描述符是否等于0x08”,而是直接告诉你“系统把不把它当磁盘用”。站在应用层角度,这种判断其实更符合需求。

如果想精确到接口层面,就得用SetupAPI那套接口,核心路径是SetupDiGetClassDevs、SetupDiEnumDeviceInterfaces、SetupDiGetDeviceInterfaceDetail。对于USB存储,可以按存储设备接口GUID枚举,也可以先把USB设备全部枚举出来,再去查它的子设备里是否包含磁盘类设备。这条路比较底层,代码量不小,除非要专门做设备管控,否则不建议一上来就用。

3.2 libusb遍历接口的跨平台实现

跨平台工具经常用libusb。它不依赖操作系统对设备的分类结果,而是直接做USB描述符解析。核心流程是:拿设备列表,逐个读设备描述符,再读当前激活配置的接口描述符,检查每个接口的bInterfaceClass。

libusb_device **list; ssize_t cnt = libusb_get_device_list(ctx, &list); for (ssize_t i = 0; i < cnt; i++) { struct libusb_device_descriptor desc; libusb_get_device_descriptor(list[i], &desc); struct libusb_config_descriptor *cfg = NULL; if (libusb_get_active_config_descriptor(list[i], &cfg) != 0) continue; for (int j = 0; j < cfg->bNumInterfaces; j++) { const struct libusb_interface *iface = &cfg->interface[j]; if (iface->num_altsetting > 0 && iface->altsetting[0].bInterfaceClass == 0x08) { printf("0x%04x:0x%04x is storage\n", desc.idVendor, desc.idProduct); } } libusb_free_config_descriptor(cfg); }

这里面有个细节很多人踩过坑:libusb_get_device_descriptor返回的是设备描述符,字段里同样有bDeviceClass,但你不能光看它。我见过有人只判断设备描述符,结果自己的U盘因为bDeviceClass是0x00被漏掉,折腾一整天。正确做法是遍历配置描述符里的接口数组。

同时还要注意多配置设备。libusb_get_active_config_descriptor拿到的才是设备当前激活的配置,如果用libusb_get_config_descriptor再指定配置编号,你得自己先确认设备用的是哪个配置。大多数U盘只有一个配置,但读卡器、复合设备常有多个配置,稳妥起见永远用active版本。

3.3 为什么不能只靠VID和PID

有相当多的人图省事,维护一张“已知U盘主控VID/PID清单”,然后靠匹配VID/PID来判断。这条路线我强烈不建议。

原因很简单:同一个主控芯片,既可能做成U盘,也可能做成读卡器,还可能做成带存储功能的网卡;同一个VID/PID在不同批次固件下,可能一个上报MSC接口,另一个上报厂商自定义接口;还有不少山寨主控直接克隆大厂VID/PID。拿清单去猜设备类型,本质上是在猜,不是判断。描述符才是USB规范赋予设备的自述,系统自己也靠它工作,所以判断依据必须落到描述符和内核驱动行为上。

  1. 最容易误判的边界情况与处理思路

4.1 复合设备:必须遍历全部接口

很多设备不是单一功能。比如一个USB键盘侧边带读卡器,它的配置里会有两个接口,一个bInterfaceClass是0x03(HID),另一个是0x08(MSC)。再比如移动硬盘盒,除了主存储接口,还有一个UAS接口备用,或者一个厂商调试接口。

如果你只检查第一个接口,或者检查到第一个非存储接口就跳过整个设备,就会漏判。正确逻辑是:只要设备任意一个接口的bInterfaceClass等于0x08,就认为它是USB存储设备;如果还要做更细的控制,再记录具体是哪些接口。

复合设备还有一种情况是设备描述符级别用bDeviceClass=0xEF、bDeviceSubClass=0x02、bDeviceProtocol=0x01,表示接口关联描述符(IAD),说明多个接口被捆绑成一个逻辑功能。即便如此,最后还是得回到接口描述符去确认里面有没有MSC接口。

4.2 能存文件但不是MSC的设备

手机通过USB连接电脑,通常会弹出一个“便携设备”,你可以在里面拷贝文件,但它不是USB Mass Storage设备。手机走的是MTP协议,接口描述符常见的是bInterfaceClass=0x06(Image类),配合PIMA 15740协议和MTP扩展。内核不会把MTP设备注册为块设备,它由应用层的MTP库访问,所以用上一节方法判断,它会直接被排除。

类似的还有基于RNDIS、NCM的USB网卡,它们传输文件靠网络协议,永远不是MSC。还有一部分老式MP3、功能机走的是厂商自定义协议,需要专用驱动才能导出文件。所以在需求层面要区分清楚:你是想判断“这个USB设备在系统里是不是块设备/磁盘”,还是想判断“我能不能通过它存取文件”。后者范围更大,不是单纯描述符能回答的。

4.3 判断“有没有介质”比判断“是存储类”更深一层

就算接口class是0x08,读卡器不一定插了卡,光驱不一定有光盘。这种情况下接口确实是存储类接口,但你访问不到任何介质。

要判断有没有介质,Linux上有几个办法。最简单的是看块设备size:/sys/class/block/sdb/size如果等于0,说明介质不可用。也可以发SCSI命令INQUIRY和READ CAPACITY,但那样工程量大不少。应用层用lsblk看SIZE列也可以,空的读卡器在带-d的情况下通常看不到对应磁盘,或者看到size是0。

Windows下则看Get-Disk是否列出对应磁盘,以及Size是否大于0。这种情况很容易被测试人员当bug报,尤其是读卡器类设备,一定要把“接口存储类”和“介质存在”分开做两层判断。

4.4 厂商自定义接口的老设备

还有一类设备,bInterfaceClass=0xFF,也就是厂商自定义。常见于早期U盘主控和某些加密U盘,它们不能用标准BOT协议访问,需要装专用驱动。从USB规范角度看,它没有声明自己是MSC,但实际功能就是存储。

这类设备靠通用规则判断不出来。如果业务必须覆盖它们,只能维护厂商清单,或者用驱动加载后的行为来判断。这属于特例,不能作为通用方案。我在实际需求里通常会先按标准描述符判断,再在日志里把0xFF接口设备的信息打印出来,由上层决定是否走专用驱动。

  1. 常见问题与排查速查表

5.1 典型场景速查表

设备现象接口class系统是否当磁盘用正确判断方式
普通U盘0x08是接口class==0x08,结合块设备确认
USB移动固态硬盘0x08是协议可能是0x62,看size
多合一读卡器空槽0x08看不到磁盘接口class是存储类,但介质size=0
手机MTP0x06/0x0E组合否检查是否存在MSC接口,没有则不是
带读卡器的键盘0x03 + 0x08是遍历所有接口,不能只看第一个
厂商自定义加密U盘0xFF取决于驱动只能靠驱动行为或厂商清单
USB网卡0x02/0xE0否没有0x08接口就不是存储设备

这张表建议直接贴在项目文档里,排查问题的时候比翻代码快得多。

5.2 排查时容易忽略的细节

第一,检查接口class时,必须在当前激活配置下枚举。如果设备是多配置设备,而你读了非激活配置,可能看到一套完全不同的接口组合,得出错误结论。

第二,注意权限问题。libusb在Linux上需要root权限或者配置udev权限规则,否则打不开设备,返回的枚举结果也拿不完整。在Windows上则需要正确的驱动,WinUSB、libusbK还是系统自带驱动,会影响你能访问的描述符范围。

第三,驱动绑定情况很重要。一个接口class是0x08的USB设备,如果usb-storage或uas驱动没有成功绑定,可能是因为设备固件异常、线材问题,或者系统里驱动被禁用。这时候即使描述符正确,设备也无法作为存储设备使用。用dmesg看内核日志,能快速定位是哪一层失败了。

第四,很多工具的“USB设备识别”是热插拔场景,别只做一次性枚举。要监听NETLINK_KOBJECT_UEVENT或者使用libudev的监控接口,在设备插入时重新判断,在拔出时清理缓存。写死了枚举结果不处理热插拔,实际使用中会积累一堆幽灵设备。

第五,双LUN读卡器也要注意。它可能在SCSI层暴露多个LUN,比如一个SD卡槽一个CF卡槽。在USB层看只有一个接口,但在块设备层会出现多个设备。判断逻辑不能假设“一个USB存储设备 = 一个磁盘”。

我个人调试这类问题时的习惯是,先问自己一个问题:我要判断的是接口层类型,还是系统层表现?接口层类型用描述符,系统层表现用块设备和驱动信息。大多数需求实际要的是后者,只不过描述符是最早能拿到的信号。所以最稳的组合拳是:先遍历接口描述符拿到候选设备,再通过sysfs或系统API确认它真的变成了可用的磁盘,两层都过了,才能放心往下走。

把这条链路理清楚之后,再遇到那些奇奇怪怪的USB设备,基本一眼就能判断出来该不该处理、怎么处理。

相关新闻

OpenClaw 云服务器一键部署指南:5分钟内跑通 AI 代理

OpenClaw 云服务器一键部署指南:5分钟内跑通 AI 代理

不知道你有没有过这种经历&#xff1a;想试一个 AI 自动化工具&#xff0c;先装环境&#xff0c;再配依赖&#xff0c;最后卡在模型接口上&#xff0c;折腾一下午连控制台页面都没见到。所以我最近几乎把所有需要长时间运行的任务都搬到云服务器上做&#xff0c;像 OpenClaw 这…

2026/10/20 5:35:11 阅读更多 →
从听到用:播客下载、转写与摘要的AI知识管理指南

从听到用:播客下载、转写与摘要的AI知识管理指南

我第一次意识到播客这个形态适合用来追踪 AI 领域&#xff0c;是在某次通勤路上。当时我刚结束一个项目的复盘&#xff0c;正好听到一档节目的某期内容&#xff0c;讲的是多模态模型如何改变内容审核的工作流。那一期的观点并不算深&#xff0c;但胜在信息密度很高&#xff0c;…

2026/10/20 5:34:11 阅读更多 →
云端AI成本高企?私有化部署实战指南与成本测算

云端AI成本高企?私有化部署实战指南与成本测算

1. 先算一笔账&#xff1a;云端 AI 的隐性成本到底藏在哪很多人第一次接触 AI 能力&#xff0c;都是从云端 API 开始的。注册一个账号&#xff0c;拿一个密钥&#xff0c;几行代码就能调用大模型&#xff0c;按 token 计费&#xff0c;用多少付多少&#xff0c;听起来确实省心。…

2026/10/20 5:34:11 阅读更多 →

最新新闻

HTTP POST表单提交全解析:Content-Type、编码格式与实战避坑指南

HTTP POST表单提交全解析:Content-Type、编码格式与实战避坑指南

1. 从一个被忽略的细节说起&#xff1a;为什么表单提交远不止填个action很多人第一次接触Web开发&#xff0c;接触到的第一个"能跑起来"的功能&#xff0c;大概率就是一个HTML表单。写一个<form>标签&#xff0c;配上action和method"post"&#xff0…

2026/10/20 6:25:32 阅读更多 →
自动驾驶多模态数据生成:统一传感器输出的关键技术与实践

自动驾驶多模态数据生成:统一传感器输出的关键技术与实践

自动驾驶算法做到后面&#xff0c;真正卡脖子的往往不是模型结构&#xff0c;而是数据。尤其当你同时要喂摄像头、激光雷达、毫米波雷达这几个完全不同的传感器时&#xff0c;数据稀缺和模态不一致会被放大成一个系统工程问题。OmniGen 这个名字听起来很高端&#xff0c;去掉包…

2026/10/20 6:25:32 阅读更多 →
三层网络架构冗余配置实战:VRRP、浮动路由与链路聚合详解

三层网络架构冗余配置实战:VRRP、浮动路由与链路聚合详解

前阵子搭了一套三层结构的网络实验环境&#xff0c;核心两台、汇聚两台、接入一台&#xff0c;实验目标很明确&#xff1a;把三层架构里的各路冗余手段都配上&#xff0c;然后人为制造故障&#xff0c;看流量到底能不能自己绕过去。做完最大的感受是——冗余两个字说起来容易&a…

2026/10/20 6:25:32 阅读更多 →
最新论文追踪指南:平台选择、检索技巧与自动订阅全攻略

最新论文追踪指南:平台选择、检索技巧与自动订阅全攻略

想第一时间看到领域里刚出炉的论文&#xff0c;最怕的不是搜不到&#xff0c;而是根本不知道该去哪个平台搜、用什么关键词、按什么排序。组会汇报前临时抱佛脚、开题时需要确认自己做的方向有没有人抢先发表、审稿时想查一查某篇预印本到底有没有正式见刊——这些场景我都经历…

2026/10/20 6:25:32 阅读更多 →
Web服务器Nginx与集群架构——Java开源litemall小商城项目应用实践

Web服务器Nginx与集群架构——Java开源litemall小商城项目应用实践

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

2026/10/20 6:25:32 阅读更多 →
AI大模型自动化测试实战:全流程智能测试设计与落地

AI大模型自动化测试实战:全流程智能测试设计与落地

我在一线做测试自动化和质量保障已经快十年&#xff0c;说实话&#xff0c;前八年大部分时间都花在写脚本、调框架、跟环境和用例维护作斗争上。最近这两年&#xff0c;AI大模型自动化这个方向确实改变了我的工作节奏。之前接手某个跨平台系统&#xff0c;每个版本回归要花上两…

2026/10/20 6:24:32 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →