图像去雾C++实战:暗通道先验与导向滤波实现
简介一份基于暗通道先验与导向滤波的图像去雾算法C实现资源包面向图像处理初学者、算法研究者及需要在雾天或低能见度场景下增强图像质量的开发者。代码依托OpenCV库完整实现了暗通道提取、大气散射模型构建、透射率迭代估计、导向滤波边缘保持平滑及无雾图像恢复等核心流程其中透射率计算采用暗通道先验并配合迭代优化导向滤波可有效保持边缘细节、减少光晕伪影各模块划分清晰便于对照论文中的数学公式逐段理解工程转化细节并附有工程配置与效果样例可直接运行查看去雾前后对比。压缩包共6个文件以cpp主程序、h头文件、vcxproj工程配置及png效果图为主整体仅287KB结构精简适合用Visual Studio直接打开调试和二次开发。目前已有2893人学习下载可作为从理论到实战的图像去雾入门参考也能为后续改进算法提供基础框架。1. 图像去雾实战暗通道先验 导向滤波的C落地雾天拍出来的照片问题不只是对比度低远处的细节被灰白色吞掉近处色彩也发闷。直方图均衡在薄雾下能用但浓雾场景里要么把天空拉出噪点要么偏色越调越重。基于暗通道先验的图像去雾算法先统计无雾图像在局部块内三通道最小值趋近于零的规律再用导向滤波把块状透射率细化为跟随边缘的连续图是效果和性能都比较稳的经典方案。这份基于 OpenCV 与 C 的实现把暗通道、大气光、透射率细化、图像恢复都拆成了独立模块适合刚接触图像去雾的开发者照着跑通也适合要在视觉前处理里加入去雾能力的工程同学。我拆这份源码时最大的感受是算法流程不长但每一步的边界条件和数据类型都比论文里写得考验耐心。2. 项目骨架与技术选型CMake OpenCV 的多模块拆分2.1 技术选型为什么是 OpenCV 4.x 和 C17这个工程的核心计算是局部窗口统计暗通道要在 patchSize 大小的窗口里取三通道最小值导向滤波要在半径 radius 的邻域里求均值、方差、协方差。这些操作如果自己写双重循环不仅代码冗长而且很难跑满 CPU 缓存。OpenCV 的 erode、boxFilter、min 这些底层算子已经做了大量优化直接用它们拼算法是最省事的路径。选择 C 而不是 Python主要为了后续接入视频流或嵌入式平台。Python 版本调试快但产品化时往往还是需要一个 C 可执行文件或静态库。OpenCV 4.x 的 Mat 自带引用计数传递图像时只增加引用不会每次拷贝整个矩阵只有需要保留中间结果时才显式 clone。这个特性在透射率第二次滤波时很有用避免无谓的内存翻倍。需要先约定一个关键点OpenCV 的 imread 读出来是 BGR 三通道不是常说的 RGB。这个顺序问题在暗通道阶段影响不大因为 min 操作对通道顺序不敏感但后面单独对某个通道做除法或合并时就会踩坑我放到 4.4 专门说。2.2 目录结构与文件职责拿到源码后我第一件事看目录树整个工程结构如下dehaze/ CMakeLists.txt README.md src/ main.cpp # 命令行入口、图像读写、耗时统计 dehaze.h # Dehazer 类和 DehazeParams 参数结构体 dehaze.cpp # 暗通道、大气光、透射率、恢复实现 guided_filter.cpp # 导向滤波独立实现 guided_filter.h images/ foggy.jpg # 输入样例main.cpp 是一个很薄的口令行程序读入图像路径和输出路径构造 Dehazer 对象调用一次 enhance 方法最后打印处理耗时。这样设计的好处是后面做批量测试时只需要在 main 里加一个文件遍历循环算法代码完全不动。dehaze.h 里的 DehazeParams 结构体集中放了五个可调参数patchSize、omega、radius、eps、t0。把参数独立成结构体而不是散落在函数形参中是为了能用同一套参数跑多张图做回归测试也方便接到命令行解析。guided_filter.cpp 被单独拆出来是因为导向滤波不依赖暗通道先验以后做细节增强或深度图平滑也能复用不需要跟去雾逻辑耦合。2.3 编译配置与命令行入口CMakeLists.txt 是构建入口内容很简洁cmake_minimum_required(VERSION 3.16) project(DehazeCpp) find_package(OpenCV REQUIRED) add_executable(dehaze src/main.cpp src/dehaze.cpp src/guided_filter.cpp ) target_include_directories(dehaze PRIVATE src) target_link_libraries(dehaze PRIVATE ${OpenCV_LIBS})如果系统里通过 apt 安装了 libopencv-dev上面这段直接就能找到 OpenCV。如果 OpenCV 装在自定义路径需要在 cmake 之前指定 OpenCV_DIR例如cmake -DOpenCV_DIR/opt/opencv/lib/cmake/opencv4 .. make -j$(nproc)编译成功后运行命令是./dehaze ../images/foggy.jpg ../images/clear.jpg \ --patch-size 15 --omega 0.95 --radius 30 --eps 1e-6 --t0 0.2参数含义整理成表参数默认值控制阶段调整方向patchSize15暗通道窗口越大暗通道越平滑但小物体细节容易丢omega0.95透射率保留率越大去雾越强过大会出现过饱和radius30导向滤波半径越大透射率过渡越柔和过大会模糊景深边界eps1e-6导向滤波正则项越小边缘保持越强越大越接近均值滤波t00.2透射率下限越大天空区域越保守但留雾越多第一次编译最容易卡在 find_package 找不到 OpenCV这通常是 OpenCV_DIR 没有指到包含 OpenCVConfig.cmake 的目录而不是没装库。排查时可以先在 CMakeLists 里加一句message(STATUS ${OpenCV_DIR})确认路径再往下走。2.4 整条处理管线与数据格式约定去雾流程可以压缩成一条流水线输入图像 I → 计算暗通道 → 估计大气光 A → 估计粗透射率 t → 导向滤波细化 t → 恢复图像 J。整个过程里各阶段的数据类型完全不一样数据OpenCV 类型值域说明ICV_8UC30~255输入原图darkCV_8UC10~255暗通道图Acv::Scalar0~255每个通道一个标量tCV_32FC10~1初始透射率t_refinedCV_32FC10~1导向滤波后透射率JCV_8UC30~255去雾输出这条链路的绝大多数翻车现场都出在类型转换上。最常见的错误是把 0~255 的暗通道当成 0~1 的透射率直接用导致恢复图整体偏暗或者反过来把 CV_8U 图像和浮点标量做除法结果被截断成 0 和 255。所以建议在 dehaze.h 里就写明透射率相关变量必须用 CV_32F颜色图像统一为 BGR 的 CV_8UC3内部需要归一化时显式 convertTo绝不在原图上就地改。2.5 为什么不是双边滤波去雾早期的实现用 soft matting 细化透射率速度很慢。后来的简化做法是直接对块状透射率做双边滤波效果接近但双边滤波在边缘区域的核函数不稳定如果引导图本身有噪声平滑后的透射率容易出现纹理复制。导向滤波的核心假设是输出和引导图之间存在局部线性关系所以只需要 boxFilter 计算均值、方差、协方差再做一次除法得到系数。由于 boxFilter 可以用积分图加速radius 增大时开销不像双边滤波那样线性暴涨。这份工程选择导向滤波主要是想在保持边缘的前提下跑出足够好的性能。2.6 Dehazer 类的接口设计如果要把算法真正当工具用建议在 dehaze.h 里定义成类而不是一堆散函数struct DehazeParams { int patchSize 15; float omega 0.95f; int radius 30; float eps 1e-6f; float t0 0.2f; }; class Dehazer { public: explicit Dehazer(const DehazeParams params); cv::Mat enhance(const cv::Mat src); cv::Mat computeTransmission(const cv::Mat src); void updateAtmosphere(const cv::Mat src); private: DehazeParams params_; cv::Scalar atmosphere_ cv::Scalar(220, 220, 220); cv::Mat cachedTransmission_; };公共接口把 enhance 和 computeTransmission 分开好处是视频流场景里不需要每帧都重新算透射率缓存一份透射率后只做恢复计算性能提升非常明显。第 5 章的视频接入就依赖这个结构。3. 核心实现拆解从暗通道到透射率细化的完整链路3.1 暗通道计算用形态学腐蚀替代暴力最小值暗通道先验的统计结论是在无雾图像的每个局部小方块里总有一个通道的灰度值很低甚至趋近于零。代码里第一步就是把这个最小值取出来cv::Mat calculateDarkChannel(const cv::Mat src, int patchSize) { // src 要求是 8UC3 BGR 原图patchSize 通常取奇数 std::vectorcv::Mat bgr; cv::split(src, bgr); // 先取每个像素三通道的最小值 cv::Mat minCh cv::min(bgr[0], cv::min(bgr[1], bgr[2])); // 再用矩形结构元素做腐蚀等效于在 patchSize x patchSize 窗口内取最小值 cv::Mat kernel cv::getStructuringElement(cv::MORPH_RECT, cv::Size(patchSize, patchSize)); cv::erode(minCh, minCh, kernel); return minCh; // CV_8UC1 }逻辑说明split 后 bgr[0]、bgr[1]、bgr[2] 分别对应 B、G、R 三个通道嵌套的 min 调用先得到逐像素的三通道最小值。随后的腐蚀会让每个像素的灰度变成邻域窗口内的最小灰度和手动滑动窗口最小值完全一致。用 getStructuringElement 创建矩形核是因为暗通道定义的窗口就是矩形局部块。参数说明patchSize 控制局部块大小经验上 15 是 100 万像素图的常用值。调到 7 会保留更多细节但暗通道噪声变大调到 25 会让大气光估计更稳定但小目标容易丢。图像分辨率更大的时候可以把 patchSize 改成和短边成正比例如src.cols / 80。3.2 大气光估计暗通道最亮前千分之一像素的取舍大气光不能简单取原图最大值否则会把白车灯、反光点当成大气光。工程里的做法是找暗通道最亮的前 0.1% 像素再用这些位置在原图中的平均灰度作为 Acv::Scalar estimateAtmosphericLight(const cv::Mat src, const cv::Mat dark, double percent) { // percent 默认 0.001也就是千分之一 int total dark.rows * dark.cols; int count std::max(1, static_castint(total * percent)); cv::Mat flat dark.reshape(1, 1); // 转成 1 x N 的 CV_8U cv::Mat flatIdx; cv::sortIdx(flat, flatIdx, cv::SORT_DESCENDING | cv::SORT_EVERY_ROW); std::vectordouble sum(3, 0.0); for (int i 0; i count; i) { int idx flatIdx.atint(0, i); int y idx / dark.cols; int x idx % dark.cols; cv::Vec3b p src.atcv::Vec3b(y, x); sum[0] p[0]; sum[1] p[1]; sum[2] p[2]; } return cv::Scalar(sum[0] / count, sum[1] / count, sum[2] / count); }逻辑说明先用 reshape 把二维暗通道展平成一维sortIdx 按降序返回索引数组不会修改原数据。取前 count 个索引换算回原图坐标在原图上累加 BGR 三个通道最后取平均得到 A。参数说明percent 一般固定在 0.001。太小容易选中单个亮点太大把暗像素混进来导致 A 偏低。雾很浓的图像里前 0.1% 的像素几乎都落在天空或远雾区域所以平均值比单一最大值更稳。如果输出图像整体发蓝或发黄可以用 imshow 查看 A 的 BGR 分量判断是不是大气光被高光区域带偏了。3.3 透射率估计公式里最容易被忽略的归一化暗通道先验的透射率公式是t(x) 1 - omega * min_c( min_window( I_c(x) / A_c ) )注意除法是在每个通道内先除以对应的大气光分量再做三通道最小值和窗口最小值顺序不能反。写成代码cv::Mat estimateTransmission(const cv::Mat src, int patchSize, const cv::Scalar A, double omega) { // 把原图转换到 0~1 浮点避免整型除法 cv::Mat srcF; src.convertTo(srcF, CV_32FC3, 1.0 / 255.0); std::vectorcv::Mat channels; cv::split(srcF, channels); double aB A[0] / 255.0; double aG A[1] / 255.0; double aR A[2] / 255.0; // 每个通道除以各自大气光 cv::Mat minCh cv::min(channels[0] / aB, cv::min(channels[1] / aG, channels[2] / aR)); // 同样用腐蚀做窗口最小值 cv::Mat kernel cv::getStructuringElement(cv::MORPH_RECT, cv::Size(patchSize, patchSize)); cv::Mat darkNorm; cv::erode(minCh, darkNorm, kernel); // omega 通常取 0.95保留一点雾让画面不显得干涩 cv::Mat t 1.0 - omega * darkNorm; return t; // CV_32FC1 }逻辑说明图像三个通道分别除以 A 后取逐像素最小值再腐蚀得到局部最小值这就是公式中的最小值项。用 1 减去它再乘以 omega得到粗透射率。t 的值域大约在 1-omega 到 1 之间数值越小表示该处透射率越低、雾越浓。参数说明omega 取 0.95 是因为论文作者发现完全去雾会失去深度感保留 5% 的雾对视觉更自然。设 1.0 可以彻底去雾但天空区域很容易过曝。这里必须用浮点图存 t0~1 的小数一旦转成 CV_8U数值就变成 0 或 255后续恢复直接全错。3.4 导向滤波细化透射率边缘保持的关键粗透射率按 patchSize 方块估计直接恢复图像会在景深边缘产生一圈白边也就是常说的 halo。导向滤波用原图灰度作为引导让透射率图的边缘和原图对齐cv::Mat guidedFilter(const cv::Mat guide, const cv::Mat src, int radius, double eps) { // guide 和 src 都必须已经是 CV_32FC1值域 0~1 CV_Assert(guide.type() CV_32F src.type() CV_32F); cv::Mat meanI, meanP, meanIp, meanII; cv::boxFilter(guide, meanI, CV_32F, cv::Size(radius, radius)); cv::boxFilter(src, meanP, CV_32F, cv::Size(radius, radius)); cv::boxFilter(guide.mul(src), meanIp, CV_32F, cv::Size(radius, radius)); cv::boxFilter(guide.mul(guide), meanII, CV_32F, cv::Size(radius, radius)); cv::Mat covIp meanIp - meanI.mul(meanP); cv::Mat varI meanII - meanI.mul(meanI); cv::Mat a covIp / (varI eps); cv::Mat b meanP - a.mul(meanI); cv::Mat meanA, meanB; cv::boxFilter(a, meanA, CV_32F, cv::Size(radius, radius)); cv::boxFilter(b, meanB, CV_32F, cv::Size(radius, radius)); return meanA.mul(guide) meanB; // 滤波结果 q }调用时把原图转灰度作为引导图cv::Mat gray; cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY); gray.convertTo(gray, CV_32F, 1.0 / 255.0); cv::Mat tRefined guidedFilter(gray, t, radius, eps);逻辑说明boxFilter 分别得到引导图均值、输入均值、引导图与输入乘积均值、引导图平方均值然后算协方差和方差。线性系数 a 是协方差除以方差加正则项 epsb 是均值平面的截距。最后对 a 和 b 再做一次均值平滑输出meanA * guide meanB这个过程和论文里的 guided image filtering 完全一致。参数说明radius 建议大于 patchSize常见配置是 patchSize15、radius30。eps 越小边缘感知越强越大越接近普通均值滤波。在 0~1 图像域取 1e-6 通常够用。如果透射率图还有方块感先试着把 eps 降一半看变化而不是盲目加大 radius。3.5 图像恢复除以透射率之前的防呆处理细化后的透射率不能直接拿去恢复因为某些像素的 t 可能趋近于 0直接除会把噪声放大成彩斑。所以恢复前要加下限cv::Mat recover(const cv::Mat src, const cv::Mat t, const cv::Scalar A, double t0) { cv::Mat srcF; src.convertTo(srcF, CV_32FC3, 1.0 / 255.0); std::vectorcv::Mat srcCh; cv::split(srcF, srcCh); // 限制最小透射率防止接近 0 的除法放大噪声 cv::Mat tClamped cv::max(t, t0); std::vectorcv::Mat outCh(3); double a[3] { A[0] / 255.0, A[1] / 255.0, A[2] / 255.0 }; for (int c 0; c 3; c) { outCh[c] (srcCh[c] - a[c]) / tClamped a[c]; } cv::Mat outF; cv::merge(outCh, outF); outF * 255.0; outF.convertTo(outF, CV_8UC3); return outF; }逻辑说明tClamped 取 t 和 t0 的逐元素最大值保证分母最小为 t0这里 t00.2。对每个通道先减大气光再除以透射率最后加大气光等于把雾的散射项分离出去得到场景辐射估计。merge 把三通道合回去乘 255 后转换回 8UconvertTo 会自动饱和到 0~255。参数说明t0 在 0.1~0.3 之间。太小会让天空出现噪点太大则去雾不彻底远处仍蒙一层灰。如果场景里基本没有天空可以降到 0.1如果画面大面积是天空建议从 0.25 起步。4. 踩坑记录去雾结果发灰、白边、色偏的定位与修复在把工程搬到自己的数据集上的过程中我遇到五个高频问题每个都能从现象反推出原因。4.1 天空区域变成灰白色块噪点被放大现象去雾后的天空或白色雾区变成一片灰斑放大后还有红红绿绿的噪点像 JPEG 过度压缩。原因暗通道先验对天空区域不成立天空本身没有暗通道算法会把整片天空当成浓雾处理。粗透射率在天空处非常小恢复时除以小透射率传感器噪声被成倍放大。解决把 omega 从 0.95 降到 0.9t0 从 0.2 提高到 0.25在恢复前对透射率做一次高斯模糊cv::Mat tBlur; cv::GaussianBlur(tRefined, tBlur, cv::Size(5, 5), 0); cv::Mat tClamped cv::max(tBlur, t0);这三个操作单独看都会损失细节组合起来能明显压制天空区的灰色块。代价是深处景物的去雾力度弱一点视觉上反而更自然。4.2 物体边缘出现一圈白色光晕现象树叶、楼顶、塔尖周围有一圈白边像是边缘没对齐的抠图。原因粗透射率按 patchSize 大小的块估计块内所有像素共享同一透射率导致真实边缘两侧的透射率发生阶跃。如果导向滤波半径小于 patchSize阶跃不会被抹平白边就留下了。解决把 radius 设成 patchSize 的 2~3 倍例如 patch15 时 radius30。如果还有白边检查 boxFilter 的边界处理显式指定边界模式cv::boxFilter(input, output, CV_32F, cv::Size(radius, radius), cv::Point(-1, -1), true, cv::BORDER_REFLECT);第五个参数是 anchor第六个是 normalize最后一个指定 BORDER_REFLECT边缘表现会比默认更稳定。4.3 整图偏暗像加了一层灰色滤镜现象同一张图在参考实现里跑出来是透亮的自己工程跑出来整体压暗灰蒙蒙。原因大概率是透射率 t 用错了值域。如果从暗通道图直接执行1 - omega * dark / 255而忘了除以 255t 会整体变小恢复时暗部被过度拉升然后截断画面发灰。另一个可能是大气光 A 偏低减掉的大气光不够残留雾让整体偏灰。解决在估计完透射率后打一行自检日志double meanT cv::mean(t)[0]; std::cout mean t meanT std::endl;正常雾图的平均透射率在 0.4~0.7 之间。如果打印出 0.9 以上说明 omega 没生效或图像本身几乎无雾如果小于 0.3先查 A 是不是因为暗通道窗口太小而选到了黑色物体上。把 t 直接 imshow 出来应该能看到景深层次而不是一片黑或一片白。4.4 通道顺序导致恢复图偏色现象去雾后绿树变成品红色红墙变成青色和原图颜色完全对不上。原因OpenCV 的 imread 返回 BGRsplit 出来的 channels[0] 是 Blue。如果参考了网上用 RGB 写的源码把 channels[0] 当成 R后续 merge 顺序就错了。暗通道的 min 运算看不出来但大气光按通道求和、恢复时按通道减去 A 时B 和 R 对调就会产生全局色偏。解决统一约定所有算法函数输入输出都是 BGR在 dehaze.h 里写一行注释// 所有处理函数默认 BGR外部传入 RGB 的调用方需要自行转换如果一定要处理 RGB就在 main 里先 cvtColor 成 RGB处理完再转回 BGR中间不要再混用顺序。常见的偏色案例里A 的 BGR 分量往往是 R 明显高于 B看起来像过暖这时大概率是通道顺序翻车了。4.5 性能比预期慢sortIdx 成了瓶颈现象100 万像素图跑到 800msCPU 多核没有明显跑满。原因暗通道和导向滤波里的 boxFilter 都很快瓶颈往往在 estimateAtmosphericLight 的 sortIdx 全排序。sortIdx 是 O(N log N) 的全局排序图像越大越拖后腿而且不像 boxFilter 那样容易并行。解决如果目标是实时视频先把输入图缩到短边 640 再算透射率float scale 640.0f / std::min(src.cols, src.rows); cv::Mat small; cv::resize(src, small, cv::Size(), scale, scale, cv::INTER_AREA); cv::Mat tSmall dehazer.computeTransmission(small); cv::Mat tFull; cv::resize(tSmall, tFull, src.size(), 0, 0, cv::INTER_LINEAR);透射率是低频信息小图估计再放大基本看不出差异但排序和 boxFilter 的耗时能下降好几倍。如果还想更快大气光估计可以改用分块统计而不是全图排序这在视频流场景里更实际。5. 二次开发把单图算法改成视频实时去雾5.1 视频流接入的改造点单图函数接口要变成视频流不需要每一帧都重新估计大气光和透射率。环境光在几十帧内一般不会突变透射率变化也是渐进的。我的建议是每 30 帧重算一次透射率中间帧复用缓存只做最后的恢复计算cv::VideoCapture cap(0); Dehazer dehazer(params); int frameCount 0; while (cap.read(frame)) { if (frameCount % 30 0) { dehazer.updateAtmosphere(frame); // 重新估计 A 和 t } cv::Mat out dehazer.enhanceWithCached(frame); // 用缓存 t 恢复 cv::imshow(dehaze-live, out); frameCount; }这种策略在 1080p 下可以把速度从 10fps 拉到 25fps 左右代价是镜头快速切换场景或光照突变时会有几帧延迟暴露出旧透射率。缓解办法是在恢复前判断当前帧平均亮度与上一帧差是否超过 15%超过就强制更新。5.2 参数随分辨率自适应固定参数在小图上效果好换到 4K 图就容易失效。一个稳定做法是把 patchSize 和 radius 跟随短边缩放int shortSide std::min(src.cols, src.rows); params.patchSize std::max(7, shortSide / 80); params.radius params.patchSize * 2; params.eps 1e-6;短边 640 时 patchSize 约 8短边 1000 时约 12短边 2000 时约 25。这个线性映射虽然不是最优解但能在多数场景下避免反复调参。如果你做固定摄像头建议离线跑一遍网格搜索把最好的参数写进配置文件。5.3 验证方式和回归检查改完代码不能只看一两张图顺眼。我习惯把中间结果都输出到本地四个文件放在一起对比dark.png、t.png、t_refined.png、out.png。只要暗通道里原有物体轮廓依然清晰透射率图在边缘处跟着物体走恢复图没有大片颜色失真这次改动就算通过。另外固定一个测试集记录每张图处理前后的 PSNR防止某次调参为了修天空把其他区域搞崩。从那以后我每次改去雾算法都会强制走一遍中间量导出再谈参数学玄学至少不再被天空块的灰白噪点带偏。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

传统行业AI落地:装修企业的多模态RAG知识库建设实录

传统行业AI落地:装修企业的多模态RAG知识库建设实录

做这个项目之前,我一度觉得"知识库"这个词跟装修行业没什么关系。直到我们公司把三百多个历史项目的合同、施工图、报价单、效果图和工艺照片翻出来盘点,才发现这家公司最值钱的资产,全都躺在一个没人能找到的角落——而它们恰恰是…

2026/10/17 4:06:00 阅读更多 →
集合论(二):从关系闭包到权限系统的工程落地

集合论(二):从关系闭包到权限系统的工程落地

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

2026/10/17 4:05:00 阅读更多 →
OpenFeign多命名空间指定目标服务:根因、方案与实战

OpenFeign多命名空间指定目标服务:根因、方案与实战

用OpenFeign做微服务调用时,最头疼的往往不是配置繁琐,而是服务明明注册得好好的,一到运行时就给你报个UnknownHostException。尤其在多命名空间场景下,同一个服务可能同时部署在好几个namespace里,OpenFeign默认只认s…

2026/10/17 4:05:00 阅读更多 →

最新新闻

AI整合安全实战:从提示词注入防御到系统级硬约束

AI整合安全实战:从提示词注入防御到系统级硬约束

直接说结论:AI整合项目里,提示词工程环节的安全策略,决定了整个系统的下限。我在多个接入大型语言模型的项目里见过同一类事故——提示注入、系统提示词被撬、训练数据被套话、输出未经校验就进了业务流程。这些问题单看都不严重,…

2026/10/17 4:43:14 阅读更多 →
多智能体编排六种模式详解:从顺序链到反思循环

多智能体编排六种模式详解:从顺序链到反思循环

做多智能体应用时间久了,你会发现真正难的从来不是单个智能体怎么写,而是多个智能体怎么协作。MAF系列写到这里是第13篇,前几篇陆续讲过工具调用、记忆管理、上下文控制,这篇集中把“智能体编排”这件事拆开聊。所谓编排&#xff…

2026/10/17 4:43:14 阅读更多 →
纯JavaScript实现RGB、HSV与十六进制颜色互转及工程实践

纯JavaScript实现RGB、HSV与十六进制颜色互转及工程实践

1. 颜色换算在真实项目里到底解决什么问题前端开发做到一定年头,你一定会碰到颜色格式打架的情况。设计师在 Figma 里给你一个#3B82F6,后端接口返回的却是rgb(59, 130, 246),而某个取色器插件复制出来的是hsv(217, 76%, 96%)。三种写法描述的…

2026/10/17 4:43:14 阅读更多 →
Android端KIMI API流式输出实战:OkHttp+Kotlin Flow实现SSE响应

Android端KIMI API流式输出实战:OkHttp+Kotlin Flow实现SSE响应

简介:本资源是一套面向Android开发者的KIMI大模型API流式响应集成实践工程,适用于需要在移动端实现低延迟、渐进式AI内容输出的中高级开发者。项目完整封装了KIMI API的异步流式调用逻辑,涵盖请求构建、SSE解析、UI线程安全更新及错误重试机制…

2026/10/17 4:43:14 阅读更多 →
malloc底层原理与动态内存管理实战指南

malloc底层原理与动态内存管理实战指南

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

2026/10/17 4:43:14 阅读更多 →
金融数据服务中台架构实战:从多源聚合到实时推送全解析

金融数据服务中台架构实战:从多源聚合到实时推送全解析

先交代下背景。我最近在负责一个代号叫financial-services的内部项目,说白了就是一套面向金融场景的数据服务中台:上游接行情源、资讯源、账户流水,下游对接移动端、Web 和量化脚本。这个项目名字看起来很简单,但真正落地的时候牵…

2026/10/17 4:42:13 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →