引导滤波code
文章目录
- 1. 原理概述
- 2. 实验环节
- 2.1 验证与opencv 库函数的结果一致
- 2.2 与 双边滤波比较
- 2.3 引导滤波应用,fathering
- 2.3 引导滤波应用,图像增强
- 2.4 灰度图引导,和各自通道引导的效果差异
- 2.5 不同参数设置影响
- 3. 参考
引导滤波
1. 原理概述
引导滤波是三大保边平滑算法之一。
原理介绍参考 图像处理基础(一)引导滤波
2. 实验环节
2.1 验证与opencv 库函数的结果一致
- 引导图是单通道时的函数guided_filter(I,p,win_size,eps)
- 引导图时三通道时的函数multi_dim_guide_filter(I, p, r, eps)
- I, p的输入如果归一化 0-1之间,则eps设置为小于1的数,比如0.2,
如果没有归一化,则 eps 需要乘以 (255 * 255) - I, p应该是浮点数
- cv2.ximgproc.guidedFilter 的输入参数r是 window_size // 2
实验图像
guided_filter 和multi_dim_guide_filter 代码:
import cv2
import numpy as np
from matplotlib import pyplot as pltdef guided_filter(I,p,win_size,eps):'''% - guidance image: I (should be a gray-scale/single channel image)% - filtering input image: p (should be a gray-scale/single channel image)% - local window radius: r% - regularization parameter: eps'''mean_I = cv2.blur(I,(win_size,win_size))mean_p = cv2.blur(p,(win_size,win_size))mean_II = cv2.blur(I*I,(win_size,win_size))mean_Ip = cv2.blur(I*p,(win_size,win_size))var_I = mean_II - mean_I*mean_Icov_Ip = mean_Ip - mean_I*mean_p#print(np.allclose(var_I, cov_Ip))a = cov_Ip/(var_I+eps)b = mean_p-a*mean_Imean_a = cv2.blur(a,(win_size,win_size))mean_b = cv2.blur(b,(win_size,win_size))q = mean_a*I + mean_b#print(mean_II.dtype, cov_Ip.dtype, b.dtype, mean_a.dtype, I.dtype, q.dtype)return qdef multi_dim_guide_filter(I, p, r, eps):"""I 是三通道p 是单通道或者多通道图像"""out = np.zeros_like(p)if len(p.shape) == 2:out = multi_dim_guide_filter_single(I, p, r, eps)else:for c in range(p.shape[2]):out[..., c] = multi_dim_guide_filter_single(I, p[..., c], r, eps)return outdef multi_dim_guide_filter_single(I, p, r, eps):"""I : 导向图,多个通道 H, W, Cp : 单个通道 H, W, 1radius : 均值滤波核长度eps:"""# if len(p.shape) == 2:# p = p[..., None]r = (r, r)mean_I_r = cv2.blur(I[..., 0], r);mean_I_g = cv2.blur(I[..., 1], r);mean_I_b = cv2.blur(I[..., 2], r);# variance of I in each local patch: the matrix Sigma in Eqn(14).# Note the variance in each local patch is a 3x3 symmetric matrix:# rr, rg, rb# Sigma = rg, gg, gb# rb, gb, bbvar_I_rr = cv2.blur(I[..., 0] * (I[..., 0]), r) - mean_I_r * (mean_I_r) + epsvar_I_rg = cv2.blur(I[..., 0] * (I[..., 1]), r) - mean_I_r * (mean_I_g)var_I_rb = cv2.blur(I[..., 0] * (I[..., 2]), r) - mean_I_r * (mean_I_b)var_I_gg = cv2.blur(I[..., 1] * (I[..., 1]), r) - mean_I_g * (mean_I_g) + epsvar_I_gb = cv2.blur(I[..., 1] * (I[..., 2]), r) - mean_I_g * (mean_I_b)var_I_bb = cv2.blur(I[..., 2] * (I[..., 2]), r) - mean_I_b * (mean_I_b) + eps# Inverse of Sigma + eps * Iinvrr = var_I_gg * (var_I_bb) - var_I_gb * (var_I_gb)invrg = var_I_gb * (var_I_rb) - var_I_rg * (var_I_bb)invrb = var_I_rg * (var_I_gb) - var_I_gg * (var_I_rb)invgg = var_I_rr * (var_I_bb) - var_I_rb * (var_I_rb)invgb = var_I_rb * (var_I_rg) - var_I_rr * (var_I_gb)invbb = var_I_rr * (var_I_gg) - var_I_rg * (var_I_rg)covDet = invrr * (var_I_rr) + invrg * (var_I_rg) + invrb * (var_I_rb)invrr /= covDetinvrg /= covDetinvrb /= covDetinvgg /= covDetinvgb /= covDetinvbb /= covDet# process pmean_p = cv2.blur(p, r)mean_Ip_r = cv2.blur(I[..., 0] * (p), r)mean_Ip_g = cv2.blur(I[..., 1] * (p), r)mean_Ip_b = cv2.blur(I[..., 2] * (p), r)# covariance of(I, p) in each local patch.cov_Ip_r = mean_Ip_r - mean_I_r * (mean_p)cov_Ip_g = mean_Ip_g - mean_I_g * (mean_p)cov_Ip_b = mean_Ip_b - mean_I_b * (mean_p)a_r = invrr * (cov_Ip_r) + invrg * (cov_Ip_g) + invrb * (cov_Ip_b)a_g = invrg * (cov_Ip_r) + invgg * (cov_Ip_g) + invgb * (cov_Ip_b)a_b = invrb * (cov_Ip_r) + invgb * (cov_Ip_g) + invbb * (cov_Ip_b)b = mean_p - a_r * (mean_I_r) - a_g * (mean_I_g) - a_b * (mean_I_b)return (cv2.blur(a_r, r) * (I[..., 0])+ cv2.blur(a_g, r) * (I[..., 1])+ cv2.blur(a_b, r) * (I[..., 2])+ cv2.blur(b, r))
实验代码:
def compare_1_3channel(im, r, eps):"""分通道进行和一起进行,结果完全一致"""out1 = guided_filter(im, im, r, eps)out2 = np.zeros_like(out1)out2[..., 0] = guided_filter(im[..., 0], im[..., 0], r, eps)out2[..., 1] = guided_filter(im[..., 1], im[..., 1], r, eps)out2[..., 2] = guided_filter(im[..., 2], im[..., 2], r, eps)return out1, out2if __name__ == "__main__":file = r'D:\code\denoise\denoise_video\guide_filter_image\dd.png'kernel_size= 7r = kernel_size // 2eps = 0.002input = cv2.imread(file, 1)out1, out2 = compare_1_3channel(input, kernel_size, (eps * 255 * 255))cv2.imwrite(file[:-4] + 'out1.png', out1) # 这个结果错误,因为uint8 * uint8仍然赋给了uint8# out2.png, out3.png, out4.png 结果基本一致input = input.astype(np.float32) # 要转换为float类型out1, out2 = compare_1_3channel(input, kernel_size, (eps * 255 * 255))cv2.imwrite(file[:-4] + 'out2.png', out2)out1[..., 0] = cv2.ximgproc.guidedFilter(input[..., 0], input[..., 0], r, (eps * 255 * 255))out1[..., 1] = cv2.ximgproc.guidedFilter(input[..., 1][..., None], input[..., 1][..., None], 3, (eps * 255 * 255))out1[..., 2] = cv2.ximgproc.guidedFilter(input[..., 2][..., None], input[..., 2][..., None], 3, (eps * 255 * 255))print('tt : ', out1.min(), out1.max())out4 = np.clip(out1 * 1, 0, 255).astype(np.uint8)cv2.imwrite(file[:-4] + 'out4.png', out4)input = input / 255input = input.astype(np.float32)out1, out2 = compare_1_3channel(input, kernel_size, (eps)) # 注意0-1 和 0-255 在eps的差异。out3 = np.clip(out1 * 255, 0, 255).astype(np.uint8)cv2.imwrite(file[:-4] + 'out3.png', out3)# out5.png 和 out6.png结果一致,利用灰度图作为导向图, 注意半径和kernel_size的区别。guide= cv2.cvtColor(input,cv2.COLOR_BGR2GRAY)out1 = cv2.ximgproc.guidedFilter(guide, input, r, (eps))out5 = np.clip(out1 * 255, 0, 255).astype(np.uint8)cv2.imwrite(file[:-4] + 'out5.png', out5)out2[..., 0] = guided_filter(guide, input[..., 0], kernel_size, eps)out2[..., 1] = guided_filter(guide, input[..., 1], kernel_size, eps)out2[..., 2] = guided_filter(guide, input[..., 2], kernel_size, eps)out6 = np.clip(out2 * 255, 0, 255).astype(np.uint8)cv2.imwrite(file[:-4] + 'out6.png', out6)plt.figure(figsize=(9, 14))plt.subplot(231), plt.axis('off'), plt.title("guidedFilter error")plt.imshow(cv2.cvtColor(out1, cv2.COLOR_BGR2RGB))plt.subplot(232), plt.axis('off'), plt.title("cv2.guidedFilter")plt.imshow(cv2.cvtColor(out2, cv2.COLOR_BGR2RGB))plt.subplot(233), plt.axis('off'), plt.title("cv2.guidedFilter")plt.imshow(cv2.cvtColor(out3, cv2.COLOR_BGR2RGB))plt.subplot(234), plt.axis('off'), plt.title("cv2.guidedFilter")plt.imshow(cv2.cvtColor(out4, cv2.COLOR_BGR2RGB))plt.subplot(235), plt.axis('off'), plt.title("cv2.guidedFilter")plt.imshow(cv2.cvtColor(out5, cv2.COLOR_BGR2RGB))plt.subplot(236), plt.axis('off'), plt.title("cv2.guidedFilter")plt.imshow(cv2.cvtColor(out6, cv2.COLOR_BGR2RGB))plt.tight_layout()plt.show()
输出结果
2.2 与 双边滤波比较
个人感觉引导滤波更好
完整代码如下:
if __name__=='__main__':file = r'D:\code\denoise\denoise_video\guide_filter_image\dd.png'kernel_size = 7r = kernel_size // 2eps1 = 0.004/2eps2 = 0.002/4input = cv2.imread(file, 1)input = input.astype(np.float32) # 要转换为float类型out1 = guided_filter(input, input, kernel_size, eps1*255*255)out2 = cv2.bilateralFilter(input, kernel_size, eps2*255*255, eps2*255*255)out1 = np.clip(out1, 0, 255).astype(np.uint8)out2 = np.clip(out2, 0, 255).astype(np.uint8)cv2.imwrite(file[:-4] + 'guide.png', out1)cv2.imwrite(file[:-4] + 'bi.png', out2)cv2.imshow("guide", out1)cv2.imshow("bi", out2)cv2.waitKey(0)
2.3 引导滤波应用,fathering
实验图像
实验code:
'''
导向滤波的应用: fathering
'''
def run_fathering():file_I = r'D:\code\denoise\denoise_video\guide_filter_image\apply\c.png'file_mask = r'D:\code\denoise\denoise_video\guide_filter_image\apply\d.png'I = cv2.imread(file_I, 1)I_gray = cv2.cvtColor(I, cv2.COLOR_BGR2GRAY)input = cv2.imread(file_mask, 0)kernel_size = 20r = kernel_size // 2eps1 = 0.000008 / 2I = I.astype(np.float32)I_gray = I_gray.astype(np.float32)input = input.astype(np.float32) # 要转换为float类型out1 = cv2.ximgproc.guidedFilter(I, input, r, (eps1 * 255 * 255))out1 = np.clip(out1, 0, 255).astype(np.uint8)cv2.imwrite(file_mask[:-4] + 'guide.png', out1)out2 = cv2.ximgproc.guidedFilter(I_gray, input, r, (eps1 * 255 * 255))out2 = np.clip(out2, 0, 255).astype(np.uint8)cv2.imwrite(file_mask[:-4] + 'guide2.png', out2)out3 = guided_filter(I_gray, input, kernel_size, eps1 * 255 * 255)out3 = np.clip(out3, 0, 255).astype(np.uint8)cv2.imwrite(file_mask[:-4] + 'guide3.png', out3)print(I.shape, input.shape)out4 = multi_dim_guide_filter(I, input, kernel_size, eps1 * 255 * 255)out4 = np.clip(out4, 0, 255).astype(np.uint8)cv2.imwrite(file_mask[:-4] + 'guide4.png', out4)
out1 是彩色引导图,opencv库
out2 是灰度引导图,opencv库
out3 是灰度引导图,
out4 是彩色引导图
结果 out1和out4 接近一致,效果好。 out2和out3一致,效果存在问题
2.3 引导滤波应用,图像增强
图片
引导滤波结果稍好一些
实验code:
if __name__ == '__main__':file = r'D:\code\denoise\denoise_video\guide_filter_image\apply\e.png'I = cv2.imread(file, 1)I = I.astype(np.float32)p = Ikernel_size = 20r = kernel_size // 2eps1 = 0.008 / 2eps2 = 0.002 / 6out0 = cv2.bilateralFilter(p, kernel_size, eps2 * 255 * 255, eps2 * 255 * 255) # 双边滤波out1 = multi_dim_guide_filter(I, p, kernel_size, (eps1 * 255 * 255)) # 多通道guideout2 = guided_filter(I, p, kernel_size, (eps1 * 255 * 255)) # 单通道各自guideout3 = cv2.ximgproc.guidedFilter(I, p, r, (eps1 * 255 * 255)) # 多通道guideout4 = (I - out0) * 2 + out0out5 = (I - out1) * 2 + out1out6 = (I - out2) * 2 + out2out7 = (I - out3) * 2 + out3out0 = np.clip(out0, 0, 255).astype(np.uint8)out1 = np.clip(out1, 0, 255).astype(np.uint8)out2 = np.clip(out2, 0, 255).astype(np.uint8)out3 = np.clip(out3, 0, 255).astype(np.uint8) # out3 应该和 out1结果一致out4 = np.clip(out4, 0, 255).astype(np.uint8)out5 = np.clip(out5, 0, 255).astype(np.uint8)out6 = np.clip(out6, 0, 255).astype(np.uint8) #out7 = np.clip(out7, 0, 255).astype(np.uint8)cv2.imwrite(file[:-4] + '0.png', out0)cv2.imwrite(file[:-4] + '1.png', out1)cv2.imwrite(file[:-4] + '2.png', out2)cv2.imwrite(file[:-4] + '3.png', out3)cv2.imwrite(file[:-4] + '4.png', out4)cv2.imwrite(file[:-4] + '5.png', out5)cv2.imwrite(file[:-4] + '6.png', out6)cv2.imwrite(file[:-4] + '7.png', out7)
2.4 灰度图引导,和各自通道引导的效果差异
一致有个疑问,
- 分别用r,g,b引导各自通道的效果
- 利用灰度图引导各通道,比1滤波强度更大
- 利用彩色图引导
哪种效果更好呢? 实际使用的时候利用彩色图引导要相对复杂,计算量也更大。
def compare_1gray_3channel(im, r, eps):"""分通道进行和一起进行,结果完全一致"""out1 = guided_filter(im, im, r, eps)im_gray = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)out2 = np.zeros_like(out1)out2[..., 0] = guided_filter(im_gray, im[..., 0], r, eps)out2[..., 1] = guided_filter(im_gray, im[..., 1], r, eps)out2[..., 2] = guided_filter(im_gray, im[..., 2], r, eps)return out1, out2def run_compare_gray_guide():file = r'D:\code\denoise\denoise_video\guide_filter_image\compare\dd.png'kernel_size = 17r = kernel_size // 2eps1 = 0.02 / 2input = cv2.imread(file, 1)input = input.astype(np.float32) # 要转换为float类型out1, out2 = compare_1gray_3channel(input, r, (eps1 * 255 * 255))out1 = np.clip(out1, 0, 255).astype(np.uint8)out2 = np.clip(out2, 0, 255).astype(np.uint8)cv2.imwrite(file[:-4] + '1.png', out1)cv2.imwrite(file[:-4] + '2.png', out2)out3 = cv2.ximgproc.guidedFilter(I, p, r, (eps1 * 255 * 255)) # 多通道out3 = np.clip(out3, 0, 255).astype(np.uint8)cv2.imwrite(file[:-4] + '3.png', out3)
2.5 不同参数设置影响
def parameter_tuning():file = r'D:\code\denoise\denoise_video\guide_filter_image\paramter_tuning\dd.png'kernel_size = 17r = kernel_size // 2eps1 = 0.02 / 2input = cv2.imread(file, 1)input = input.astype(np.float32) # 要转换为float类型index = 0for r in np.arange(3, 21, 4):for eps in np.arange(0.000001, 0.00001, 0.000001):eps1 = eps * 255 * 255_, out2 = compare_1gray_3channel(input, r, eps1)out2 = np.clip(out2, 0, 255).astype(np.uint8)cv2.imwrite(file[:-4] + '{}.png'.format(index), out2)index += 1for eps in np.arange(0.2, 1, 0.1):eps1 = eps * 255 * 255_, out2 = compare_1gray_3channel(input, r, eps1)out2 = np.clip(out2, 0, 255).astype(np.uint8)cv2.imwrite(file[:-4] + '{}.png'.format(index), out2)index += 1
3. 参考
[1]https://zhuanlan.zhihu.com/p/438206777 有详细解释 和 C++相关代码仓库
[2]https://blog.csdn.net/huixingshao/article/details/42834939 高级图像去雾算法的快速实现, guide filter用于去雾,解释的很清楚
[3]http://giantpandacv.com/academic/传统图像/一些有趣的图像算法/OpenCV图像处理专栏六 来自何凯明博士的暗通道去雾算法(CVPR 2009最佳论文)/去雾代码
[4]https://github.com/atilimcetin/guided-filter引导滤波C++code
相关文章:

引导滤波code
文章目录1. 原理概述2. 实验环节2.1 验证与opencv 库函数的结果一致2.2 与 双边滤波比较2.3 引导滤波应用,fathering2.3 引导滤波应用,图像增强2.4 灰度图引导,和各自通道引导的效果差异2.5 不同参数设置影响3. 参考引导滤波1. 原理概述 引导…...
Leetcode.2353 设计食物评分系统
题目链接 Leetcode.2353 设计食物评分系统 Rating : 1782 题目描述 设计一个支持下述操作的食物评分系统: 修改 系统中列出的某种食物的评分。 返回系统中某一类烹饪方式下评分最高的食物。 实现 FoodRatings类: FoodRatings(String[] foo…...

C语言学习_DAY_2_变量的定义_输入与输出
高质量博主,点个关注不迷路🌸🌸🌸! 目录 I. 变量的定义 II. 变量的赋值 III. 输出 IV. 输入 I. 变量的定义 首先,我们新建一个.c文件在Dev C中,并把之前定义好的程序框架放进去。 此时我…...
mac 安装navicat
由于各种原因发布不了链接,这里记录下,保存在了阿里云里...
RocketMQ快速入门
2.1 消息生产和消费介绍使用RocketMQ可以发送普通消息、顺序消息、事务消息,顺序消息能实现有序消费,事务消息可以解决分布式事务实现数据最终一致。RocketMQ有2种常见的消费模式,分别是DefaultMQPushConsumer和DefaultMQPullConsumer模式,这…...

【虚拟仿真】Unity3D实现从浏览器拉起本地exe程序并传参数
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 最近有项目需求,从浏览器调起来本地的exe程序&…...

Intel中断体系(1)中断与异常处理
文章目录概述中断与异常中断可屏蔽中断与不可屏蔽中断(NMI)异常异常分类中断与异常向量中断描述符表中断描述符中断与异常处理中断与异常处理过程堆栈切换错误码64位模式下的中断异常处理64位中断描述符64位处理器下的堆栈切换相关参考概述 中断是现代计…...

财报解读:四季度营收超预期,优步却越来越“不务正业”了
“公司第四季度的业绩表现将是强劲的”。 公布2022年第三季度财报时,优步的高管给出了这样的预告,给资本市场打了一针“强心剂”。然而有人对此表示质疑,后疫情时代,带着新模式、新车型的全新网约车公司层出不穷,车企…...

C语言-程序环境和预处理(14.2)
目录 预处理详解 1.预定义符号 2. #define 2.1 #define定义标识符 2.2 #define 定义宏 2.3 #define 替换规则 注意事项: 2.4 #和## 2.5 带副作用的宏参数 2.6 宏和函数对比 3. #undef 4. 条件编译 4.1 单分支条件编译 4.2 多分支条件编译 4.3 判断是…...

VHDL语言基础-时序逻辑电路-计数器
目录 计数器的设计: 计数器的作用: 计数器的实现: 1、用“”函数描述: 用T触发器级联构成的串行进位的二进制加法计数器的仿真波形: 计数器的仿真: 计数器的设计: 计数是一种最简单基本的…...

MySQL数据库07——高级条件查询
前面一章介绍了基础的一个条件的查询,如果多条件,涉及到逻辑运算,and or 之类的。就是高级一点的条件查询。本章来介绍复杂的条件搜索表达式。 AND运算符 AND运算符只有当两边操作数均为True时,最后结果才为True。人们使用AND描述…...

《Terraform 101 从入门到实践》 第四章 States状态管理
《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新,书中的示例代码也是放在GitHub上,方便大家参考查看。 军书十二卷,卷卷有爷名。 为什么需要状态管理 Terraform的主要作用是管理云平台上的资源ÿ…...

数据结构之二叉树
🎈一.二叉树相关概念 1.树 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合,树结构通常用来存储逻辑关系为 "一对多" 的数据。例如: 关于树的几个重要概念&…...

上海亚商投顾:三大指数集体调整 消费板块逆市活跃
上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。市场情绪三大指数今日集体调整,沪指全天弱势震荡,创业板指盘中跌超1%。旅游、食品、乳业等大消费板块…...

【2023unity游戏制作-mango的冒险】-开始画面API制作
👨💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 收录于专栏:游戏制作 ⭐mango的冒险-开始画面制作⭐ 文章目录⭐mango的冒险-开始画面制作⭐👨&…...

【微服务】Nacos配置管理
🚩本文已收录至专栏:微服务探索之旅 👍希望您能有所收获 Nacos除了可以做配置管理,同样可以当作注册中心来使用。 了解注册中心用法点击跳转👉【微服务】Nacos注册中心 一.引入 当微服务部署的实例越来越多࿰…...

【C++】类与对象理解和学习(上)
专栏放在【C知识总结】,会持续更新,期待支持🌹类是什么?类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它(实例化后才…...

Pyqt5小案例,界面与逻辑分离的小计算器程序
直接看下最终效果: 使用技术总结 使用Designer设计界面 使用pyuic5命令导出到python文件 新建逻辑处理文件,继承pyuic5导出的文件的类,在里面编写信号与槽的处理逻辑 使用Designer设计界面 要使用Designer,安装一个Python库即…...

leaflet加载KML文件,显示图形(方法2)
第049个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中加载KML文件,将图形显示在地图上。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果; 注意如果OpenStreetMap无法加载,请加载其他来练习 文章目录 示例效果配置方式示例源代码(共66…...

Mysql 部署 MGR 集群
0. 参考文章 官方文档: MySQL :: MySQL 8.0 Reference Manual :: 18.2 Getting Started 博客: MGR 单主模式部署教程(基于 MySQL 8.0.28) - 墨天轮 (modb.pro) mysql MGR单主模式的搭建 - 墨天轮 (modb.pro) MySQL 5.7 基于…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...