PyImgSearch实战:用Python从零构建以图搜图系统
1. 从零理解 PyImgSearch一个用 Python 做以图搜图的完整项目第一次接触 PyImgSearch 是在一个做电商商品去重的需求里。当时团队手里有几十万张商品图运营那边反馈说很多供应商上传的图片其实是同一款货只是换了角度、调了亮度、加了水印人工比对根本看不过来。我一开始想的是用图片哈希做去重但很快就发现哈希只能搞定完全一样或者几乎一样的图稍微裁剪一下、换个背景就失效了。后来翻资料翻到了 PyImgSearch 这个项目它做的事情很纯粹用 Python 把以图搜图这套流程从头搭一遍包括特征提取、索引构建、相似度检索代码量不大但五脏俱全特别适合拿来理解图像检索的底层逻辑也适合作为二次开发的起点。PyImgSearch 本质上是一个基于内容的图像检索Content-Based Image Retrieval简称 CBIR系统。你给它一张查询图它从图库里找出视觉上最相似的若干张返回给你。它解决的核心问题是当图片没有可靠的文本标签、或者标签质量很差的时候怎么靠图像本身的视觉特征来找到相似内容。这套东西的适用人群其实很广做电商的可以用它做同款检索和去重做设计的可以用它做素材库管理做安防的可以用它做目标图检索甚至做个人相册整理的也能用。只要你有“一堆图 想按视觉相似度找图”这个需求PyImgSearch 的思路就能派上用场。我写这篇东西的出发点是把 PyImgSearch 这个项目里最关键的几个环节拆开讲透包括它为什么这么设计、每一步背后的原理是什么、实际跑起来会遇到哪些坑、参数怎么调。网上很多翻译文章只把代码贴出来但没告诉你为什么这么写、换个场景该怎么改我尽量把这些补上。文章里涉及的操作步骤和参数选择一部分来自项目本身的实现一部分是我在实际改造过程中总结出来的常见实践我会明确区分哪些是原项目的、哪些是我补充的。2. 整体设计思路与方案选型拆解2.1 为什么不用深度学习模型而是走传统特征路线PyImgSearch 最让人意外的一点是它没有用现在流行的 CNN 特征或者 CLIP 这类多模态模型而是走了比较传统的路线用颜色直方图、纹理特征比如 Haralick 特征、边缘方向直方图这些手工设计的特征来描述图像。很多人第一反应是“这都什么年代了还用传统特征”但我实际用下来发现这个选择在特定场景下非常合理。传统特征最大的优势是轻量和可解释。颜色直方图提取一张图可能就几毫秒特征维度也就几十到几百维整个图库几万张图的索引文件可能就几十兆检索的时候算距离也快。而深度学习特征动辄 512 维、1024 维甚至更高提取要过一遍网络没有 GPU 的话慢得让人抓狂。如果你的图库规模在十万级以内而且对检索精度要求不是那种“必须找到语义相同的图”传统特征完全够用。另外传统特征对光照、旋转的鲁棒性可以通过设计来调节比如用 HSV 空间的直方图就比 RGB 空间对光照变化更稳。当然传统特征的短板也很明显它抓的是低层视觉信息不理解语义。你搜一只猫它可能返回一堆毛茸茸的纹理相似的图但不一定是猫。所以如果你的场景是“找语义相似的图”那还是得上深度学习特征。PyImgSearch 的定位更像是一个教学和原型工具让你先把检索流程跑通理解索引、距离度量、排序这些环节等流程通了再换特征提取器也不迟。2.2 特征提取、索引、检索三段式架构PyImgSearch 的架构可以拆成三段特征提取、索引构建、相似度检索。这三段是解耦的每一段都可以单独替换这是它设计上比较聪明的地方。特征提取阶段项目里提供了多种描述子你可以组合使用。比如颜色方面用 HSV 直方图纹理方面用灰度共生矩阵GLCM算对比度、相关性、能量、同质性这四个量形状方面用 Hu 矩或者边缘方向直方图。每种特征提取完会拼成一个长向量作为这张图的“指纹”。这里有个关键决策要不要做特征归一化。如果不归一化颜色直方图的数值范围可能是 0 到几千而 Hu 矩可能只有零点几距离计算的时候颜色特征会完全主导纹理和形状特征等于白提。所以实际用的时候一定要对每个特征维度做标准化让它们在同一量级上。索引构建阶段项目用的是暴力检索brute-force的思路就是把所有图的特征向量存成一个矩阵检索的时候算查询向量和矩阵里每一行的距离然后排序取 top-k。这个做法在几万张图的规模下完全可行因为矩阵运算可以用 NumPy 向量化一次算完所有距离。但如果图库到了百万级暴力检索就扛不住了这时候需要引入近似最近邻ANN索引比如 Faiss 或者 Annoy。PyImgSearch 本身没带 ANN但它的接口设计留了口子你可以把索引部分换成 Faiss检索速度能提升一到两个数量级。检索阶段核心是距离度量的选择。项目里默认用的是欧氏距离但实际用的时候余弦距离往往更合适尤其是特征做过归一化之后。欧氏距离对向量的模长敏感余弦距离只看方向对于“颜色分布比例”这种特征方向比绝对大小更重要。我一般会把特征向量做 L2 归一化然后用余弦距离或者内积来算相似度效果更稳。2.3 距离度量与相似度排序的取舍距离度量的选择直接决定了检索结果的好坏这里值得单独说一下。假设你有两个特征向量 A 和 B欧氏距离算的是它们在空间里的直线距离余弦距离算的是它们夹角的余弦值。如果 A 和 B 的模长差异很大但方向一致欧氏距离会认为它们不相似而余弦距离会认为它们高度相似。在图像检索里模长往往代表“强度”或者“数量”比如颜色直方图的模长和图像里颜色的总量有关。如果你关心的是颜色的相对分布而不是绝对数量那余弦距离更合适。举个例子一张图整体偏暗另一张图整体偏亮但两张图的颜色比例分布是一样的这时候余弦距离会认为它们相似而欧氏距离会认为它们差很远。实际场景里我们通常更关心分布而不是绝对亮度所以余弦距离用得更多。排序的时候除了距离本身还可以引入一些后处理。比如对 top-k 结果做重排序re-ranking用更精细的特征或者空间验证来调整顺序。PyImgSearch 本身没做重排序但这是提升精度的常用手段。我试过在颜色特征检索完之后对 top-50 结果再用纹理特征算一遍距离加权融合两个距离最终排序质量比单用颜色特征好不少。3. 核心细节解析与实操要点3.1 颜色特征提取HSV 直方图怎么设参数颜色特征里最常用的就是直方图。PyImgSearch 用的是 HSV 空间的直方图而不是 RGB。为什么因为 RGB 三个通道高度相关而且对光照变化很敏感同一个物体在阳光下和阴影里RGB 直方图差异巨大。HSV 把色调H、饱和度S、明度V分开色调对光照相对稳定更适合做检索。具体提取的时候H 通道通常量化成 8 到 18 个 binS 和 V 各量化成 3 到 8 个 bin。bin 的数量是个权衡bin 太少区分度不够不同颜色的图可能落到同一个 bin 里bin 太多特征维度爆炸而且容易受噪声影响泛化变差。我一般用 H12、S4、V4总共 192 维这个配置在多数场景下表现比较均衡。还有一个细节是加权。人眼对色调的敏感度高于饱和度和明度所以可以给 H 通道更高的权重。比如 H 的每个 bin 乘以 2S 和 V 保持原值这样色调在距离计算里占的比重更大。这个权重不是固定的要根据你的数据来调。如果你的图库主要是黑白图或者灰度图那 H 通道基本没信息权重就得降下来。注意OpenCV 读进来的图默认是 BGR 格式转 HSV 之前要先转成 RGB否则色调会偏。这个坑我踩过转出来的直方图完全不对排查了半天才发现是通道顺序问题。3.2 纹理特征灰度共生矩阵的计算与归一化纹理特征用的是灰度共生矩阵GLCM。它的思路是统计图像里成对像素的灰度组合出现的频率。比如规定一个方向和距离统计有多少对像素满足“左边是灰度 i右边距离 d 处是灰度 j”把所有 (i, j) 组合的频次排成一个矩阵就是 GLCM。GLCM 本身维度很高如果灰度级是 256矩阵就是 256x256不能直接当特征用要从里面算统计量。PyImgSearch 里用了四个对比度contrast、相关性correlation、能量energy、同质性homogeneity。对比度反映纹理的清晰程度相关性反映纹理的方向性能量反映纹理的均匀程度同质性反映纹理的局部平滑程度。这四个量组合起来能比较好地描述纹理的整体特性。计算 GLCM 之前有个关键步骤降灰度级。原始图是 256 级灰度直接算 GLCM 矩阵太大而且很多灰度级出现次数极少统计不可靠。通常会把灰度降到 8 级或 16 级这样矩阵变成 8x8 或 16x16统计量也更稳。降灰度级的方法可以是均匀量化也可以用自适应量化均匀量化简单够用。方向和距离也要选。通常会在 0°、45°、90°、135° 四个方向上各算一次 GLCM然后把四个方向的统计量取平均或者拼起来。距离一般取 1 到 3 个像素。方向越多、距离越大计算量越大但描述能力也越强。实际用的时候四个方向、距离 1 是个不错的起点。3.3 特征融合与归一化的具体做法多种特征拼在一起的时候归一化是必须的。我一般用 z-score 归一化对每个特征维度减去均值再除以标准差。这样每个维度的数值都变成均值 0、方差 1距离计算的时候各维度贡献均衡。但 z-score 有个前提均值和标准差要从整个图库的特征里算而不是单张图。所以流程是先把所有图的特征提出来存成一个矩阵然后按列算均值和标准差再用这个统计量去归一化每一张图的特征。查询图来的时候也要用同样的均值和标准差来归一化不能重新算。这个细节很容易忽略如果查询图单独归一化它和图库的归一化标准不一致距离算出来就是错的。归一化之后还可以做一步降维。如果特征维度太高比如几百维可以用 PCA 降到 50 到 100 维既能去噪又能加速检索。PCA 的投影矩阵也是从图库特征里学出来的查询图用同一个矩阵投影。降维会损失一些信息但通常损失的是噪声部分对检索精度影响不大甚至可能提升。4. 实操过程与核心环节实现4.1 环境准备与依赖安装先把环境搭起来。Python 版本建议 3.8 以上太老的版本有些库不支持。核心依赖是 NumPy、OpenCV、scikit-image、scikit-learn。NumPy 做矩阵运算OpenCV 读图和做颜色空间转换scikit-image 里有现成的 GLCM 实现scikit-learn 提供 PCA 和归一化工具。pip install numpy opencv-python scikit-image scikit-learn如果你要用 Faiss 做 ANN 索引再装一个pip install faiss-cpu有 GPU 的话可以装 faiss-gpu但 CPU 版在几万张图的规模下已经够快了。装完之后建议跑一下 import 测试确认没有版本冲突。OpenCV 和 scikit-image 有时候会有 NumPy 版本兼容问题遇到报错先检查 NumPy 版本。4.2 图库特征提取的完整流程假设你的图库放在./images目录下先遍历所有图片文件逐张提取特征。代码结构大概是这样import os import cv2 import numpy as np from skimage.feature import graycomatrix, graycoprops from sklearn.preprocessing import StandardScaler def extract_color_hist(img, h_bins12, s_bins4, v_bins4): hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) hist cv2.calcHist([hsv], [0, 1, 2], None, [h_bins, s_bins, v_bins], [0, 180, 0, 256, 0, 256]) hist cv2.normalize(hist, hist).flatten() return hist def extract_texture(img, levels8, distance1): gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray (gray / (256 / levels)).astype(np.uint8) glcm graycomatrix(gray, [distance], [0, np.pi/4, np.pi/2, 3*np.pi/4], levelslevels, symmetricTrue, normedTrue) contrast graycoprops(glcm, contrast).mean() correlation graycoprops(glcm, correlation).mean() energy graycoprops(glcm, energy).mean() homogeneity graycoprops(glcm, homogeneity).mean() return np.array([contrast, correlation, energy, homogeneity]) def extract_features(img_path): img cv2.imread(img_path) if img is None: return None img cv2.resize(img, (256, 256)) color_feat extract_color_hist(img) texture_feat extract_texture(img) return np.concatenate([color_feat, texture_feat])遍历图库的时候把每张图的特征存到一个列表里同时记录对应的文件路径。提完所有图之后把特征列表转成 NumPy 矩阵用 StandardScaler 做归一化再可选地做 PCA 降维。归一化和 PCA 的模型要保存下来检索的时候要用同一个。features [] paths [] for fname in os.listdir(./images): path os.path.join(./images, fname) feat extract_features(path) if feat is not None: features.append(feat) paths.append(path) features np.array(features) scaler StandardScaler() features_norm scaler.fit_transform(features) from sklearn.decomposition import PCA pca PCA(n_components100) features_pca pca.fit_transform(features_norm) np.save(features.npy, features_pca) np.save(paths.npy, np.array(paths))这里有个实操细节图片尺寸不统一的时候一定要先 resize 到固定尺寸再提特征。颜色直方图对尺寸不敏感但 GLCM 对尺寸敏感因为像素对的数量和图像大小有关。统一 resize 到 256x256 是个常见选择既保留了足够细节计算量也可控。4.3 检索接口的实现与 top-k 返回检索的时候对查询图走同样的特征提取、归一化、PCA 投影流程然后算它和图库矩阵的距离。用 NumPy 的话余弦距离可以这样算def search(query_path, features, paths, scaler, pca, top_k10): query_feat extract_features(query_path) query_feat scaler.transform(query_feat.reshape(1, -1)) query_feat pca.transform(query_feat) # 余弦相似度 query_norm query_feat / np.linalg.norm(query_feat, axis1, keepdimsTrue) features_norm features / np.linalg.norm(features, axis1, keepdimsTrue) similarities np.dot(features_norm, query_norm.T).flatten() top_indices np.argsort(similarities)[::-1][:top_k] results [(paths[i], similarities[i]) for i in top_indices] return results返回的结果是路径和相似度分数的列表按相似度从高到低排。实际用的时候可以设一个阈值相似度低于某个值的直接过滤掉避免返回一堆不相关的结果。阈值设多少要看数据我一般先跑一批查询看看分数分布再定阈值。4.4 用 Faiss 加速大规模检索图库超过十万张之后暴力检索开始变慢。这时候可以上 Faiss。Faiss 提供了多种索引类型最简单的是 IndexFlatIP内积或 IndexFlatL2欧氏距离它们本质上还是暴力检索但底层用 C 优化过比 NumPy 快不少。如果要更快可以用 IndexIVFFlat它先把向量聚类成若干簇检索的时候只在最近的几个簇里找速度能快一个数量级代价是可能漏掉一些结果。import faiss dim features.shape[1] index faiss.IndexFlatIP(dim) faiss.normalize_L2(features) index.add(features) query_feat query_feat.astype(np.float32) faiss.normalize_L2(query_feat) scores, indices index.search(query_feat, top_k)用 Faiss 的时候要注意数据类型必须是 float32NumPy 默认是 float64不转的话会报错。另外 normalize_L2 是原地操作会修改原数组如果后面还要用原特征记得先拷贝一份。5. 常见问题与排查技巧实录5.1 检索结果全是同一类图怎么办这个问题很常见尤其是图库里某个类别的图特别多的时候。比如图库里 80% 是风景图你搜一张人像返回的全是风景图因为风景图的特征在数量上占了绝对优势。解决办法有两个一是对图库做类别平衡每个类别采样相同数量的图二是引入重排序先召回较多候选再用更精细的特征筛选。还有一个可能是特征本身区分度不够。颜色直方图对“蓝天绿地”这种组合特别敏感很多风景图都有类似的颜色分布所以它们互相之间的相似度都很高。这时候可以加大纹理特征的权重或者引入边缘特征让形状信息参与进来。5.2 查询图和图库图尺寸不一致导致特征偏差前面提过 GLCM 对尺寸敏感其实颜色直方图也有影响。如果查询图是 1000x1000图库图是 256x256直方图的 bin 分布可能不一样因为大图的颜色过渡更平滑小图可能有更多极端值。统一 resize 是必须的而且 resize 的方法也要一致都用双线性插值或者都用最近邻不要混用。另外如果查询图有白边或者黑边resize 之后这些边会占据一定比例影响直方图。可以在 resize 之前先做裁剪去掉纯色边框。检测边框的方法可以是找上下左右连续同色的行和列超过一定宽度就裁掉。5.3 相似度分数普遍偏低或偏高相似度分数的绝对值其实没有太大意义关键是相对排序。但如果所有分数都集中在 0.9 以上说明特征区分度不够可能是归一化没做好或者特征维度太低。如果所有分数都在 0.3 以下可能是归一化标准不一致查询图用了不同的 scaler。排查的时候先检查查询图的特征提取流程和图库是否完全一致包括颜色空间转换、resize 尺寸、归一化参数。然后看看特征向量的模长如果查询图的模长和图库图的模长差异很大余弦距离也会受影响。最后可以可视化一下特征分布用 t-SNE 或者 PCA 降到二维看看如果所有点都挤在一起说明特征本身没有区分力。5.4 常见问题速查表问题现象可能原因排查方法解决思路检索结果全是同一类类别不平衡或特征区分度低统计图库类别分布看特征方差类别平衡采样增加纹理/形状特征权重相似度分数异常归一化不一致或尺寸不统一检查 scaler 和 resize 流程统一预处理流程保存并复用 scaler检索速度慢暴力检索或特征维度太高计时各环节耗时上 FaissPCA 降维查询图无结果特征提取失败或阈值太高检查图片是否能正常读取加异常处理降低阈值结果排序不合理距离度量不合适对比欧氏和余弦距离结果改用余弦距离加权重排序提示每次改完特征提取或归一化逻辑一定要重新提取整个图库的特征不能只更新查询部分。我见过有人只改了查询图的提取代码图库特征还是旧的结果怎么调都不对。5.5 几个我踩过的坑第一个坑是 OpenCV 的 HSV 范围。H 通道在 OpenCV 里是 0 到 180不是 0 到 360所以 calcHist 的 range 要写 [0, 180] 而不是 [0, 360]。写错了直方图会截断色调信息丢失一半。第二个坑是 GLCM 的 symmetric 参数。如果不设 symmetricTrueGLCM 不是对称矩阵统计量会偏。设了之后矩阵对称统计更稳定。normedTrue 也要设不然统计量是原始计数和图的大小有关。第三个坑是 PCA 的随机性。PCA 本身是确定性的但如果用了 randomized SVD 求解器结果会有微小差异。要保证可复现设 random_state。另外 PCA 的 n_components 不要设得太大超过样本数或者特征数会报错。第四个坑是文件路径的编码问题。图库里有中文路径的时候cv2.imread 可能读不进来。解决办法是用 np.fromfile 加 cv2.imdecode或者把路径转成英文。这个在 Windows 上尤其常见。6. 特征工程之外的优化空间6.1 用预训练模型替换手工特征PyImgSearch 的手工特征适合入门和理解流程但真要提升精度还是得上预训练模型。最简单的做法是用 ImageNet 上预训练的 ResNet 或 VGG去掉最后的分类层取倒数第二层的输出作为特征。这个特征维度通常是 512 或 4096语义信息比手工特征丰富得多。用 PyTorch 的话几行代码就能提特征import torch import torchvision.models as models import torchvision.transforms as transforms model models.resnet18(pretrainedTrue) model torch.nn.Sequential(*list(model.children())[:-1]) model.eval() transform transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) def extract_deep_feature(img_path): img Image.open(img_path).convert(RGB) img_tensor transform(img).unsqueeze(0) with torch.no_grad(): feat model(img_tensor).squeeze().numpy() return feat提完特征之后同样做归一化和 PCA 降维然后走原来的检索流程。实测下来ResNet 特征在语义检索上的效果比手工特征好一大截尤其是搜“猫”“狗”这种语义类别的时候。代价是提取速度慢很多CPU 上一张图可能要几十毫秒图库大的话建议用 GPU 批量提。6.2 引入重排序提升精度重排序的思路是先用快而粗的特征召回一批候选比如 top-100再用慢而精的特征对候选重新排序。粗特征可以是颜色直方图精特征可以是深度特征或者局部特征SIFT、ORB。这样既保证了速度又提升了精度。具体做法是维护两套特征检索的时候先用第一套召回然后用第二套算候选之间的距离加权融合两个距离得到最终排序。权重可以调比如粗特征占 0.3精特征占 0.7。融合之前两套距离都要归一化到 0 到 1 之间否则量纲不一致。6.3 增量索引与图库更新实际系统里图库是不断更新的不能每次都重新提全部特征。增量索引的做法是新图来了单独提特征、归一化、PCA 投影然后追加到特征矩阵和路径列表里。归一化和 PCA 的模型保持不变不要重新 fit否则旧特征和新特征不在同一个空间里。如果图库更新频繁可以考虑定期重建索引比如每周重新 fit 一次 scaler 和 PCA然后全量重提特征。重建期间可以用旧索引继续服务重建完再切换。这个策略在工程上比较稳妥避免了增量更新带来的空间漂移问题。7. 一些实际应用中的体会PyImgSearch 这个项目最大的价值不在于它的代码有多复杂而在于它把图像检索的完整链路摊开给你看。特征提取、归一化、索引、距离度量、排序每一步都有讲究每一步的参数选择都会影响最终效果。我一开始觉得传统特征太简陋但实际调优下来发现只要参数设得合理在特定场景下它完全能打。比如做商品去重的时候颜色直方图加纹理特征就能搞定大部分同款识别因为同款商品的颜色和材质纹理通常很接近。反倒是深度特征有时候会把不同颜色的同款商品判为相似因为语义上它们都是“同一类商品”但业务上我们要求颜色也必须一致。所以特征的选择最终还是要回到业务需求上没有绝对的好坏。另外一点体会是检索系统的评估很重要。不能只看几个 case 觉得效果好就上线要构造一个标注集算 precisionk、recallk、mAP 这些指标。我一般会随机抽 100 张查询图人工标注每张图的真实相似图然后跑检索算指标。有了量化指标调参才有方向不然就是瞎调。最后分享一个小技巧如果图库里有大量重复图或者近似重复图先做一轮去重再建索引能显著提升检索结果的多样性。去重可以用简单的哈希也可以用特征距离加阈值。去完之后图库更干净检索的时候也不会返回一堆几乎一样的图占满 top-k。这个预处理步骤在很多教程里都不提但实际用的时候能省不少事。

相关新闻

OpenRig:企业级 Node.js CLI 工具链元框架

OpenRig:企业级 Node.js CLI 工具链元框架

1. OpenRig 是什么?它不是“矿工软件”,而是被严重误读的 Node.js 工程化 CLI 工具链OpenRig 这个名字,最近在技术社区里频繁出现,但绝大多数人点进去第一反应是:“这不就是挖矿工具?”——错。这是一个典型…

2026/10/14 14:14:25 阅读更多 →
JAVA漫画推文AI系统源码:多端部署与变现全解析

JAVA漫画推文AI系统源码:多端部署与变现全解析

这两年漫画推文赛道是真的火,很多人盯上了这个方向,想在漫画推文项目上一展身手。而围绕这个赛道,最核心的"JAVA漫画推文AI漫画系统源码支持小程序+公众号+APP+H5"这类项目,我前前后后…

2026/10/14 14:14:25 阅读更多 →
PPO近端策略优化实战:从策略梯度到Clip裁剪与GAE的完整实现

PPO近端策略优化实战:从策略梯度到Clip裁剪与GAE的完整实现

1. 从策略梯度到 PPO:为什么我们需要一个“克制”的更新规则如果你跟着这个系列一路走到第七篇,说明你已经啃下了强化学习里最硬的那几块骨头——从最基础的价值迭代、策略迭代,到 Q-Learning、DQN,再到策略梯度那一套 REINFORCE …

2026/10/14 14:14:25 阅读更多 →

最新新闻

工业机器人坐标系全解析:从原理到标定实操

工业机器人坐标系全解析:从原理到标定实操

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

2026/10/15 1:36:03 阅读更多 →
Bugzilla部署报错couldn‘t create child process: 720002: index.cgi排查指南

Bugzilla部署报错couldn‘t create child process: 720002: index.cgi排查指南

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

2026/10/15 1:36:03 阅读更多 →
Matplotlib图例完全指南:legend()参数、位置与样式全解析

Matplotlib图例完全指南:legend()参数、位置与样式全解析

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

2026/10/15 1:36:03 阅读更多 →
单片机C运行时libspace:启动流程、多任务栈与中断安全实战

单片机C运行时libspace:启动流程、多任务栈与中断安全实战

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

2026/10/15 1:36:03 阅读更多 →
Spring BeanDefinitionRegistryPostProcessor底层注册机制详解

Spring BeanDefinitionRegistryPostProcessor底层注册机制详解

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

2026/10/15 1:36:03 阅读更多 →
CS5211单芯片eDP转LVDS方案:工业显示兼容性落地实践

CS5211单芯片eDP转LVDS方案:工业显示兼容性落地实践

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

2026/10/15 1:35:03 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/15 0:14:36 阅读更多 →
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/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →