How to remove this red line in my micro-doppler analysis?

Here is my main code, I look the spectograms but I only see a red strip just near to the middle bins, which I assume that it is an object with zero speed.
rFFT = fft(mDopplerAvg.*win, [],1);
rFFT = rFFT - mean(rFFT, 2);
% Obtain range bins that include a target
rangePower = mean(abs(rFFT).^2,2);
% Do not use first few bins as they would probably include DC peaks due
% to antenna leakage (can be adjusted empirically)
rangeVar = var(abs(rFFT), 0, 2);
rangeVar(1:6) = 0;
[~, targetIdx] = max(rangeVar);
slowTime = rFFT(targetIdx,:);
Here, the mDopplerAvg is the raw I/Q matrix that I process for micro-Doppler. I have applied some tricks in order that the static zero speed object (the red strip) go away. However, it didn't work. At the last of the code, the classic short time Fourier transform is applied along the second axis, and I think the size of the spectogram is well-configurated. I almost always obtain a map just like below.

5 Kommentare

William Rose
William Rose am 3 Jan. 2026
Bearbeitet: William Rose am 3 Jan. 2026
[Edit: My original request for data files was poor, because I misinterpreted a line of code. I recommend including code that is runnable by others (and data, if needed).]
please provide the data file(s), so that others can run your code.
%% Dataset_Collector.m
% Description: Captures raw radar data via DCA1000, processes it into
% Range-Doppler maps, resizes for CNN, and saves as a labeled .mat file.
clear; clc; close all;
%% --- 2. RADAR CAPTURE (DCA1000) ---
clear dca
delete(fullfile(pwd,"iqFrameDatas", "*"))
cfgFile = fullfile(pwd, "configFiles","sample.cfg");
dca = dca1000("IWR6843ISK", "ConfigFile",cfgFile);
dca.RecordDuration = 20; % Duration in seconds
dca.RecordLocation = "D:\Projects\Final_Radar\Radar_Design\fmcw_deneme\Doppler_Sign_Classification\iqFrameDatas";
disp("📡 Starting Radar Capture...");
startRecording(dca);
while isRecording(dca)
pause(0.5);
fprintf('.');
end
disp(" Capture Complete ✅");
disp("Waiting for file system synchronization...")
pause(5)
recordLocation = dca.RecordLocation;
%% --- 3. LOAD PARAMETERS ---
temp = load(fullfile(recordLocation,'iqData_RecordingParameters.mat'));
p = temp.RecordingParameters;
% Convert parameters to physical units
fs = p.ADCSampleRate * 1e3; % ADC sample rate in "samples per second"
sweepSlope = p.SweepSlope * 1e12; % chirp rate in Hz/s
fc = p.CenterFrequency * 1e9; % carrier frequency in Hz
tpulse = 2 * p.ChirpCycleTime * 1e-6; % chirp duration in secs (idle time + ramp end time)
prf = 1 / tpulse; % pulse repetition frequency in Hz
% Extract frame cube parameters
nr = p.SamplesPerChirp; % Samples in a single chirp
nc = p.NumChirps / p.NumTransmitters; % (128 x 3) / 3 , total number of chirps emitted from single Tx
numTx = p.NumTransmitters;
numRx = p.NumReceivers;
numVirtual = numTx*numRx;
%% --- 4. PROCESS & SAVE DATASET ---
% User Input: Class Label
classLabel = input("Enter Class Label (e.g., human, car): ", 's');
% Initialize Reader and DSP Range-Doppler Response Object
fr = dca1000FileReader(recordLocation = recordLocation);
numFrames = fr.NumDataCubes; % Num of frames
% --- PREPARATION ---
frameSeries = 40;
maxSamples = floor(numFrames / frameSeries);
% STFT parameters
winLen = 32;
overlap = 16;
fftlen = 128; % Allows zero padding
H = winLen - overlap;
N = frameSeries * nc;
stftRows = fftlen;
stftCols = floor((N - winLen) / H) + 1;
TARGET_SIZE = [stftRows, stftCols]; % Must match CNN Input Layer
% Pre-allocate memory for speed
% X_new is the CNN input tensor of
% range bins x doppler bins x num of channels x num of frames
% H x W x C x N (standart MATLAB Deep Learning format)
% the "num of channels" is 1 for a gray-scaled CNN input image.
X_new = zeros(TARGET_SIZE(1), TARGET_SIZE(2), 1, maxSamples, 'single');
% Labeling vector
Y_new = cell(numFrames, 1);
disp("🔄 Processing frames...");
frameIdx = 1;
fullMIMOData = zeros(nr, numVirtual, nc, numFrames);
rawRD = zeros(nr,nc,numVirtual);
win = hann(nr); % Hanning window
dopplerChain = zeros(1,nc*frameSeries);
chainStartIdx = 1;
sampleIdx = 1;
while (frameIdx <= numFrames)
% 1. Read Raw IQ Data
% radarDataCube is a complex double-precision three-dimensional array of size
% "SamplesPerChirp * NumRecievers * NumChirps".
iqData = read(fr, 1); % next position, read only one frame per iteration.
if isempty(iqData), break; end
iqData = iqData{1};
% Make use of the virtual antennas. New data format is
% "(SamplesPerChirp) * (numVirtual) * (NumChirps emitted from the Tx in the
% current visual channel)
channelIdx = 1;
for t = 1:numTx
for n = 1:numRx
temp = iqData(:,n,t:numTx:end);
fullMIMOData(:,channelIdx,:,frameIdx) = temp;
rawRD(:,:,channelIdx) = temp;
channelIdx = channelIdx + 1;
end
end
% Find the mean of obtained 12 range-doppler map. In this case, the
% azimuth information is lost, but a more stable single R-D response per
% frame is evaluated
mDopplerAvg = mean(rawRD,3);
rFFT = fft(mDopplerAvg.*win, [],1);
rFFT = rFFT - mean(rFFT, 2);
% Obtain range bins that include a target
rangePower = mean(abs(rFFT).^2,2);
% Do not use first few bins as they would probably include DC peaks due
% to antenna leakage (can be adjusted empirically)
rangeVar = var(abs(rFFT), 0, 2);
rangeVar(1:6) = 0;
[~, targetIdx] = max(rangeVar);
slowTime = rFFT(targetIdx,:);
chainEndIdx = chainStartIdx + nc - 1;
dopplerChain(:, chainStartIdx:chainEndIdx) = slowTime;
chainStartIdx = chainStartIdx + nc;
if mod(frameIdx, frameSeries) == 0
[s, f, tvec] = stft(dopplerChain,prf,"Window",hann(winLen),"OverlapLength",overlap,"FFTLength",fftlen);
mDopplerMag = abs(s);
mDopplerdB = 20*log10(mDopplerMag + eps);
% 4. Pre-processing
% Resize to match CNN input dimensions
rdMap_resized = imresize(mDopplerdB, TARGET_SIZE); %Image processing toolbox
rdMap_resized = rdMap_resized - min(rdMap_resized(:));
rdMap_resized = rdMap_resized / (max(rdMap_resized(:))+eps);
% Draw the spectogram for any frame for vizualization.
if frameIdx == 40 | frameIdx == 80
figure;
imagesc(rdMap_resized);
axis xy;
colormap jet;
colorbar;
title('Sanity Check - STFT Micro-Doppler (Frame 10)');
xlabel('Time Bins');
ylabel('Doppler Bins');
end
% 5. Store in Tensor
X_new(:, :, 1, sampleIdx) = single(rdMap_resized);
Y_new{sampleIdx} = classLabel;
dopplerChain = zeros(1,nc*frameSeries);
chainStartIdx = 1;
sampleIdx = sampleIdx + 1;
end
if mod(frameIdx, 10) == 0
fprintf('Processed Frame: %d\n', frameIdx);
end
frameIdx = frameIdx + 1;
end
% Trim unused pre-allocated space
X_new = X_new(:, :, :, 1:sampleIdx-1);
Y_new = Y_new(1:sampleIdx-1);
% Convert labels to categorical
Y_new = categorical(Y_new);
% --- SAVE FILE ---
saveFolder = "D:\Projects\Final_Radar\Radar_Design\fmcw_deneme\Doppler_Sign_Classification";
saveFileName = fullfile(saveFolder, sprintf('Dataset_%s.mat', classLabel));
save(saveFileName, 'X_new', 'Y_new');
disp("------------------------------------------------");
disp("💾 DATA SAVED SUCCESSFULLY!");
disp("File: " + saveFileName);
disp("Dimensions: " + num2str(size(X_new)));
disp("------------------------------------------------");
% This is the full format that I transfer the raw I/Q data online, and
% process them offline. I do not use any other file for now.
Thank you for your full script. When I asked for a data file in my previous comment, I misunderstood your code. That was my error.
Others cannot execute the script you provided, because they do not have your hardware. I find that I am more likely to get useful help on this site when I supply the simplest example of code (and data) that demonstrates the problem I want to solve. I encourage you to provide the minimum code and a data file needed to make a figure like the one in your original post. Before you post, use the green Run button in the Matlab Answers window, to confirm that the code you have provided is actually runnable by others.
In fact, the problem is not about the actual hardware or the data to which I transfer, but is about the method that I can use to see the micro-doppler pattern of a walking or breathing person who moves in front of the radar module TI IWR6843ISK, but not to see the static huge object as a target, causing the red area... I actually browse for a hint or method findable in the literature. Thanks for your intentions...
@Mustafa, the point is that without the data to work with, however it was acquired, and the starting point of code to process it to produce what you have, nobody is going to have a magic answer...

Melden Sie sich an, um zu kommentieren.

Antworten (1)

Dinesh
Dinesh am 9 Jan. 2026

0 Stimmen

Based on my understanding, (rFFT - mean(rFFT, 2)) doesn't remove DC fully.
Apply stronger clutter removal before STFT, consider applying high-pass filtering along the slow-time

1 Kommentar

To avoid DC component from FFT, subtract the mean from the time signal.

Melden Sie sich an, um zu kommentieren.

Gefragt:

am 3 Jan. 2026

Kommentiert:

dpb
am 9 Jan. 2026

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by