Delphi 10.2直接驱动Android摄像头:接管预览帧与JPEG回调

简介:面向 Delphi 10.2 开发者的 Android 摄像头调用示例工程,基于 FireMonkey 框架演示安卓设备上的常见相机功能,涵盖权限声明、实时预览、拍照录像、前后摄像头切换、对焦变焦及图片数据转换等场景,适合希望快速集成相机功能的应用项目参考。压缩包共 92 个文件,除了 pas 源码、fmx 界面、AndroidManifest 模板、dproj 工程配置外,还包含可直接安装的 apk、9 张截图、5 个 so 动态库以及历史修改版本,整体约 45.78 MB,目录按类型归档,方便按需提取。已有 1206 人学习下载,内容对刚接触 Delphi 安卓原生组件开发的中级程序员比较友好。通过可运行工程,将 TAndroidCamera 组件的属性、事件和控制方法落实到实际代码中,并附上排错思路与部署配置,能帮助理解相机权限、预览绑定、图像格式转换等关键环节,大幅节省环境搭建和问题排查时间。

1. Delphi 10.2 直接驱动 Android 摄像头:不靠 Intent,自己接管预览帧

在 Delphi 10.2 的 Android 工程里直接调摄像头,大多数人第一步就选错了——第一反应是拖一个 TakePhotoFromCameraAction 进去,但那只是把请求丢给系统相机 App,你自己拿不到预览帧,更做不了实时帧分析。这个小项目完全走另一条路:用 Androidapi.JNI.Hardware 的封装直接操作 Camera 硬件,预览、对焦、拍照回调、JPEG 落盘全部自己接管,连取景框都用 SurfaceView 自己画。适合两类人:一类是只想「拍照并返回路径、但不被系统相机界面绑架」的 App 业务;另一类是要做扫码、OCR 框选、实时特征检测、但不打算用原生 Java 重写界面的 Delphi 开发者。按下文把工程跑一遍,半小时内能看到摄像头预览画面出现在你自己画的容器里。

2. 项目定位与技术选型:为什么绕开系统相机的 Intent

2.1 这个 Demo 解决什么问题

很多 Delphi 开发者做 Android 拍照功能时,被官方文档里的 TakePhotoFromCameraAction 带偏了。那个 Action 本质是一次跨进程 Intent 调用,系统相机拍照后把图片 Uri 返回给你。好处是代码少,坏处是:你拿不到预览帧、控制不了闪光灯和对焦策略、界面风格不可控,在部分 ROM 上还会出现拍照后返回慢、图片被压缩的问题。

这个项目封装的是一套直接面向 Camera 服务的调用链。它先把 JNI 层的 Camera 对象拿到手,再通过 SurfaceHolder 把预览画面渲染到你自己指定的 View 上,最后通过 PictureCallback 拿回原始 JPEG 字节流。也就是说,从「打开硬件」到「拿到照片字节」中间的每一帧都经过你的代码,没有被系统 App 插一脚。对于做扫码、OCR、车道线识别这类需要逐帧分析的业务,这才是正确姿势。

2.2 用到的 Delphi 单元与关键组件

工程核心依赖 4 个 Delphi 系统单元,都在 10.2 自带的 SDK 封装里:

单元作用
Androidapi.JNI.Hardware提供 JCamera、JCamera_Params、JCamera_PictureCallback 等相机硬件接口
Androidapi.JNI.GraphicsContentViewText提供 JSurfaceView、JSurfaceHolder 等界面组件接口
Androidapi.JNI.Os / Androidapi.JNI.App提供动态权限申请所需的 TJManifest、Activity 接口
Androidapi.Helpers托管 Activity、Form 与 Native View 之间的转换,以及 TPermissionRequestResult 消息

另外自己写了一个 uCameraHelper.pas,把打开、设参、拍照、释放四个动作收敛成一个类。这样主窗体只负责 UI 和事件响应,不直接碰 JNI 细节。改造时如果想换成 Camera2 API,只需要替换这个类,主窗体逻辑基本不动。

2.3 整体调用链路

摄像头功能从点击按钮到拿到 JPEG,大致走这样一条链路:

  1. 用户点击「打开预览」,先走运行时权限申请;
  2. 权限通过后,Camera.open(0) 拿到后置摄像头句柄;
  3. SurfaceHolder.addCallback 触发 surfaceCreated,此时把 Camera 与 SurfaceHolder 关联并 startPreview;
  4. 点击「拍照」,takePicture 传入三个 callback,其中 JPEG 回调触发后拿到字节数组;
  5. 字节数组写入应用沙盒目录,同时 updatePreview 恢复预览;
  6. 离开页面时在 surfaceDestroyed 或 Form 的 onPause 里 release 摄像头。

其中第 3 步是最容易翻车的地方——很多人直接把 setPreviewDisplay 写在按钮点击里,但那时 Surface 还没创建好,结果是黑屏。后面避坑章节会专门说。

3. 工程搭建与权限配置:Android 6 动态权限是第一道坎

3.1 从空工程到摄像头权限清单

先按常规方式建一个 Delphi 10.2 的 Android 空工程,然后在 Project Options 的 Permissions 页签里勾选 Camera,这一步会同步修改 AndroidManifest.template.xml。如果你用的是自行管理的 manifest,也可以手动加:

<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" android:required="true" />

uses-feature 表示该应用强依赖摄像头硬件,Google Play 会据此过滤无摄像头设备。注意:在 10.2 里,如果你只勾选了界面上的 Permission 而没有检查 AndroidManifest.template.xml 里是否真的注入了 CAMERA 权限,就可能在旧设备上遇到 SecurityException。我习惯勾选后打开 manifest 文件确认一遍,避免玄学问题。

3.2 运行时权限申请与结果处理

Android 6 及以上,只写 manifest 还不够,必须在代码里动态申请权限。10.2 没有像高版本那样的 PermissionsService 快捷封装,但可以直接操作 Activity:

procedure TMainForm.RequestCameraPermission; var LPermissions: TJavaObjectArray<JString>; begin LPermissions := TJavaObjectArray<JString>.Create(1); LPermissions.Items[0] := TJManifest.JavaClass.permission.CAMERA; TAndroidHelper.Activity.requestPermissions(LPermissions, 2001); end;

这段代码把 CAMERA 权限字符串包进 Java String 数组,以 2001 作为请求码发给系统。系统弹窗后结果会异步返回,需要在主 Activity 的 onRequestPermissionsResult 通知里接住。10.2 里可通过 TMessageManager 订阅 TPermissionRequestResult 消息:

TMessageManager.DefaultManager.SubscribeToMessage( TMessage<TPermissionRequestResult>, procedure(const Sender: TObject; const M: TMessage) var LPerm: TPermissionRequestResult; begin if M is TMessage<TPermissionRequestResult> then begin LPerm := TMessage<TPermissionRequestResult>(M).Value; if LPerm.RequestCode = 2001 then begin if LPerm.GrantResults[0] = TJPackageManager.JavaClass.PERMISSION_GRANTED then OpenCameraAndStartPreview else ShowMessage('权限被拒绝,无法打开摄像头'); end; end; end);

这里有个容易忽略的点:GrantResults 是 Java int 数组,比较时要和 TJPackageManager.PERMISSION_GRANTED 常量比,不能自己想当然用 0。另外消息订阅最好在 FormCreate 里做,尽量不要在一个局部过程里 subscribe 后马上调用,否则回调还没注册成功。

3.3 预览容器:在 FMX 界面上挂一个 SurfaceView

Delphi 的 TLayout 本身不是原生 View,直接把 Camera 的预览输出指向它是不行的。常见做法是用 JSurfaceView 创建原生视图,再通过 addContentView 加到 Activity 的顶层:

FSurfaceView := TJSurfaceView.Create(TAndroidHelper.Activity); FSurfaceHolder := FSurfaceView.getHolder; FSurfaceHolder.addCallback(Self); FSurfaceHolder.setType(SurfaceType_CAMERA); TAndroidHelper.Activity.addContentView( FSurfaceView, TJViewGroup_LayoutParams.JavaClass.init( TJViewGroup_LayoutParams.JavaClass.MATCH_PARENT, TJViewGroup_LayoutParams.JavaClass.MATCH_PARENT));

setType 在 Android 3.0 之后已经不再建议启用,但老设备上不设置 SurfaceType_CAMERA 可能在预览时报异常,写上这一行可以兼容性兜底。addContentView 那两行参数解释:MATCH_PARENT 让 SurfaceView 铺满整个 Activity 根布局,如果你想让预览画在某个 Panel 区域,可以把这里的参数改成宽高像素值,或者把 SurfaceView 包装进 FrameLayout 再控制位置。

提示:addContentView 添加的是原生 View,它永远盖在 FMX 控件之上。如果需求是「上下留按钮、中间留预览区」,建议在中间留白区域对应的 Native 坐标里,用 setX/setY + setLayoutParams 控制 SurfaceView 的位置,而不是直接用 MATCH_PARENT 全屏。

4. 核心模块拆解:从 Camera.open 到 JPEG 落盘的完整链路

4.1 打开摄像头:前置还是后置

Camera.open 的参数是摄像头 ID。0 是后置,1 是前置。部分国产设备上 ID 可能超过 1,所以更稳妥的做法是先拿 Camera.getNumberOfCameras 再遍历查找:

function TCameraHelper.OpenCamera(AUseFront: Boolean): Boolean; var LCount: Integer; LInfo: JCamera_CameraInfo; I: Integer; begin Result := False; LCount := 0; try LCount := JCamera::JCamera._Creator.getNumberOfCameras; except Exit; end; for I := 0 to LCount - 1 do begin LInfo := TJCamera_CameraInfo.JavaClass.init; JCamera::JCamera._Creator.getCameraInfo(I, LInfo); if (AUseFront and (LInfo.facing = CameraInfo_CAMERA_FACING_FRONT)) or ((not AUseFront) and (LInfo.facing = CameraInfo_CAMERA_FACING_BACK)) then begin FCamera := JCamera::JCamera._Creator.open(I); Result := Assigned(FCamera); Break; end; end; end;

CameraInfo_CAMERA_FACING_FRONT 是硬件层定义的方向常量,取前面加 TJ 前缀的类可以拿到可比较的值。打开后可以顺手读一下分辨率支持列表,后面设参数时就不会设到不支持的尺寸。如果 open 返回空,大概率是摄像头被别的进程占用了,这种情况重试两三次仍是空,就应该提示用户。

4.2 设置预览参数:分辨率与对焦模式

拿到 FCamera 后先 getParameters,改完再 setParameters。直接改 Camera 属性是无效的,必须走参数对象:

var LParams: JCamera_Params; begin LParams := FCamera.getParameters; LParams.setPreviewSize(1280, 720); LParams.setPictureSize(1920, 1080); LParams.setFocusMode(StringToJString('continuous-picture')); LParams.setJpegQuality(90); FCamera.setParameters(LParams); end;

setPreviewSize 决定预览帧的宽高,setPictureSize 决定最终照片分辨率,两者独立。不少开发者只设置了拍照分辨率,预览还是默认的 640x480,看起来非常模糊。setJpegQuality 是 JPEG 压缩质量,范围 1 到 100,90 是速度与画质的折衷点。如果做 OCR,建议降到 80,能明显加快回调速度,对识别率影响可以忽略。对焦模式里,'continuous-picture' 是最常用的拍照场景模式;做扫码可以改用 'continuous-video',帧率会更平滑。

4.3 预览回调:把 Camera 输出绑定到 SurfaceHolder

预览能显示的前提是 Surface 已经准备好。所以回调方法必须实现 JSurfaceHolder_Callback 的三个方法:

procedure TMainForm.surfaceCreated(holder: JSurfaceHolder); cdecl; begin if Assigned(FCamera) then begin FCamera.setPreviewDisplay(holder); FCamera.startPreview; end; end; procedure TMainForm.surfaceChanged(holder: JSurfaceHolder; format: Integer; width: Integer; height: Integer); cdecl; begin // 横竖屏切换时 Surface 会重建,这里需要重新启动预览 if Assigned(FCamera) then begin FCamera.stopPreview; FCamera.setPreviewDisplay(holder); FCamera.startPreview; end; end; procedure TMainForm.surfaceDestroyed(holder: JSurfaceHolder); cdecl; begin ReleaseCamera; end;

surfaceCreated 是首个回调,此时 Surface 已经可用。setPreviewDisplay 把 Camera 输出定向到这个 Surface 上,之后 startPreview 才开始出帧。surfaceChanged 在 Surface 尺寸变化或旋转时触发,最稳妥的处理就是停掉预览、重新绑定、再启动。surfaceDestroyed 是和 release 最匹配的位置,在这里释放可以避免 Activity 退出后摄像头仍在工作。

4.4 拍照回调:JPEG 字节从硬件到内存

拍照通过 takePicture 完成,它接收 4 个回调:ShutterCallback、RawCallback、PostViewCallback、JpegPictureCallback。实际使用中后两个通常传 nil,因为大多数场景只需要最终 JPEG:

FCamera.takePicture(nil, nil, nil, Self);

Self 之所以能传进来,是因为主窗体声明时实现了 JCamera_PictureCallback 接口。接口里的方法只有一个:

procedure TMainForm.OnPictureTaken(Data: TJavaArray<Byte>; Camera: JCamera); cdecl; begin if Assigned(Data) and (Data.Length > 0) then SaveJpegToFile(Data) else ShowMessage('拍照失败,未拿到图片数据'); end;

Data 是完整 JPEG 字节流,不是文件路径。这个特性和系统相机 Intent 完全不同:字节流可以让你在落盘前直接做压缩、裁剪、灰度化,无需先从文件读一遍。回调执行在 camera 的 binder 线程上,不要在回调里直接更新 UI,把字节流转到主线程再弹提示或刷新界面。

4.5 保存 JPEG 与释放摄像头

拿到字节后最直接的做法是写到应用沙盒目录,避免申请存储权限:

procedure TMainForm.SaveJpegToFile(const AData: TJavaArray<Byte>); var LPath: string; LStream: TFileStream; begin LPath := TPath.Combine(TPath.GetDocumentsPath, Format('camera_%s.jpg', [FormatDateTime('yyyymmddhhnnsszzz', Now)])); LStream := TFileStream.Create(LPath, fmCreate); try LStream.Write(AData.ToBytes[0], AData.Length); finally LStream.Free; end; end;

写应用私有目录不需要 READ/WRITE_EXTERNAL_STORAGE 权限,这是很多项目的隐藏坑:如果你随手把图片写到公共 DCIM 目录,Android 6+ 就必须动态申请存储权限,否则 FileNotFoundException 或者 SecurityException 随机出现。文件命名的时间戳精确到毫秒,可以防止连续拍照时覆盖。

释放摄像头时要注意顺序:先 stopPreview 再 release,release 后必须把对象置 nil,否则下一次 open 会直接抛 RuntimeException:

procedure TMainForm.ReleaseCamera; begin if Assigned(FCamera) then begin FCamera.stopPreview; FCamera.release; FCamera := nil; end; end;

release 是一个耗时的硬件操作,在 Android 主线程里调用虽然不报错,但会有几十到上百毫秒的卡顿。如果页面切后台比较频繁,可以考虑把 release 放到一个延迟任务里执行,但要先 stopPreview 避免新预览帧继续往一个已释放的 Camera 上送。

5. 避坑记录:黑屏、照片旋转、权限二次弹窗、资源占用

5.1 预览黑屏,Surface 还没好你就 startPreview 了

现象:点击按钮后 Camera 打开了,屏幕上却一片黑,logcat 里经常出现 startPreview 失败或 setPreviewDisplay failed。 原因:SurfaceView 的 Surface 创建是异步的,按钮点击发生在 surfaceCreated 之前,此时 setPreviewDisplay 找不到可用的 Surface,预览自然出不来。 解决:把 setPreviewDisplay 和 startPreview 全部放进 surfaceCreated 回调里,用回调驱动相机启动,而不是用按钮直接启动。

5.2 拍出来的照片自动旋转 90 度

现象:竖屏应用预览是正的,拍完打开相册发现照片横了。 原因:摄像头传感器默认横向放置,Java 层拿到的 JPEG 不带旋转信息,也没有自动补偿。 解决:在拍照前根据 CameraInfo.orientation 计算旋转角,然后 setDisplayOrientation 修正预览方向;JPEG 落盘时用 Exif 接口写入 orientation 标签,或者直接把 JPEG 字节解码后旋转再编码。一般后置摄像头 orientation 是 90,前置是 270,具体要以设备实测为准。

5.3 用户拒绝后第二次申请权限弹窗不出现

现象:第一次点「拒绝」,第二次调 requestPermissions 完全没有反应,功能直接不可用。 原因:系统会把第一次拒绝的请求记住,如果用户勾选了「不再询问」,后续申请直接走拒绝分支,不会再弹窗。 解决:在申请前先判断 shouldShowRequestPermissionRationale,返回 false 且权限未授予时,说明被彻底拒绝,此时引导用户去系统设置页手动打开。设置页可以用 Intent 带 package uri 跳转,这里需要注意申请代码要跑在 UI 线程上。

5.4 退出页面后摄像头被其他应用占用

现象:从页面返回后,再进来自拍,打开前置摄像头报错 Camera open failed。 原因:Form 销毁时没有调用 release,或者 release 被写在一个永远不执行的清理分支里,摄像头硬件一直保持 open 状态。 解决:把 ReleaseCamera 同时挂在 FormDestroy 和 Application 的 onEvent 里处理 APP 切后台的场景。只要摄像头未释放,其他应用打开相机也会失败,用户会以为是自己手机坏了。我的经验是「surfaceDestroyed → 切后台 → 窗体销毁」三个点都调用 release,并保证 release 方法内部做了空指针判断,不重复释放。

6. 二次开发改造思路:把拍照 Demo 改成帧分析引擎

先弄清楚业务需要的是「单张拍照」还是「连续分析」。如果是 OCR 或扫码,重点不在 takePicture,而在预览帧回调。Camera 支持 setPreviewCallbackWithBuffer,把每一次预览帧的 byte 数据回调出来:

FCamera.setPreviewCallbackWithBuffer(FPreviewCallback); // 配合 addCallbackBuffer 循环复用 byte 数组

然后在回调里做灰度转换、二值化,再把结果交给你的识别算法。注意预览格式要设置成 ImageFormat.NV21,这个格式在 Android 相机上支持最广,转灰度最快,Delphi 里对应的是 TJImageFormat.JavaClass.NV21。

如果目标设备都是 Android 7 以上,建议直接升级 Camera2 API。Camera2 在 10.2 里有 Androidapi.JNI.Hardware.Camera2 封装,核心入口是 TJCameraManager.openCamera,支持手动拼接 Session 和反复提交 CaptureRequest。改造时把 uCameraHelper 的接口保持不变,内部实现从 Camera 换成 Camera2,主窗体的调用代码不需要大改。

这个 Demo 我前后在真机上翻过三次车,最典型的就是黑屏和旋转问题。从那以后我每次做 Android 相机功能都会强制走一遍「权限 → Surface → 预览 → 回调 → 释放」的五步链路,确认每一步都有日志或可见反馈,再做下一步。希望帮到你。

本文还有配套的精品资源,点击获取

相关新闻

SSM+Vue在线考试系统毕设实战:从架构到二次开发完整指南

SSM+Vue在线考试系统毕设实战:从架构到二次开发完整指南

简介&#xff1a;一套基于Java的在线考试系统毕业设计资料包&#xff0c;采用SSM框架与Vue开发&#xff0c;适合计算机专业毕业设计、课程设计及Java Web学习者使用。系统按角色分为前台用户与管理员两大模块&#xff0c;用户可进行首页浏览、个人中心管理、考试成绩查询、公告…

2026/10/20 4:20:37 阅读更多 →
光纤通道Zone配置原理与实战避坑指南

光纤通道Zone配置原理与实战避坑指南

1. 光纤交换机Zone配置&#xff1a;不是“划个圈”那么简单很多人第一次接触光纤交换机的Zone配置时&#xff0c;下意识觉得就是“在管理界面里点几下&#xff0c;把几个端口拖进一个组里”&#xff0c;就像给微信群拉人一样简单。我刚接手某高校数据中心存储网络改造项目时也是…

2026/10/20 4:20:37 阅读更多 →
PyQt+图像识别:液化气排气隐患检测毕设项目全解析

PyQt+图像识别:液化气排气隐患检测毕设项目全解析

做毕设选方向的时候&#xff0c;估计不少人都被“选个能做、能讲清楚、还能做出东西”的题目搞得头大。这个PyQt基于图像识别的液化气排气隐患识别项目&#xff0c;就是典型的“深度学习应用型”题&#xff1a;本身不搞什么新理论&#xff0c;但把目标检测、界面开发、工程部署…

2026/10/20 4:20:37 阅读更多 →

最新新闻

K8s持久化卷实战:Ceph纠删码池与RBD CSI完整配置指南

K8s持久化卷实战:Ceph纠删码池与RBD CSI完整配置指南

K8s持久化卷这块&#xff0c;Ceph是老熟人了。但大部分入门教程默认用副本池&#xff0c;等生产跑久了你才会意识到&#xff0c;三个副本吃掉的空间有多惊人。一台4TB的OSD&#xff0c;按3副本、数据均衡算&#xff0c;逻辑可用容量连1.3TB都不到。这时候把眼睛盯上纠删码池&am…

2026/10/20 8:03:22 阅读更多 →
RT-Thread ENV工具入门:从安装到配置驱动开发

RT-Thread ENV工具入门:从安装到配置驱动开发

废话不多说&#xff0c;直接进入正题。很多玩RT-Thread的朋友第一次听说ENV工具时&#xff0c;心里多半是拒绝的&#xff1a;明明Keil/IAR的图形界面用得挺顺手&#xff0c;为什么还要去敲命令行&#xff1f;我最初也这么想&#xff0c;直到手动维护一个带Wi-Fi、文件系统、多种…

2026/10/20 8:03:22 阅读更多 →
AI资讯过载时代的技术主线提炼:从信息筛选到落地行动

AI资讯过载时代的技术主线提炼:从信息筛选到落地行动

每天早上一睁眼&#xff0c;信息流里塞满的全是模型发布、框架更新、应用落地案例&#xff0c;3月28日这天也不例外。我做技术选型和落地评估很多年&#xff0c;看全球AI技术资讯的习惯早就不是“刷标题”了&#xff0c;而是带着几个问题在翻&#xff1a;这条消息解决的是什么场…

2026/10/20 8:03:22 阅读更多 →
Selenium多页面切换实战:窗口句柄机制与踩坑排查指南

Selenium多页面切换实战:窗口句柄机制与踩坑排查指南

刚开始接触Selenium自动化测试的人&#xff0c;十有八九都会在“多页面切换”这件事上栽跟头。我见过太多人写脚本时点开一个新标签页&#xff0c;然后继续用原来的driver去查找元素&#xff0c;结果报了一堆NoSuchElementException&#xff0c;一脸懵地看着浏览器发呆。说穿了…

2026/10/20 8:03:22 阅读更多 →
layui 2.5.6 + ThinkPHP 6.0.2 权限管理后台实战:三层权限模型与避坑指南

layui 2.5.6 + ThinkPHP 6.0.2 权限管理后台实战:三层权限模型与避坑指南

简介&#xff1a;这是一套基于 layui2.5.6 前端组件库与 ThinkPHP6.0.2 后端框架搭建的权限管理后台源码&#xff0c;面向需要快速构建企业级管理系统的 PHP 开发者&#xff0c;也适合初学者理解前后端协同开发流程。资源包共 1098 个文件&#xff0c;约 6.1MB&#xff0c;以 4…

2026/10/20 8:03:22 阅读更多 →
打印数组最大数:从循环遍历到并行与流式处理的完整指南

打印数组最大数:从循环遍历到并行与流式处理的完整指南

别小看“打印数组最大数”这五个字。我见过太多工作三五年的开发者&#xff0c;写这段逻辑时栽在没人提醒的细节上&#xff1a;数组为空怎么办&#xff1f;全是负数怎么办&#xff1f;元素是浮点数带NaN怎么办&#xff1f;数据量到千万级怎么办&#xff1f;这段代码几乎是所有编…

2026/10/20 8:02:22 阅读更多 →

日新闻

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 阅读更多 →