Keras 实战:从文本编码到扩散模型,轻松搭建文字生成图像项目

我记得很清楚,第一次在电脑前跑通“输入一句文字、输出一张图”的流程时,那种感觉确实很奇妙。前几分钟还在为模型结构报错发愁,后一秒钟就看到屏幕上生成了和描述高度相关的画面。这篇文章不是来科普生成式AI的概念的,而是想和你一起拆解一个完整的技术链路:用 Python 和 Keras 把文字到图像这件事从概念做到落地。适合那些已经会一点 Python、知道张量和神经网络是什么,但还没系统跑过一个生成式项目的读者。我会把项目设计思路、核心机制、代码骨架、训练经验和踩坑记录都放进来。

1. 项目整体设计:为什么选 Keras,以及要面对的核心问题

1.1 从"文字到图像"这个任务说起

文字到图像生成,本质上是要让模型学会两种信息的对齐映射:一边是人类语言这种离散、高语义化的符号序列,另一边是像素空间里连续、低语义化的数值矩阵。用更直白的话说,模型得先知道“一只戴帽子的柴犬”这句话的语义落脚点在哪,然后还得知道这种语义该对应画面上哪些像素块、什么颜色分布、怎样的空间构图。这是一个跨模态的学习任务,也是整个生成式AI里最有工程价值的场景之一。

单说“落地”这个词,包含的东西其实很多。一个简单的 Demo 是落地,一个能批量推理、稳定产出、方便接入业务的生成服务也是落地。我在这篇文章里想带着大家实现的,是前者到中间态的过渡:一个可训练、可推理、可调整的 Keras 生成项目,同时给后期扩展留出空间。整个项目依赖的核心组件包括文本编码器、条件控制模块和图像生成模型,这三块缺一不可。

1.2 Keras 在生成式任务中的位置和优势

先别急着上大模型框架。Keras 在高层次 API 上的成熟度,以及和 TensorFlow 生态的无缝衔接,让它非常适合做生成式AI里的原型验证和中小规模生产任务。抛开性能调优层面的争议,Keras 的核心优势在我看来就是三点:建模速度快、调试门槛低、部署路径全。像我们在项目中要用的keras.layers里的各类层结构、tf.data数据管道、模型保存与转换工具链,基本上都能以较低的试错成本串起来。

举一个很实际的例子。在生成式模型里,我们经常要做一些自定义的前向传播流程——比如训练的时候要把文本条件向量反复注入生成网络的多个层里,这就意味着不能只靠model.fit一条路走到黑。Keras 里通过继承Model类重写call或train_step的方式,可以很优雅地处理这类复杂逻辑,同时依然享受框架自带的梯度记录、回调和分布式策略。这一点在项目骨架设计时帮助我们省掉了大量底层代码。

另一个不能忽略的层面是社区资源。Keras 官方和社区里积累了非常多针对图像分类、图像生成、迁移学习的现成模块,比如用预训练模型提取文本特征、用 KerasCV 加载稳定的扩散模型组件,都能直接融入自己的项目。站在工程的角度,能站在巨人的肩膀上确实是选型时要认真考虑的维度。

1.3 整条技术链路的架构安排

我建议把整个项目拆成四个模块:数据模块、文本编码模块、图像生成模块、训练与推理模块。数据模块负责把图文对数据统一成模型需要的张量格式;文本编码模块把句子变成定长或变长的语义向量;图像生成模块通过条件机制把语义向量“翻译”成图像;训练与推理模块则把前三个模块串起来,完成梯度更新和生成推理。

在我实际搭过的项目里,最核心的调控开关有两个:一是条件注入的方式,也就是文本向量在哪个位置、以什么权重进入图像生成过程;二是生成目标的定义,比如是在像素空间直接重建,还是在一个压缩后的潜在空间做去噪。这两个开关直接决定模型的行为特性,也决定了后续调试时候要盯哪个指标。稍后我会在核心机制部分展开讲这两块,并把代码级实现也列出来。

2. 核心机制拆解:文本编码、条件注入与图像生成

2.1 文本侧:从句子到张量的三步转换

要让文本进入神经网络,必须先把它变成数值。用 Keras 完成这件事通常分三步:先通过TextVectorization层把句子切成 token,得到一个整数序列;再把整数序列映射成稠密向量,这一步可以通过Embedding层实现(也可以直接接预训练模型的输出);最后还需要一个把变长序列整合成固定向量或矩阵的编码器,比如双向 LSTM、Transformer Encoder 或简单的池化层。

这三步里最值得说的其实是最后一步的设计选择。我们可以把文本编码器的输出处理成一个固定维度的语义向量,这叫全局表示,适合在图像生成时做全局条件控制;也可以保留每个 token 的向量形成一个特征序列,这就可以在图像生成的不同空间位置做细粒度的条件注入。项目早期我建议先用全局向量,因为好调试、好理解,等整个链路跑通后再考虑细节特征注入。

下面是一个很精简的文本编码器实现骨架:

import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers def build_text_encoder(vocab_size, max_len, embed_dim, latent_dim): inputs = keras.Input(shape=(max_len,), dtype="int64") x = layers.Embedding(vocab_size, embed_dim)(inputs) x = layers.Bidirectional(layers.LSTM(latent_dim, return_sequences=False))(x) x = layers.Dense(latent_dim, activation="tanh")(x) return keras.Model(inputs, x, name="text_encoder")

这里latent_dim就是我们要得到的文本语义向量维度,后面做条件注入时它要参与拼接和变换。注意tanh激活是有意选择的,它可以把向量值控制在 -1 到 1 之间,这在后续注入时能减少数值波动带来的训练不稳定问题。

2.2 图像侧:扩散模型和生成对抗网络的选择

图像生成端的方案选择,直接决定项目的成败。当前主流的路线有两条:生成对抗网络和扩散模型。但就文字到图像任务来说,扩散模型在条件控制的稳定性和生成多样性上明显更占优势。原因也好理解——扩散模型的训练目标是从噪声逐步去噪还原图像,这个过程天然允许外部条件反复介入,每一步去噪都可以参考文本语义信息,相当于在多个环节做“纠偏”。而生成对抗网络往往是生成器一次性输出完整图像,文本信息只能在生成入口处影响一次,容错空间小不少。

当然,直到今天依然有很多场景在用 GAN。比如在低分辨率、小数据量、对实时性要求高的任务里,GAN 的收敛速度和计算开销还是很有吸引力的。不过从普通开发者做项目、上线功能的视角看,扩散模型的可控性和质量上限更值得押注。所以下面这个项目,图像生成主干就用一个轻量级的扩散模型,配合文本条件的交叉注意力机制。

交叉注意力是条件注入的关键结构。简单说就是把文本向量当作注意力机制中的 Key 和 Value,把图像特征当作 Query,让图像生成过程中的每个空间位置都能“参考”到最相关的文本信息。Keras 里可以用layers.MultiHeadAttention直接实现,不用自己造轮子。

2.3 潜在空间:先压缩再生成的思路

扩散模型在高分辨率图像上做逐像素处理,计算量非常夸张。一个 64×64 的图就有 4096 个像素点,每个点还要经历几十步去噪,训练开销不是普通单卡能轻松扛住的。所以成熟方案的做法是先训练一个自编码器,把图像压缩到一个更低维的潜在表示,在潜在空间里完成扩散去噪,最后再通过解码器还原成图像。

这个“先在压缩世界里做生成,再重新展开”的思路,类似我们写文章时先列大纲再逐段展开。大纲层面改动成本低、容错高,等大纲确定了再去往段落里填细节。项目中我也沿用这个思路,用一个小型的 VAE 结构实现图像压缩,然后在潜在特征图上进行条件扩散。这可以让项目在单张消费级显卡上也可以训练,纯 CPU 也不是完全没有跑通的可能,只是慢一些。

图像侧的主干网络我习惯用 UNet 结构加注意力模块。Keras 里可以直接用函数式 API 搭一个简化版:

def build_unet(input_shape): inputs = keras.Input(shape=input_shape) # 收缩路径 c1 = layers.Conv2D(64, 3, activation="relu", padding="same")(inputs) c1 = layers.Conv2D(64, 3, activation="relu", padding="same")(c1) p1 = layers.MaxPooling2D(2)(c1) c2 = layers.Conv2D(128, 3, activation="relu", padding="same")(p1) c2 = layers.Conv2D(128, 3, activation="relu", padding="same")(c2) p2 = layers.MaxPooling2D(2)(c2) c3 = layers.Conv2D(256, 3, activation="relu", padding="same")(p2) # 扩张路径 u1 = layers.Conv2DTranspose(128, 3, strides=2, padding="same")(c3) u1 = layers.Concatenate()([u1, c2]) u1 = layers.Conv2D(128, 3, activation="relu", padding="same")(u1) u2 = layers.Conv2DTranspose(64, 3, strides=2, padding="same")(u1) u2 = layers.Concatenate()([u2, c1]) u2 = layers.Conv2D(64, 3, activation="relu", padding="same")(u2) outputs = layers.Conv2D(3, 3, activation="sigmoid", padding="same")(u2) return keras.Model(inputs, outputs)

提示:上面的 UNet 结构特意省去了跳跃连接之外的注意力模块,目的是把重点讲明白。实际项目里会在中间层加入MultiHeadAttention完成文本条件注入,完整代码我会在第三节给出。

3. 从零搭建文字到图像项目:数据处理、模型训练与推理

3.1 数据集准备:图文对的质量决定了上限

任何生成模型的上限都由数据决定,这一点在图文任务里表现得特别明显。你在准备数据时要格外注意三个问题:图文对是否对齐、文字描述的粒度是否足够、图像分辨率是否统一。哪怕是同一个数据集,文本写“一只猫”和写“一只橘白相间的猫蹲在窗台上望向远方”,对模型学到的东西影响完全不一样。

我在实际项目中使用的模拟数据集大约一万对图文样本。图像统一缩放为 64×64,文本长度限制在 32 个 token 以内。数据管道用tf.data来做,批量喂给模型。这里给一个数据预处理的参考:

def preprocess_image(path, target_size=(64, 64)): image = tf.io.read_file(path) image = tf.image.decode_jpeg(image, channels=3) image = tf.image.resize(image, target_size) image = tf.cast(image, tf.float32) / 127.5 - 1.0 return image

数据量小时不要急着上复杂模型,先用一个能够拟合这个小数据集的精简结构把链路跑通,再逐步放大数据规模,这是降低 Debug 成本的有效策略。

3.2 训练目标:重建、条件与噪声预测

扩散模型的核心训练目标不是直接生成图像,而是预测噪声。也就是说,我们会选择一个步数(比如 1000 步),在训练时随机抽取一个时间步 t,把图像按该时间步的噪声计划加噪,然后让模型去预测被加进去的那个噪声。文本条件在每一步都会参与预测。整个训练目标可以表达为一个简单的均方误差:

预测的噪声和真实噪声之间的 MSE 越小,说明模型对图像结构的理解和对文本条件的把握越准确。真正推理时,我们从一个纯噪声出发,用模型反复预测并去除噪声,迭代指定的步数,最终还原出与文本描述匹配的图像。

训练代码的核心部分其实并不复杂。下面是我整理过的训练步骤简化版:

def train_step(self, data): images, texts = data batch_size = tf.shape(images)[0] # 随机采样时间步 t = tf.random.uniform( minval=0, maxval=num_timesteps, shape=(batch_size,), dtype=tf.int32 ) # 生成噪声并加噪 noise = tf.random.normal(shape=tf.shape(images)) noisy_images = add_noise(images, noise, t) with tf.GradientTape() as tape: predicted_noise = self.model([noisy_images, texts, t]) loss = tf.reduce_mean(tf.square(predicted_noise - noise)) grads = tape.gradient(loss, self.model.trainable_variables) self.optimizer.apply_gradients(zip(grads, self.model.trainable_variables)) return {"loss": loss}

这里有一个关键细节:时间步 t 也必须变成模型的输入。因为扩散模型在不同时间去噪的行为不同,模型必须要知道现在处于加噪过程的哪个阶段,才能决定去噪力度。传统做法是把它编码成正弦位置向量,再和别的特征相加或拼接。这一块千万别省,少了它模型基本学不出来。

3.3 完整模型结构:文本编码器、UNet 和注意力注入

把前面几个模块拼起来,才能构成完整可训练模型。我的方案是这样的:文本输入先通过一个文本编码器变成latent_dim维向量;图像侧的 UNet 中间层把潜在特征图展平后,与文本向量一起送入注意力模块,注意力输出的结果再恢复到特征图形状继续后续上采样。这样的注入方式能让文本信息在生成过程中多次参与引导,而不是只在起跑线上起作用。

下面是一个关键注入代码:

class CrossAttentionBlock(layers.Layer): def __init__(self, num_heads=8, key_dim=64, **kwargs): super().__init__(**kwargs) self.attention = layers.MultiHeadAttention( num_heads=num_heads, key_dim=key_dim ) self.norm = layers.LayerNormalization(epsilon=1e-6) def call(self, image_feat, text_feat): b, h, w, c = tf.shape(image_feat)[0], tf.shape(image_feat)[1], tf.shape(image_feat)[2], tf.shape(image_feat)[3] # 展平成序列形式 image_seq = tf.reshape(image_feat, [b, h * w, c]) # 交叉注意力:Query来自图像,Key/Value来自文本 attn_out = self.attention(query=image_seq, key=text_feat, value=text_feat) attn_out = self.norm(attn_out + image_seq) return tf.reshape(attn_out, [b, h, w, c])

text_feat在这里被当成了 Key 和 Value,它的长度与注入位置无关。因为我们用全局语义向量,所以 Key/Value 的序列长度就是 1(或者稍微扩展几个位置)。如果是更细粒度的文本特征注入,Key/Value 长度会对应 token 数。

3.4 训练策略与参数选择

训练生成式模型,超参数的选择比模型结构更容易影响最终效果。几个关键参数我整理成了表格,方便参考:

参数推荐值注意事项
图像分辨率64×64先跑通链路,再考虑放大到 128×128
批大小16~32取决于显存,小批多步比大批少步更容易稳定
学习率5e-5 ~ 2e-4用 Adam 优化器,必要时加 Warmup
扩散步数训练时 1000,推理时 50~100训练和推理的步数可以不一致
文本向量维度256太小容纳不了语义信息,太大增加参数

关于学习率,我建议刚开始时固定在一个较小的值上,先确认模型损耗平稳下降,再考虑尝试学习率调度器。很多项目训练不稳定,不是结构写错了,而是学习率太大导致损耗震荡。

3.5 推理生成:从纯噪声开始迭代去噪

推理过程用一句话概括:从随机噪声出发,按每一步去噪公式迭代,每一轮都以文本条件为依据更新图像。Keras 里实现的核心逻辑如下:

def generate(model, text, noise_steps=50): text_vec = text_encoder(text) image = tf.random.normal([1, 64, 64, 3]) for t in reversed(range(noise_steps)): t_tensor = tf.fill([1], t) predicted_noise = model([image, text_vec, t_tensor]) image = denoise_step(image, predicted_noise, t, noise_steps) return image

每步去噪公式看起来抽象,其实就是在当前图像上减去一部分预测噪声,再按系数缩放。真实的公式还包含一些噪声计划相关的系数,具体实现需要参考所选扩散模型的论文或开源实现的公式。我建议第一次做的时候直接用已开源的调度算法,比如 KerasCV 提供的DDIMScheduler或DDPMScheduler,等效果稳定之后再尝试自己实现简化版本。

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

4.1 显存不足:小模型也一样爆显存

很多第一次跑生成式项目的朋友都会遇到显存不够的问题,明明模型参数不大,怎么一跑训练就爆了?原因通常出在中间激活值上。扩散模型训练时,CNN 特征图在多个尺度上都保留完整张量,再加上时间步条件和注意力模块,中间激活可能远大于模型本身的参数量。尤其是加了注意力后,序列长度和头数一旦设置过大,显存消耗是爆炸式的增长。

我的排查思路是这样的:先把批大小降到 1,确认能不能跑通一次前向和反向;如果还不能,就检查特征图尺寸是不是太大、注意力层的序列长度是否合理;稳定下来后再逐步调大批大小。关掉混合精度训练可能反而更省显存,因为某些算子在不支持混合精度的设备上会有额外显存消耗。

4.2 生成图像出现条纹状伪影

条纹伪影是图像生成里特别典型的失败形态,通常表现为画面里有规律的横向或纵向纹路。我遇到这种情况时,首先怀疑的就是转置卷积的使用方式。Conv2DTranspose如果步长和卷积核设置不合理,很容易引入棋盘效应。解决办法有两个:换成UpSampling2D加普通Conv2D的组合,或者在转置卷积后接一个小的卷积层来修正。

另一个原因是去噪步数太少。推理时的去噪步数如果远小于训练时使用的步数,模型还没来得及逐步修正高频细节就结束了,也容易产生条带感。可以适当调高推理步数,观察是否缓解。

4.3 损耗一直不下降或干脆发散

这种情况我至少遇到过三次,原因各不相同。第一次是文本编码器输出没有归一化,数值过大导致梯度爆炸;第二次是学习率设定过高,前几百步损耗就冲到 NaN;第三次是数据管道里图像像素范围不统一,有的在 0 到 1,有的在 -1 到 1,导致模型无所适从。

我的排查建议是:先固定一个极小的学习率(比如 1e-5),用仅包含 100 样本的子数据集训练 200 步,观察损耗是否还有持续下降的趋势。如果没有,大概率是模型结构或数据管道的问题,而不是学习率的问题。先把数据管道的输出切成图片可视化确认一下,这一步看似浪费时间,却能省掉后面好几天的排查。

4.4 文本条件不起作用,生成结果和描述无关

这个问题也很常见,生成出来的图像质量不错,但完全看不出和输入文字有什么关系。问题大概率出在条件注入的强度上。如果文本向量只在最开始和图像特征拼接过一次,后续层里的图像特征早就把文本信息冲淡了。建议在 UNet 的多个尺度上反复注入条件,并在每个注入点之后使用层归一化,让文本信号持续影响生成过程。

也可以检查一下文本编码器是否训练到位。一开始训练时,文本编码器如果被随机初始化,它输出的向量基本是噪声,模型根本没有能力从中提取语义。这时候可以考虑先用一个小任务单独预训练文本编码器,等到语义向量稳定了再接入生成模型。

5. 写在实际项目之后的几点经验

项目做到后面,我的体会是:生成式AI项目的关键不是把某个模型的代码跑通,而是建立起一套能够稳定复现结果、快速定位问题的调试框架。文本侧、图像侧、条件注入、训练策略这四个模块的边界一定要清晰,任何时候改一个模块都不应该影响其他模块的可用性。我在项目里为每个模块都写了一个独立的调试脚本,这样做的好处是回归验证成本特别低。

还有一个容易被忽视的点是训练过程的固定随机种子。生成模型本身就带有很强的随机性,如果连数据加载顺序、噪声采样、权重初始化这些随机源都不固定,几乎无法判断改动某个参数到底产生了什么效果。项目里我在tf.random.set_seed和np.random.seed上做了统一设置,这样多次运行之间的比较才有意义。

最后想分享一个实战技巧:不要一开始就追求生成效果惊艳。先把一个 64×64 的小模型、小数据、短步数的全流程跑通,再逐步加数据量、加模型复杂度、加分辨率。这个“先全流程,再高质量”的思路在多个项目里都帮我节省过大量时间。你花在“让流程跑通”上的时间,其实是在为后面的调优铺路。

相关新闻

Spring AI Alibaba 架构拆解:从模型适配到多步编排的工程实践

Spring AI Alibaba 架构拆解:从模型适配到多步编排的工程实践

1. 从 Spring AI 到 Spring AI Alibaba:一个被低估的适配层第一次看到 Spring AI Alibaba 这个名字,很多人的第一反应是"又一个套壳项目"。毕竟 Spring AI 本身已经提供了 ChatClient、EmbeddingClient、VectorStore 这些抽象,再往…

2026/10/20 3:41:10 阅读更多 →
TCP握手排查实战:从抓包到队列,搞懂backlog与重传调参

TCP握手排查实战:从抓包到队列,搞懂backlog与重传调参

前阵子接手一个连接超时的排查,同事第一句话就是“我们是不是该调一下 TCP 参数”。我问他调哪个参数、依据什么、期望变成什么效果,他答不上来。这其实是我见过最常见的状态——手里存着一堆sysctl参数列表,但对 TCP 握手的过程缺乏可观测的…

2026/10/20 3:41:10 阅读更多 →
OpenCV透视矫正+OCR识别:从拍照文档到可编辑文本的实战

OpenCV透视矫正+OCR识别:从拍照文档到可编辑文本的实战

刚把上周拍的几页纸质资料整理成可编辑文本,整个过程从手机照片到最终文字输出,只用了一个Python脚本。很多朋友问我怎么做到的,其实就是OpenCV做文档矫正,再交给OCR引擎识别。这个需求在实际工作中太常见了:扫描件要转…

2026/10/20 3:41:10 阅读更多 →

最新新闻

神经网络边权更新:从浮点精度到硬件协同的工程实践

神经网络边权更新:从浮点精度到硬件协同的工程实践

1. 这不是“调参”,而是神经网络的“肌肉记忆”形成过程很多人第一次看到反向传播公式时,下意识觉得:“哦,就是按链式法则求个导,然后用学习率乘一下更新权重。”——这就像说“跑步就是抬腿、迈步、落地”&#xff0c…

2026/10/20 4:27:40 阅读更多 →
SRGAN原理与实战:超分辨率生成对抗网络详解

SRGAN原理与实战:超分辨率生成对抗网络详解

简介:本资源是基于SRGAN(生成对抗网络)的图像超分辨率完整复现项目,面向深度学习初学者与计算机视觉方向研究者,聚焦解决大倍率(4)超分中高频纹理丢失、感知质量差的核心难题。项目实现了论文提…

2026/10/20 4:27:40 阅读更多 →
TCP协议深度实训:银行前置机通信的三道安检门与二进制报文解析

TCP协议深度实训:银行前置机通信的三道安检门与二进制报文解析

1. 这不是“银行系统”,而是一次面向真实金融场景的TCP协议深度实训很多人看到“网络银行”四个字,第一反应是点开一个网页输账号密码——但这次我们要做的,恰恰是把浏览器、HTTPS、前端框架这些“遮羞布”全撕掉,直接蹲在TCP连接…

2026/10/20 4:27:40 阅读更多 →
AutoRemesher 网格修复:把破面高模重网格成干净四边形

AutoRemesher 网格修复:把破面高模重网格成干净四边形

AutoRemesher 网格修复:把破面高模重网格成干净四边形 【免费下载链接】autoremesher Automatic quad remeshing tool 项目地址: https://gitcode.com/GitHub_Trending/au/autoremesher 扫描仪吐出的高模又密又破:几百万张碎三角面,边…

2026/10/20 4:27:40 阅读更多 →
WorkBuddy_WorkBuddy界面布局指南18_移动端App界面布局

WorkBuddy_WorkBuddy界面布局指南18_移动端App界面布局

移动端App界面布局 摘要 本文围绕移动端App界面布局展开讨论,重点分析手机端与桌面端在布局上的核心差异,并针对"云端工作"与"连接电脑"双模式场景,给出界面切换的设计思路与可运行的代码实现。文章涵盖视口与响应式基础…

2026/10/20 4:27:40 阅读更多 →
Qt新建工程全攻略:从环境配置到构建调试一步到位

Qt新建工程全攻略:从环境配置到构建调试一步到位

最近有朋友问我:Qt 到底怎么新建工程?他说自己把 Qt Creator 装好了,结果打开软件,面对一堆模板和选项完全不知道该点哪里。这个问题看起来基础,但我在带新人时发现,能在这一步顺畅走完、并且真正理解每个选…

2026/10/20 4:26:40 阅读更多 →

日新闻

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实现详解

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

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

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

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

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

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

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在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 阅读更多 →