% Function :VI_CFAR_Processing
% brief :二维VI-CFAR处理函数
% modification :初始创建,新增雷达VI-CFAR功能模块;
% detail :对于均匀杂波环境,前后参考滑窗均匀且前后参考滑窗均值相同,认为前后参考滑窗是一致的,选择CA-CFAR检测器;
% 对于杂波边缘环境,当某一侧参考滑窗的参考单元分别属于两种不同功率的杂波区时,一侧参考滑窗均匀而另一侧非均匀,直接取均匀一侧作为背景杂波功率估计值,选择N/2长度的CA-CFAR检测器;
% 当两侧参考滑窗都是均匀,但均值不处于统一功率水平,选择GO-CFAR检测器,以保证杂波边缘的虚警概率;
% 当两侧参考滑窗都是非均匀,说明两侧参考滑窗可能都含有干扰目标或者存在杂波边缘的情况,选择SO-CFAR检测器,取均值较小的一侧作为背景杂波功率估计值
function VI_CFAR_Processing(fft2d_NCI, SoftCopy_thre, beamsn)
rd = fft2d_NCI(:, :, beamsn); % beamsn = 1、2分别控制宽、窄波束rd数据(256x256)
[rows, columns] = size(rd); % rows对应doppler最大Idx,columns对应range最大Idx
rd = abs(squeeze(rd)); % 取模值
% BackgroundNoise = bg(:, :, beamsn);
GuardCellsNum_Range = 2; TrainCellsNum_Range = 4; % range维单侧滑窗的的保护单元、参考单元个数
GuardCellsNum_Doppler = 2; TrainCellsNum_Doppler = 4; % doppler维单侧滑窗的的保护单元、参考单元个数
TrainAvg_Left = zeros(rows, columns); % 检测单元左侧参考单元均值
TrainAvg_Right = zeros(rows, columns); % 检测单元右侧参考单元均值
TrainSum_Left = zeros(rows, columns); % 检测单元左侧参考单元元素的和
TrainSum_Right = zeros(rows, columns); % 检测单元右侧参考单元元素的和
TrainAvg_Up = zeros(rows, columns); % 检测单元上方参考单元均值
TrainAvg_Down = zeros(rows, columns); % 检测单元下方参考单元均值
TrainSum_Up = zeros(rows, columns); % 检测单元上方参考单元元素的和
TrainSum_Down = zeros(rows, columns); % 检测单元下方参考单元元素的和
Vvi_Left = zeros(rows, columns); Vvi_Right = zeros(rows, columns); % 检测单元左右滑窗的二阶统计量,用于评估检测单元前后参考单元是否属于均匀杂波
Vvi_Up = zeros(rows, columns); Vvi_Down = zeros(rows, columns); % 检测单元上下滑窗的二阶统计量,用于评估检测单元上下参考单元是否属于均匀杂波
Vmr_LR = zeros(rows, columns); % 检测单元左右滑窗的均值比,用于评估检测单元前后参考单元均值是否相同
Vmr_UD = zeros(rows, columns); % 检测单元上下滑窗的均值比,用于评估检测单元上下参考单元均值是否相同
Kvi = 4.76; Kmr = 1.806; % 初始化判断门限,Kvi为Vvi二阶统计量的判断门限,Kmr为左右滑窗的均值比Vmr_LR的判断门限 (仿真初始门限值 Kvi = 4.76; Kmr = 1.806;)
Pfa = 10^(-5); % 虚警率
alpha = 0; % 标称因子
beta = 0.01; % 门限系数
% alpha(1,1) = Pfa.^(-1./(2*TrainCellsNum_Range)) - 1; % 基于虚警率和两侧参考单元求得标称因子
% alpha(1,1) = Pfa.^(-1./TrainCellsNum_Range) - 1; % 基于虚警率和单侧参考单元求得标称因子
T_1D = zeros(rows, columns); T_2D = zeros(rows, columns); % 检测门限
VICFAR_Results_range = zeros(rows, columns); % VI-CFAR range维结果矩阵,用于存储CFAR结果
VICFAR_Results_doppler = zeros(rows, columns); % VI-CFAR doppler维结果矩阵,用于存储CFAR结果
VICFAR_range_flag = 1; % range维画图控制位
VICFAR_doppler_flag = 1; % doppler维CFAR及画图控制位
for RangeIdx = 1:columns
if RangeIdx <= GuardCellsNum_Range + 1 % 检测单元Idx左侧没有参考单元
TrainAvg_Right(:, RangeIdx) = mean(rd(:, RangeIdx + GuardCellsNum_Range + 1 : RangeIdx + GuardCellsNum_Range + TrainCellsNum_Range), 2);
TrainAvg_Left(:, RangeIdx) = TrainAvg_Right(:, RangeIdx);
TrainSum_Right(:, RangeIdx) = sum(rd(:, RangeIdx + GuardCellsNum_Range + 1 : RangeIdx + GuardCellsNum_Range + TrainCellsNum_Range), 2);
TrainSum_Left(:, RangeIdx) = TrainSum_Right(:, RangeIdx);
Vvi_Right(:, RangeIdx) = 1 + (1/TrainCellsNum_Range).*sum(((rd(:, RangeIdx + GuardCellsNum_Range + 1 : RangeIdx + GuardCellsNum_Range + TrainCellsNum_Range) - TrainAvg_Right(:, RangeIdx)).^2)./(TrainAvg_Right(:, RangeIdx).^2), 2);
Vvi_Left(:, RangeIdx) = Vvi_Right(:, RangeIdx);
Vmr_LR(:, RangeIdx) = TrainAvg_Left(:, RangeIdx)./TrainAvg_Right(:, RangeIdx);
elseif (RangeIdx > GuardCellsNum_Range + 1) && (RangeIdx <= GuardCellsNum_Range + TrainCellsNum_Range) % 检测单元Idx左侧有参考单元,但个数<TrainCellsNum_Range
TrainAvg_Right(:, RangeIdx) = mean(rd(:, RangeIdx + GuardCellsNum_Range + 1 : RangeIdx + GuardCellsNum_Range + TrainCellsNum_Range), 2);
TrainAvg_Left(:, RangeIdx) = mean(rd(:, 1 : RangeIdx - GuardCellsNum_Range), 2);
TrainSum_Right(:, RangeIdx) = sum(rd(:, RangeIdx + GuardCellsNum_Range + 1 : RangeIdx + GuardCellsNum_Range + TrainCellsNum_Range), 2);
TrainSum_Left(:, RangeIdx) = sum(rd(:, 1 : RangeIdx - GuardCellsNum_Range), 2);
Vvi_Right(:, RangeIdx) = 1 + (1/TrainCellsNum_Range).*sum(((rd(:, RangeIdx + GuardCellsNum_Range + 1 : RangeIdx + GuardCellsNum_Range + TrainCellsNum_Range) - TrainAvg_Right(:, RangeIdx)).^2)./(TrainAvg_Right(:, RangeIdx).^2), 2);
Vvi_Left(:, RangeIdx) = 1 + (1/(RangeIdx - GuardCellsNum_Range)).*sum(((rd(:, 1 : RangeIdx - GuardCellsNum_Range) - TrainAvg_Left(:, RangeIdx)).^2)./(TrainAvg_Left(:, RangeIdx).^2), 2);
Vmr_LR(:, RangeIdx) = TrainAvg_Left(:, RangeIdx)./TrainAvg_Right(:, RangeIdx);
elseif RangeIdx >= columns - GuardCellsNum_Range % 检测单元Idx右侧没有参考单元
TrainAvg_Left(:, RangeIdx) = mean(rd(:, RangeIdx - GuardCellsNum_Range - TrainCellsNum_Range : RangeIdx - GuardCellsNum_Range - 1), 2);
TrainAvg_Right(:, RangeIdx) = TrainAvg_Left(:, RangeIdx);
TrainSum_Left(:, RangeIdx) = sum(rd(:, RangeIdx - GuardCellsNum_Range - TrainCellsNum_Range : RangeIdx - GuardCellsNum_Range - 1), 2);
TrainSum_Right(:, RangeIdx) = TrainSum_Left(:, RangeIdx);
Vvi_Left(:, RangeIdx) = 1 + (1/TrainCellsNum_Range).*sum(((rd(:, RangeIdx - GuardCellsNum_Range - TrainCellsNum_Range : RangeIdx - GuardCellsNum_Range - 1) - TrainAvg_Left(:, RangeIdx)).^2)./(TrainAvg_Left(:, RangeIdx).^2), 2);
Vvi_Right(:, RangeIdx) = Vvi_Left(:, RangeIdx);
Vmr_LR(:, RangeIdx) = TrainAvg_Left(:, RangeIdx)./TrainAvg_Right(:, RangeIdx);
elseif (RangeIdx >= columns - GuardCellsNum_Range