航拍图像车辆检测:如何排除阴影避免其被纳入最小外接矩形?
解决航拍车辆检测中阴影干扰的实用方案
嘿,这个阴影误检的问题我在做停车场智能监测时也踩过坑!结合你用scikit-image做差分检测的方案,给你几个实际可落地的思路,帮你把阴影从检测结果里排除掉:
1. 颜色空间转换分离阴影
阴影的本质是亮度降低但色度不变,这是区分它和车辆的关键。你可以把图像转换到对光照变化更鲁棒的颜色空间(比如YCrCb或HSV),然后通过通道阈值来提取阴影区域:
- YCrCb空间中,阴影的Y通道(亮度)远低于正常地面,但Cr/Cb通道(色度)和背景地面几乎一致;
- 先从空停车场图像中计算背景的Cr/Cb均值,再在差值图中筛选出「Y通道低于阈值+Cr/Cb与背景差值小」的区域,就是阴影。
示例代码(基于scikit-image):
from skimage import color, filters, morphology import numpy as np # 假设diff_image是你计算出的空停车场与有车图像的差值图(RGB格式) # 转换为YCrCb颜色空间 ycrcb_diff = color.rgb2ycrcb(diff_image) y_channel = ycrcb_diff[:, :, 0] cr_channel = ycrcb_diff[:, :, 1] cb_channel = ycrcb_diff[:, :, 2] # 从空停车场图像(background_img)提取背景的Cr/Cb均值 ycrcb_bg = color.rgb2ycrcb(background_img) bg_cr_mean = np.mean(ycrcb_bg[:, :, 1]) bg_cb_mean = np.mean(ycrcb_bg[:, :, 2]) # 生成阴影掩码:亮度低+色度接近背景 y_thresh = filters.threshold_otsu(y_channel) shadow_mask = (y_channel < y_thresh) & \ (np.abs(cr_channel - bg_cr_mean) < 25) & \ (np.abs(cb_channel - bg_cb_mean) < 25) # 从差值图中移除阴影区域 diff_no_shadow = diff_image.copy() diff_no_shadow[shadow_mask] = 0
2. 纹理特征区分车辆与阴影
车辆表面有明显的纹理(比如车窗、车身线条),而阴影区域的纹理更平滑单一。你可以用scikit-image的纹理分析工具,提取候选区域的特征后过滤掉阴影:
- 用**局部二值模式(LBP)**计算区域的纹理复杂度,阴影的LBP特征值会更集中;
- 或者用**灰度共生矩阵(GLCM)**提取对比度、能量等特征,车辆的对比度远高于阴影。
举个LBP的简单应用:
from skimage.feature import local_binary_pattern # 对差值图的灰度版计算LBP gray_diff = color.rgb2gray(diff_image) lbp = local_binary_pattern(gray_diff, P=8, R=1, method='uniform') # 计算每个区域的LBP方差,方差小的是平滑的阴影区域 # 结合区域props筛选:比如方差低于某个阈值的区域标记为阴影
3. 形态学+区域特征后处理
即使有漏网的阴影,也可以通过形态学操作和区域属性筛选来排除:
- 用
skimage.morphology.remove_small_objects()去掉面积过小的细碎阴影; - 用
skimage.measure.regionprops()计算每个候选区域的长宽比、面积、矩形度等特征,阴影通常更扁长,而车辆的长宽比更接近固定范围(比如1:2到2:1之间)。
示例:
from skimage.measure import label, regionprops from skimage.morphology import remove_small_objects # 二值化差值图(先处理掉阴影后的图) binary_diff = color.rgb2gray(diff_no_shadow) > filters.threshold_otsu(color.rgb2gray(diff_no_shadow)) # 移除小物体 binary_clean = remove_small_objects(binary_diff, min_size=500) # 阈值根据你的图像调整 # 标记区域并筛选 label_img = label(binary_clean) for region in regionprops(label_img): # 过滤长宽比不符合车辆的区域(比如阴影可能长宽比>5) if region.major_axis_length / region.minor_axis_length > 5: label_img[label_img == region.label] = 0
4. 多帧时间差分(如果有连续航拍帧)
如果你的航拍是连续帧序列,阴影的位置和形态变化很慢(甚至不变),而车辆是移动的。可以通过多帧差分的交集来过滤:
- 计算连续3-5帧的差值图,只保留在多帧中都出现的区域(车辆),排除只在单帧或少数帧出现的阴影(如果光照有变化);
- 或者取多帧差值的并集,然后排除持续存在的区域(阴影)。
这些方法可以组合使用,比如先通过颜色空间过滤大部分阴影,再用纹理+区域特征做二次筛选,基本就能解决大部分阴影干扰的问题了!
内容的提问来源于stack exchange,提问作者nipunasudha
相关产品推荐
相关产品推荐

