💛前情提要💛
本文是传知代码平台
中的相关前沿知识与技术的分享~
接下来我们即将进入一个全新的空间,对技术有一个全新的视角~
本文所涉及所有资源均在传知代码平台可获取
以下的内容一定会让你对AI 赋能时代
有一个颠覆性的认识哦!!!
以下内容干货满满,跟上步伐吧~
📌导航小助手📌
- 💡本章重点
- 🍞一. 概述
- 🍞二. 算法原理
- 🍞三.演示效果
- 🍞四. 核心逻辑
- 🫓总结
💡本章重点
- 红外小目标检测
🍞一. 概述
红外图像在许多领域中都有所应用。例如军事领域中,经常需要通过红外成像设备对远距离的目标进行侦察和监视,如复杂背景下的无人机、导弹之类的物体。此外,航空航天领域中也需要通过红外传感器检测地面或海上的船只、车辆等等。这些需要检测的物体在红外图像中通常都是以不超过7X7像素大小的小目标呈现。在实际应用时,我们一般不需要区分这些物体的形状或纹理,而只需区分图像中是否有这些物体(有时对其检测位置及大小也有一定要求)以及时采取相应的措施,这就是红外小目标检测的应用场景。 在真实的应用场景中,这样的单帧红外图像短时间内就可能产生相当大的数量,如果人为一张张查看会耗费相当大的人力,所以一个能够自动检测出红外小目标的算法就显得相当有意义。
不同于自然图像,红外图像中的物体因为拍摄距离较远通常以小目标呈现,加之受各种因素的干扰,如环境因素(无人机可能受到雾或是云层的干扰)与设备自身因素(传感器不可避免地引入噪声)等,使得红外小目标淹没在各种复杂的背景中,检测具有相当的难度。本文复现的方法就是致力于实现高效的红外小目标检测。
本文用python复现论文Infrared Small Target Detection Based on Facet Kernel and Random Walker中提出的红外小目标检测算法。
该论文提出了一种针对红外图像中小目标检测的算法。在红外小目标检测方面优于其之前的所有传统方法并且为后续传统的红外小目标检测算法打下了良好的基础。
该方法作为非深度学习方法,基于滤波与图论的思想来对红外小目标进行检测。所以其对算力几乎没有任何要求,且性能也足够优秀。其提出的检测与分割的策略与指标为后续许多相关论文所借鉴。
从展示结果可以看出,该算法可以将红外图像中位于云层背景干扰下的微小目标精确地检测并分割出来,这是其他传统方法难以实现的。
🍞二. 算法原理
检测流程中图像的变化
1.均值滤波与次序统计滤波
2 * 2 的均值滤波用于平滑图像来降低噪声等级,为后续RandomWalker算法的使用创造一个低噪声空间,此外次序统计滤波被使用来去除一部分图像中的单点高亮噪声。假设原图像为 I,此步骤之后的图像被称为增强图像 M 对应流程中的(b)。
2.Facet Kernel滤波
图像经过Facet Kernel滤波后并通过一个自适应阈值来对图像进行初步分割。从而实现对红外图像中的小目标进行一个粗检。
其中Factet Kernel为 F,其值如下:
滤波后的图像设为 Mf ,其为图像 M与 F 卷积而成,即:
对应流程中的( c )。分割所使用的阈值为:
分割后的图像对应流程中的(d)。可以看到,这样的粗检无法避免云层中背景杂波的干扰。
3.RandomWalker算法分割
对于(d)图中的候选目标像素,依次设置为一个11 × 11邻域的中心,在对应原图的这个11 × 11的邻域内,中心像素设为目标,周围一圈设为背景,如下图所示:
目标种类标为1,背景标为2。RndomWalker算法会根据未标记像素与标记像素的灰度相似程度来自动对未标记像素进行分割。利用RandomWlaker算法进行分割并得到邻域内所有像素属于目标类的概率值,大于等于0.5的设为目标类,小于0.5的设为背景类。
至此,检测本可以结束。但本文提出了两个特异性指标来进一步优化检测与分割结果。即:
公式的意思是如果邻域内中心像素不在分割的目标区域内部即将此指标设为0,否则就设为一个概率值。这个概率值是这样获得的,将邻域内非中心像素而被分割为目标像素的那些像素所属目标类的概率值取平均作为分子,被分为背景像素的那些像素所属目标类的概率值取平均作为分母。这个指标在目标区域明显会大于背景区域。,具体来说它用于区分以下情况:
(a1)是真正的目标区域,而(a2)是背景区域,但由于中心较亮,其也存在被分为目标区域的像素。此指标的值在(a1)会远大于(a2)从而区分这两种情况,找出真正的目标区域。
这个公式的意思是,如果邻域中被分为背景区域的像素的灰度值的最大值大于等于被分为目标区域像素的平均灰度值,就将该指标设为0,否则就设为目标区域灰度值的平均值除以背景区域灰度的最大值。这个指标用于进一步去除单点高亮噪声被错误分为目标区域的情况。具体来说,单点高亮噪声所处的邻域中,这个值的计算应当为0.
作为我们所分割的目标区域的标签值,背景区域则设为0。得到与原图像尺寸相同的加权图即流程中的( e )。( c )与( e )相乘得到最终检测图(f)。
🍞三.演示效果
🍞四. 核心逻辑
def visual_attention_rw(img,k):
#FacetKernel滤波
img = img.astype(np.float64) / 255.0
# Step 2: Define the filter
h = np.array([[1, 1, 1], [1, 0, 1], [1, 1, 1]])
# Step 3: Apply the rank filter
img_1 = rank_filter(img, rank=7, footprint=h)
# Step 4: Calculate the ratio
con_idx = img / img_1
# Step 5: Create a mask
tmp = np.ones_like(img)
tmp[con_idx > 1] = 0
# Step 6: Combine the images
img = img * tmp + img_1 * (1 - tmp)
h = np.ones((2, 2)) / 4
img_filtered= convolve(img, h, mode='nearest')
img=img_filtered
im = img.copy()
L = np.array([
[-4, -1, 0, -1, -4],
[-1, 2, 3, 2, -1],
[0, 3, 4, 3, 0],
[-1, 2, 3, 2, -1],
[-4, -1, 0, -1, -4]
])
im_mirrored = mirror_matrix(im, 3)
img_dog = convolve2d(im_mirrored, L, mode='valid')
#探测
Th = np.mean(img_dog) + k * np.sqrt(np.var(img_dog))
# 创建与 img_dog 相同大小的全 1 数组
img_idx = np.ones_like(img_dog)
# 将 img_dog 中小于阈值 Th 的位置设为 0
img_idx[img_dog < Th] = 0
# 创建 out1 并将 img_dog 中小于阈值 Th 的部分设为 0
out1 = img_dog.copy()
out1[img_dog < Th] = 0
# 对 out1 进行归一化,防止除以零
out1 = out1 / (np.max(out1) + 1e-6)
patch=11
p=(patch+1)//2
im_m=mirror_matrix(im,p)
im_out = np.zeros_like(im_m)
out2 = im_out.copy()
out3 = im_out.copy()
p_idx_r, p_idx_c = np.where(img_idx == 1)
im_v = im[img_idx == 1]
I = np.argsort(-im_v)
p_idx_r = p_idx_r[I]
p_idx_c = p_idx_c[I]
FLAG = np.zeros_like(im_out)
patch_half = (patch - 1) // 2
for i in range(len(p_idx_r)):
r_pos = int(p_idx_r[i] + (patch - 1) //2)
c_pos = int(p_idx_c[i] + (patch - 1) // 2)
if FLAG[r_pos, c_pos] == 1:
continue
# 提取图像块
img = im_m[r_pos - patch_half: r_pos + patch_half + 1,c_pos - patch_half: c_pos + patch_half + 1]
X, Y = img.shape
# 计算 s1x 和 s1y
s1x = int((patch + 1) / 2)-1
s1y = int((patch + 1) / 2)-1
# 复制 img 并设置边界
img_2 = img.copy()
img_2[:, 0] = 1
img_2[:, -1] = 1
img_2[0, :] = 1
img_2[-1, :] = 1
idx = np.flatnonzero(img_2 == 1)
# 将 idx 转换为 double 类型(与 MATLAB 类型相似)
idx = idx.astype(float)
markers= np.zeros_like(img)
markers[:, 0] = 2
markers[:, -1] = 2
markers[0, :] = 2
markers[-1, :] = 2
markers[s1x,s1y]=1
mask=random_walker(img, markers,mode='bf',beta=200)
proba = random_walker(img, markers,mode='bf', return_full_prob=True,beta=200)
prob_t=proba[0,:,:]
if np.sum(mask == 1) == 1:
# 将 im_out 数组在位置 (r_pos, c_pos) 处的值设为 0
im_out[r_pos, c_pos] = 0
# 将 FLAG 数组在位置 (r_pos, c_pos) 处的值设为 1
FLAG[r_pos, c_pos] = 1
# 跳过当前循环的剩余部分,继续下一次循环
continue
mask[s1x, s1y] = 2
# 计算 prob_t 数组中对应 mask 中等于 1 的位置的均值
prob_res = np.mean(prob_t[mask == 1])
# 计算 prob_t 数组中对应 mask 中不等于 1 的位置的均值
# 并将 prob_res 除以这个均值
prob_res = prob_res / np.mean(prob_t[mask != 1])
# 将 mask 数组在位置 (s1x, s1y) 处的值重新设为 1
mask[s1x, s1y] = 1
inten_res=local(mask,img)
idx_r, idx_c = np.where(mask == 1)
patch_half = (patch - 1) // 2
for j in range(len(idx_r)):
r_idx = r_pos - patch_half + idx_r[j] - 1
c_idx = c_pos - patch_half + idx_c[j] - 1
if FLAG[r_idx, c_idx] == 1:
continue
im_out[r_idx, c_idx] = prob_res * inten_res ** 6
out2[r_idx, c_idx] = prob_res
out3[r_idx, c_idx] = inten_res ** 6
FLAG[r_idx, c_idx] = 1
out2 = out2[patch_half:-patch_half, patch_half:-patch_half]
out3 = out3[patch_half:-patch_half, patch_half:-patch_half]
out2 = out2 / (np.max(out2) + 1e-6)
out3 = out3 / (np.max(out3) + 1e-6)
im_out = im_out[patch_half:-patch_half, patch_half:-patch_half]
im_out = im_out * img_dog
im_out = im_out / (np.max(im_out) + 1e-6)
out4 = im_out
return out4
🫓总结
综上,我们基本了解了“一项全新的技术啦” 🍭 ~~
恭喜你的内功又双叒叕得到了提高!!!
感谢你们的阅读😆
后续还会继续更新💓,欢迎持续关注📌哟~
💫如果有错误❌,欢迎指正呀💫
✨如果觉得收获满满,可以点点赞👍支持一下哟~✨
【传知科技 – 了解更多新知识】