Java实现Markdown转PDF:基于iText7与HTML中间层的完整实战

真正开始做这个需求之前,我先坦白:Markdown转PDF这条路,我前前后后踩了小半个月的坑。

起因是一个文档系统要导出PDF,业务方给了一批Markdown格式的知识库文章,要求生成排版干净、支持中文、能直接分发给客户的PDF文件。我第一反应是找现成工具,但试了一圈,要么是命令行工具部署麻烦,要么是样式控制太弱。后来定了Java后端自己做,技术栈选了ITextPDF,链路是Markdown先转HTML,再用ITextPDF的HTML转PDF能力生成最终文件。

这套流程跑通之后,我发现网上资料很零散,要么只讲Markdown解析,要么只讲IText渲染,很少有人把两段拼起来讲完整。这篇文章我把整个链路拆开讲清楚,包括选型理由、依赖配置、完整代码、样式适配,以及我在实际项目中遇到的几个大坑。适合Java后端开发者、做文档导出或电子书生成功能的小伙伴直接参考。

1. 方案选型:为什么是Markdown转HTML再到PDF的三级跳

1.1 Markdown直接转PDF为什么不靠谱

Markdown本身是轻量级标记语言,设计初衷是给人类阅读和网页渲染用的,不是为PDF排版服务。你可以在IDE里看到漂亮的Markdown预览,但那个渲染效果依赖编辑器的CSS引擎,和PDF的排版引擎完全是两回事。

市面上的确有一些库声称支持Markdown直接转PDF,但它们内部通常做了两件事:要么内置一套写死的样式,要么偷偷调用了系统浏览器打印。前者的问题是样式不可控,你没法定制页边距、页眉页脚、代码块配色;后者的问题是部署环境复杂,服务器上未必有浏览器环境,而且打印出来的PDF尺寸和分页经常不稳定。

更关键的是,ITextPDF这个库本身不解析Markdown。它擅长的是PDF底层操作、元素绘制、以及HTML/CSS渲染。所以你需要在它前面加一层解析器,把Markdown翻译成它认识的语言,也就是HTML。

1.2 选择iText5还是iText7,以及pdfHTML模块

如果你搜过ITextPDF,会看到有iText 5和iText 7两大版本。iText 5是经典老版本,包名是com.itextpdf.text,很多老项目还在用。iText 7是重写后的新架构,包名是com.itextpdf.kernel、com.itextpdf.layout、com.itextpdf.html2pdf,模块划分更清晰。

做HTML转PDF必须用iText 7的pdfHTML模块,这个模块负责接收HTML字符串和CSS样式,解析后映射到iText的layout元素,最终写入PDF。iText 5没有对应的HTML转PDF能力,硬要用的话得自己写标签解析器,工作量巨大,不建议。

同类方案里还有Flying Saucer、wkhtmltopdf、Openhtmltopdf等。Flying Saucer基于Java,但CSS支持停留在老版本,表格和Flex布局经常出问题。wkhtmltopdf要依赖Qt和WebKit,服务器部署费劲。Openhtmltopdf是不错的替代品,但如果你已经在项目里用了iText处理PDF合并、签名等操作,直接用pdfHTML是最省事的,毕竟底层渲染模型统一,调试起来心智负担小。

1.3 整体技术链路与核心依赖

我最终采用的链路是这样的:

Markdown源文件 -> 解析器(commonmark-java或flexmark) -> HTML片段 -> 套用CSS模板 -> 完整HTML字符串 -> ITEXT pdfHTML模块 -> PDF文件

这个链路的核心优势是每一层都可替换。Markdown解析器不喜欢可以换,CSS模板不喜欢可以改,PDF生成逻辑不喜欢可以换成其他HTML转PDF库,不会互相绑架。

依赖方面,我用的Maven坐标如下:

<dependency> <groupId>com.itextpdf</groupId> <artifactId>itext7-core</artifactId> <version>7.2.5</version> <type>pom</type> </dependency> <dependency> <groupId>org.commonmark</groupId> <artifactId>commonmark</artifactId> <version>0.21.0</version> </dependency>

itext7-core是一个聚合依赖,会把kernel、layout、io、pdfhtml等模块一起拉进来,省去手动维护多个版本的麻烦。版本号建议用7.2.x,不要用太老的7.0.x,因为pdfHTML对CSS的支持在后续版本里完善了不少。

2. 详细实操:Markdown解析与HTML中间层生成

2.1 Markdown解析器选型:commonmark-java还是flexmark

Java生态里Markdown解析器有十几种,我用过的有commonmark-java和flexmark。

commonmark-java是CommonMark规范的标准实现,胜在轻量、解析速度快、依赖少。它默认支持标准Markdown语法,标题、列表、引用、代码块、链接这些都没问题。如果需求就是标准Markdown,它最合适。

flexmark是commonmark-java的增强版,扩展了表格、脚注、任务列表、删除线、自动链接等。如果你的Markdown内容来自语雀、飞书或者某些富文本编辑器导出的文档,里面很可能包含表格和任务列表,这时候flexmark更稳。

两种的选择我建议这样判断:先看源文档格式,如果表格是管道符写法,比如| 姓名 | 年龄 |,那就要用flexmark,或者commonmark-java加上表格扩展插件。如果只是普通文章,没有特殊语法,commonmark-java足够。

我项目里的Markdown源文件大量使用表格和代码块,所以最终选了flexmark。但为了思路清晰,下面示例先用commonmark-java,逻辑更简单,你们换解析器时只动一个类就行。

2.2 让解析结果变成规范HTML

Markdown解析器输出的HTML片段通常是这样的:

<h1>标题</h1> <p>段落内容</p> <pre><code class="language-java">代码块</code></pre> <table> <thead>...</thead> <tbody>...</tbody> </table>

这段HTML可以直接扔给浏览器,但如果直接扔给pdfHTML,你会发现样式很难看。因为pdfHTML虽然支持CSS,但默认情况下没有你对Markdown加的任何样式,标题就是默认字号,代码块没有背景色,表格没有边框。

所以必须做一步:把解析器输出的HTML片段,拼接进一个完整的HTML模板,模板里用CSS定义整套文档样式。

这里有个关键点:IText的pdfHTML对XHTML的规范性要求比浏览器严格。标签没有闭合、属性值没有加引号、<img>没有自闭合,这些在浏览器里都能忍,pdfHTML却可能直接解析失败或渲染异常。好在CommonMark规范的解析器输出都是标准闭合标签,只要你不手工拼字符串拼出错,一般没这个问题。

2.3 代码示例:Markdown解析并套用模板

下面这段代码是我测试时写的第一版,核心逻辑至今没变:

import org.commonmark.node.Node; import org.commonmark.parser.Parser; import org.commonmark.renderer.html.HtmlRenderer; public class MarkdownToHtmlConverter { public static String toHtml(String markdownText) { Parser parser = Parser.builder().build(); Node document = parser.parse(markdownText); HtmlRenderer renderer = HtmlRenderer.builder().build(); return renderer.render(document); } }

拿到HTML片段后,套用模板:

public static String wrapWithTemplate(String bodyHtml) { String css = """ body { font-family: "SourceHanSansSC", "Noto Sans CJK SC", sans-serif; font-size: 12pt; line-height: 1.8; margin: 2cm; } h1 { font-size: 22pt; color: #1a1a1a; border-bottom: 1.5pt solid #333; padding-bottom: 6pt; } h2 { font-size: 18pt; color: #2c3e50; margin-top: 18pt; } h3 { font-size: 15pt; color: #34495e; } pre { background-color: #f6f8fa; border-radius: 4pt; padding: 10pt; font-family: "JetBrains Mono", "Courier New", monospace; font-size: 10pt; white-space: pre-wrap; } code { font-family: "JetBrains Mono", "Courier New", monospace; background-color: #f6f8fa; } table { border-collapse: collapse; width: 100%; margin: 12pt 0; } th, td { border: 0.75pt solid #bbb; padding: 6pt 10pt; text-align: left; } th { background-color: #f2f2f2; font-weight: bold; } img { max-width: 100%; } """; return "<!DOCTYPE html>\n<html>\n<head>\n<style>" + css + "</style>\n</head>\n<body>\n" + bodyHtml + "\n</body>\n</html>"; }

模板设计有几个注意点。

字号单位建议用pt,不要用px。浏览器里px是屏幕像素,PDF里更适合用pt(磅),12pt接近小四字号,阅读体感合适。

行高line-height用1.8,比浏览器默认的1.2大不少。原因很简单,PDF是打印阅读场景,行距太密在纸面上很难受,尤其是中文内容。

pre代码块的white-space要设成pre-wrap。不设的话,代码行太长会导致内容超出页面宽度被截断,设置了pre-wrap后会自动换行,虽然牺牲了一点代码格式化,但保证了不丢内容。

3. 核心环节:使用ITExtPDF将HTML渲染为PDF

3.1 三步走的转换流程

HTML转PDF最核心的一段代码其实很短,就三步:

import com.itextpdf.html2pdf.ConverterProperties; import com.itextpdf.html2pdf.HtmlConverter; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfWriter; import java.io.FileOutputStream; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; public class HtmlToPdfService { public static void convert(String fullHtml, String outputPath) throws Exception { // 1. 创建PDF写入器 try (FileOutputStream fos = new FileOutputStream(outputPath)) { PdfWriter writer = new PdfWriter(fos); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.setTagged(true); // 开启标签,便于无障碍阅读和元数据 // 2. 配置转换属性 ConverterProperties props = new ConverterProperties(); // 这一步在后面字体章节详细讲 props.setBaseUri("/path/to/resource/root/"); // 3. 执行转换 HtmlConverter.convertToPdf( new ByteArrayInputStream(fullHtml.getBytes(StandardCharsets.UTF_8)), pdfDoc, props ); } } }

这段逻辑很简单:PdfWriter写文件,PdfDocument承载文档,HtmlConverter.convertToPdf把HTML流解析后写入PDF。

有一个隐藏细节是编码。HTML字符串写入流之前必须用UTF-8编码,并且在HTML模板的head标签里加上<meta charset="UTF-8">,否则中文容易出现乱码。上面的代码已经用StandardCharsets.UTF_8指定了。

3.2 中文字体:ITExtPDF最绕不开的坑

新装的iText默认字体是Helvetica,这是一套西文字体,不含中文。如果你不加处理直接转换,PDF里所有中文会变成空白甚至乱码。这是我当时踩的第一个大坑,也是最多人卡住的地方。

正确做法是自定义字体集,通过ConverterProperties里挂一个FontProvider。

import com.itextpdf.io.font.FontProgram; import com.itextpdf.io.font.FontProgramFactory; import com.itextpdf.kernel.font.PdfFontFactory; import com.itextpdf.layout.font.FontProvider; public static ConverterProperties createProperties() throws Exception { FontProvider provider = new FontProvider(); // 方式一:注册系统字体目录 provider.addSystemFonts(); // 方式二:注册单个字体文件(推荐,可控性更强) String fontPath = "/fonts/SourceHanSansSC-Regular.otf"; FontProgram fontProgram = FontProgramFactory.createFont(fontPath); provider.addFont(fontProgram); ConverterProperties props = new ConverterProperties(); props.setFontProvider(provider); return props; }

FontProvider对象建议只初始化一次并复用,不要每次转换都重新加载字体文件,不然性能会很差。

关于字体文件选择,我建议直接在项目里放一套开源字体,比如思源黑体或Noto Sans CJK系列。这套字体内含简体中文、繁体中文、日文、韩文,覆盖了大多数文档场景。字体文件较大,几十MB到一百多MB都有可能,但为了PDF正常显示,这个体积代价可以接受。

注意:font-family里写的字体名要和你注册的字体实际匹配。如果注册的是SourceHanSansSC-Regular.otf,CSS里写font-family: "SourceHanSansSC"或者"思源黑体"都能对上。如果CSS里写的是某个系统没有的字体名,iText会回退到默认字体,中文又变空白。

3.3 分页控制和页眉页脚

HTML在PDF里分页是pdfHTML模块自动处理的,内容超过一页会自然分到下一页。但有些时候你想要更精确的控制,比如某个表格必须整块展示,不想跨页断开。

CSS里有几个分页属性pdfHTML是支持的:

  • page-break-before: always:强制元素前分页
  • page-break-after: always:强制元素后分页
  • page-break-inside: avoid:尽量避免元素内部跨页

我给标题和表格都加了page-break-inside: avoid,效果是如果表格在当前页剩余空间放不下,会整体挪到下一页,而不是从中间断开。这个体验对阅读PDF来说很重要。

页眉页脚用CSS做不到,需要写iText的页面事件处理器。核心思路是监听PdfDocumentEvent.END_PAGE,在每页结束绘制时往页脚位置画页码。

import com.itextpdf.kernel.events.PdfDocumentEvent; import com.itextpdf.kernel.events.Event; import com.itextpdf.kernel.events.IEventHandler; import com.itextpdf.kernel.pdf.canvas.PdfCanvas; import com.itextpdf.kernel.font.PdfFont; import com.itextpdf.kernel.font.PdfFontFactory; public class FooterEventHandler implements IEventHandler { private PdfFont font; public FooterEventHandler() throws Exception { font = PdfFontFactory.createFont("/fonts/SourceHanSansSC-Regular.otf"); } @Override public void handleEvent(Event event) { PdfDocumentEvent docEvent = (PdfDocumentEvent) event; com.itextpdf.kernel.pdf.PdfPage page = docEvent.getPage(); int pageNum = docEvent.getDocument().getPageNumber(page); int totalPages = docEvent.getDocument().getNumberOfPages(); String text = "第 " + pageNum + " 页 / 共 " + totalPages + " 页"; PdfCanvas canvas = new PdfCanvas(page); canvas.beginText() .setFontAndSize(font, 9) .moveText(0, 20) .showText(text) .endText(); } }

不要忘了给PdfDocument注册这个处理器:

PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, new FooterEventHandler());

这段代码有几个细节值得说。

moveText(0, 20)里的20是页面底部预留的高度,单位是用户空间单位,基本等价于pt。如果你的页边距是2cm,也就是大约57pt,那么20pt的页脚位置基本就在页边距下方空白处,不会压到正文。

因为是END_PAGE事件,每页结束时执行,所以页码不会乱,包括最后一页的更新也会正常。

4. 常见问题与排查技巧实录

4.1 表格样式错乱或边框消失

Markdown里的表格经过解析器转换后,得到的是<table>、<th>、<td>这些标准标签。但ITExt的pdfHTML对表格的默认样式很朴素,没有边框、没有padding,列宽也可能挤压在一起。

我第一次转换出来的表格,单元格文字叠在一起,边框看不到,简直没法看。后来排查发现原因有两个。

第一个是CSS没有生效。pdfHTML对CSS选择器的支持有限,它支持th、td这样的标签选择器,但不支持某些高级选择器比如table > tbody > tr:nth-child(odd)这类伪类。解决方案是尽量用简单的元素选择器,别用太复杂的组合。

第二个是单元格里内容过长,导致表格被撑爆。解决方案是在td上设置word-wrap: break-word;,并且给table设置table-layout: fixed;。我用的模板里加了这两条之后,表格再没出过问题。

4.2 图片不显示或路径解析失败

Markdown里的图片语法![alt](path),解析后变成<img src="path" alt="alt">。pdfHTML要显示图片,必须能通过src路径加载到图片文件。

这里有个很容易踩的坑:如果src是相对路径,比如./images/foo.png,默认情况下pdfHTML会把路径当成相对于当前工作目录的路径来解析。你如果是在Tomcat里跑的Web服务,工作目录可能是bin目录,图片自然找不到。

解决办法是在ConverterProperties上设置setBaseUri(),指定一个资源根目录。

ConverterProperties props = new ConverterProperties(); props.setBaseUri("C:/project/uploads/");

如果图片是网络URL,比如https://example.com/img/foo.png,pdfHTML本身也能加载,但我建议不要依赖它下载网络图片,一是网络延迟不可控,二是外网图片可能随时失效。稳妥的做法是预处理阶段把图片下载到本地,替换img标签的src为本地路径。

4.3 性能问题和内存控制

文档量大时,HTML转PDF很容易吃内存。核心原因是pdfHTML解析HTML时会在内存里构建完整的DOM树和样式树,如果HTML有几MB,内存占用可能达到几百MB。

我处理过单文件超过10MB的Markdown文档,转换时堆内存直接飙到1.5GB,后来做了两个优化。

第一个优化是复用FontProvider和ConverterProperties。这两个对象创建成本高,尤其是字体加载,不要在循环里每次new。

第二个优化是可以考虑拆分文档。如果源文档结构允许,比如目录章节清晰,可以拆成多个HTML块分别转换,再用ITExt的PdfMerger合并PDF。这样单次转换的内存占用能显著降低,缺点是合并后总页码和页脚处理要额外设计。

4.4 常见问题速查表

问题现象根源分析解决方案
PDF里中文全变空白未注册中文字体FontProvider注册Noto Sans CJK或思源黑体
中文出现乱码HTML流编码不是UTF-8ByteArrayInputStream用UTF_8,head加meta charset
代码块内容超出页面被截断没设置pre-wrappre里加white-space: pre-wrap
表格边框不显示CSS选择器太复杂用简单元素选择器,加table、th、td样式
图片显示为空相对路径找不到ConverterProperties设置setBaseUri
转换时内存溢出文档过大或对象重复创建复用FontProvider,必要时拆分文档再合并
页面之间内容断裂元素跨页对标题和表格加page-break-inside: avoid

最后再分享一个经验:在实际项目里,Markdown内容和HTML模板的耦合远比你想象的大。你定的CSS模板会影响所有转换出来的PDF,所以不要一次性把所有样式写完就上线。先拿两三篇真实文档做样本,转换后逐页检查标题、表格、代码块、图片四类元素的表现,确认没问题后再批量转换。这个习惯帮我避免了很多次线上文档导出返工的问题。

如果你后续还要支持目录自动生成、PDF元数据标注、加密权限控制,ITExt也都能实现。先从这条链路跑通,后面扩展就不难了。

相关新闻

Arch Linux下xrdp远程桌面故障排查:闪退黑屏蓝屏与D-Bus配置

Arch Linux下xrdp远程桌面故障排查:闪退黑屏蓝屏与D-Bus配置

1. 先说结论&#xff1a;这趟 xrdp 的坑&#xff0c;值得记录最近在一台 Arch Linux 上折腾 xrdp&#xff0c;目标特别朴素&#xff1a;局域网里的另一台电脑能直接远程登录图形桌面&#xff0c;不要每次有事都跑机房。结果这个看起来常规的活儿&#xff0c;硬生生把我从客户端…

2026/10/20 12:55:46 阅读更多 →
PyTorch深度学习工程实践:核心原理与训练避坑指南

PyTorch深度学习工程实践:核心原理与训练避坑指南

做深度学习这几年&#xff0c;PyTorch 几乎贯穿了我所有实际落地的项目。从早期图像分类的 Demo&#xff0c;到后来需要上线的检测服务&#xff0c;再到大规模分布式训练&#xff0c;这个框架始终是绕不开的主力工具。我见过很多新手拿着一堆教材却卡在入门环节&#xff0c;也见…

2026/10/20 12:55:46 阅读更多 →
C语言指针辨析:数组指针、指针数组与二级指针一次讲透

C语言指针辨析:数组指针、指针数组与二级指针一次讲透

把int *p[3]、int (*p)[3]和int **pp并排放在一起&#xff0c;绝大多数人会在头两秒内卡壳。我当年在某项目里排查一个段错误&#xff0c;查了整整一下午&#xff0c;最后发现就是把数组指针和指针数组混着用了——声明差一个括号&#xff0c;函数传参时整个类型都变了&#xf…

2026/10/20 12:55:46 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年&#xff0c;我大部分时间都在跟浏览器标签页打交道&#xff0c;直到第一次把桌面应用跑起来&#xff0c;才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词&#xff0c;最开始是在某段时间频繁出现在同事的讨论里&#xff0c;一个用HTML…

2026/10/21 9:32:40 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档&#xff0c;主要面向智能锁安装人员、终端用户及售后维护者&#xff0c;帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件&#xff0c;大小4.37MB&#xff0c;内容结构清晰&#xff…

2026/10/21 9:32:40 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统&#xff0c;整车要求空载跑到8m/s&#xff0c;电机转速已经拉到额定点&#xff0c;驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令&#xff0c;转速纹丝不动&#xff0c;三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/21 9:32:40 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年&#xff0c;用它写过嵌入式驱动、做过游戏服务端&#xff0c;也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词&#xff0c;我其实挺感慨的——这门语言的难点从来不是语法多&#xff0c;而是知识点之间的耦合太深…

2026/10/21 9:32:40 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书以PDF格式发布&#xff0c;适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开&#xff0c;先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能&#xff0c;再给出完整安装步骤&…

2026/10/21 9:32:40 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历&#xff1a;翻开源码注释、论文摘要或者一份专业报告&#xff0c;每个字都认识&#xff0c;连在一起却像天书。想找人聊聊&#xff0c;身边要么没人懂&#xff0c;要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型&#xff0c;几秒钟之后&a…

2026/10/21 9:31:32 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事&#xff1a;AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里&#xff0c;按宣传口径&#xff0c;本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”&#xff0c;而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起&#xff1a;用户到底在追求什么“封号重开”这四个字&#xff0c;放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流&#xff0c;背后是大量的时间和精力成本。正常情况下&#xff0c;没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”&#xff0c;而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时&#xff0c;就意识到&#xff1a;单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/21 4:27:17 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →