5.3_channels

本文介绍了多输入通道和多输出通道的卷积操作,包括如何处理彩色图像的卷积,1x1卷积层的计算原理,以及其在调整网络复杂度中的作用。通过实例演示了如何在实际中运用这些概念。

5.3 多输入通道和多输出通道

前面两节里我们用到的输入和输出都是二维数组,但真实数据的维度经常更高。例如,彩色图像在高和宽2个维度外还有RGB(红、绿、蓝)3个颜色通道。假设彩色图像的高和宽分别是 h h h w w w(像素),那么它可以表示为一个 3 × h × w 3\times h\times w 3×h×w的多维数组。我们将大小为3的这一维称为通道(channel)维。本节我们将介绍含多个输入通道或多个输出通道的卷积核。

5.3.1 多输入通道

当输入数据含多个通道时,我们需要构造一个输入通道数与输入数据的通道数相同的卷积核,从而能够与含多通道的输入数据做互相关运算。假设输入数据的通道数为 c i c_i ci,那么卷积核的输入通道数同样为 c i c_i ci。设卷积核窗口形状为 k h × k w k_h\times k_w kh×kw。当 c i = 1 c_i=1 ci=1时,我们知道卷积核只包含一个形状为 k h × k w k_h\times k_w kh×kw的二维数组。当 c i > 1 c_i > 1 ci>1时,我们将会为每个输入通道各分配一个形状为 k h × k w k_h\times k_w kh×kw的核数组。把这 c i c_i ci个数组在输入通道维上连结,即得到一个形状为 c i × k h × k w c_i\times k_h\times k_w ci×kh×kw的卷积核。由于输入和卷积核各有 c i c_i ci个通道,我们可以在各个通道上对输入的二维数组和卷积核的二维核数组做互相关运算,再将这 c i c_i ci个互相关运算的二维输出按通道相加,得到一个二维数组。这就是含多个通道的输入数据与多输入通道的卷积核做二维互相关运算的输出。

图5.4展示了含2个输入通道的二维互相关计算的例子。在每个通道上,二维输入数组与二维核数组做互相关运算,再按通道相加即得到输出。图5.4中阴影部分为第一个输出元素及其计算所使用的输入和核数组元素: ( 1 × 1 + 2 × 2 + 4 × 3 + 5 × 4 ) + ( 0 × 0 + 1 × 1 + 3 × 2 + 4 × 3 ) = 56 (1\times1+2\times2+4\times3+5\times4)+(0\times0+1\times1+3\times2+4\times3)=56 (1×1+2×2+4×3+5×4)+(0×0+1×1+3×2+4×3)=56

在这里插入图片描述

图5.4 含2个输入通道的互相关计算

接下来我们实现含多个输入通道的互相关运算。我们只需要对每个通道做互相关运算,然后通过add_n函数来进行累加。

import torch
from torch import nn
import sys
sys.path.append("..") 
import d2lzh_pytorch as d2l

def corr2d_multi_in(X, K):
    # 沿着X和K的第0维(通道维)分别计算再相加
    res = d2l.corr2d(X[0, :, :], K[0, :, :])
    for i in range(1, X.shape[0]):
        res += d2l.corr2d(X[i, :, :], K[i, :, :])
    return res

我们可以构造图5.4中的输入数组X、核数组K来验证互相关运算的输出。

X = torch.tensor([[[0, 1, 2], [3, 4, 5], [6, 7, 8]],
              [[1, 2, 3], [4, 5, 6], [7, 8, 9]]])
K = torch.tensor([[[0, 1], [2, 3]], [[1, 2], [3, 4]]])

corr2d_multi_in(X, K)

输出:

tensor([[ 56.,  72.],
        [104., 120.]])

5.3.2 多输出通道

当输入通道有多个时,因为我们对各个通道的结果做了累加,所以不论输入通道数是多少,输出通道数总是为1。设卷积核输入通道数和输出通道数分别为 c i c_i ci c o c_o co,高和宽分别为 k h k_h kh k w k_w kw。如果希望得到含多个通道的输出,我们可以为每个输出通道分别创建形状为 c i × k h × k w c_i\times k_h\times k_w ci×kh×kw的核数组。将它们在输出通道维上连结,卷积核的形状即 c o × c i × k h × k w c_o\times c_i\times k_h\times k_w co×ci×kh×kw。在做互相关运算时,每个输出通道上的结果由卷积核在该输出通道上的核数组与整个输入数组计算而来。

下面我们实现一个互相关运算函数来计算多个通道的输出。

def corr2d_multi_in_out(X, K):
    # 对K的第0维遍历,每次同输入X做互相关计算。所有结果使用stack函数合并在一起
    return torch.stack([corr2d_multi_in(X, k) for k in K])

我们将核数组KK+1K中每个元素加一)和K+2连结在一起来构造一个输出通道数为3的卷积核。

K = torch.stack([K, K + 1, K + 2])
K.shape # torch.Size([3, 2, 2, 2])

下面我们对输入数组X与核数组K做互相关运算。此时的输出含有3个通道。其中第一个通道的结果与之前输入数组X与多输入通道、单输出通道核的计算结果一致。

corr2d_multi_in_out(X, K)

输出:

tensor([[[ 56.,  72.],
         [104., 120.]],

        [[ 76., 100.],
         [148., 172.]],

        [[ 96., 128.],
         [192., 224.]]])

5.3.3 1 × 1 1\times 1 1×1卷积层

最后我们讨论卷积窗口形状为 1 × 1 1\times 1 1×1 k h = k w = 1 k_h=k_w=1 kh=kw=1)的多通道卷积层。我们通常称之为 1 × 1 1\times 1 1×1卷积层,并将其中的卷积运算称为 1 × 1 1\times 1 1×1卷积。因为使用了最小窗口, 1 × 1 1\times 1 1×1卷积失去了卷积层可以识别高和宽维度上相邻元素构成的模式的功能。实际上, 1 × 1 1\times 1 1×1卷积的主要计算发生在通道维上。图5.5展示了使用输入通道数为3、输出通道数为2的 1 × 1 1\times 1 1×1卷积核的互相关计算。值得注意的是,输入和输出具有相同的高和宽。输出中的每个元素来自输入中在高和宽上相同位置的元素在不同通道之间的按权重累加。假设我们将通道维当作特征维,将高和宽维度上的元素当成数据样本,那么 1 × 1 1\times 1 1×1卷积层的作用与全连接层等价

在这里插入图片描述

图5.5 1x1卷积核的互相关计算。输入和输出具有相同的高和宽

下面我们使用全连接层中的矩阵乘法来实现 1 × 1 1\times 1 1×1卷积。这里需要在矩阵乘法运算前后对数据形状做一些调整。

def corr2d_multi_in_out_1x1(X, K):
    c_i, h, w = X.shape
    c_o = K.shape[0]
    X = X.view(c_i, h * w)
    K = K.view(c_o, c_i)
    Y = torch.mm(K, X)  # 全连接层的矩阵乘法
    return Y.view(c_o, h, w)

经验证,做 1 × 1 1\times 1 1×1卷积时,以上函数与之前实现的互相关运算函数corr2d_multi_in_out等价。

X = torch.rand(3, 3, 3)
K = torch.rand(2, 3, 1, 1)

Y1 = corr2d_multi_in_out_1x1(X, K)
Y2 = corr2d_multi_in_out(X, K)

(Y1 - Y2).norm().item() < 1e-6

输出:

True

在之后的模型里我们将会看到 1 × 1 1\times 1 1×1卷积层被当作保持高和宽维度形状不变的全连接层使用。于是,我们可以通过调整网络层之间的通道数来控制模型复杂度。

小结

  • 使用多通道可以拓展卷积层的模型参数。
  • 假设将通道维当作特征维,将高和宽维度上的元素当成数据样本,那么 1 × 1 1\times 1 1×1卷积层的作用与全连接层等价。
  • 1 × 1 1\times 1 1×1卷积层通常用来调整网络层之间的通道数,并控制模型复杂度。

注:除代码外本节与原书此节基本相同,原书传送门

import torch import torch.nn as nn import torch.nn.functional as F from mmcv.ops import DeformConv2dPack class SRU(nn.Module): def __init__(self, out_channels): super(SRU, self).__init__() self.pool = nn.AdaptiveAvgPool2d(1) self.conv = nn.Conv2d(out_channels, out_channels, kernel_size=1) self.sigmoid = nn.Sigmoid() def forward(self, x): attn = self.pool(x) attn = self.conv(attn) attn = self.sigmoid(attn) return x * attn class DSC_Module(nn.Module): def __init__(self, in_channels, out_channels, kernel_size=3, deform_groups=1, dilation_rates=None, use_residual=True): super(DSC_Module, self).__init__() if dilation_rates is None: dilation_rates = [1, 2] self.use_residual = use_residual self.deform_convs = nn.ModuleList([ DeformConv2dPack( in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, padding=(kernel_size + (d_rate - 1) * (kernel_size - 1)) // 2, dilation=d_rate, deform_groups=deform_groups, bias=False ) for d_rate in dilation_rates ]) self.weight_fusion = nn.Conv2d(out_channels * len(dilation_rates), out_channels, kernel_size=1, bias=False) self.bn = nn.BatchNorm2d(out_channels) self.relu = nn.ReLU(inplace=True) self.edge_conv = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1, bias=False) self.edge_bn = nn.BatchNorm2d(out_channels) self.edge_sigmoid = nn.Sigmoid() self.res_conv = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False) if (self.use_residual and in_channels != out_channels) else None self.sru = SRU(out_channels) def forward(self, x): features = [deform_conv(x) for deform_conv in self.deform_convs] target_size = (max(f.shape[2] for f in features), max(f.shape[3] for f in features)) resized_features = [F.interpolate(f, size=target_size, mode=&#39;bilinear&#39;, align_corners=False) for f in features] x_concat = torch.cat(resized_features, dim=1) x = self.weight_fusion(x_concat) x = self.bn(x) x = self.relu(x) edge = self.edge_conv(x) edge = self.edge_bn(edge) edge = self.edge_sigmoid(edge) x = x * edge x = self.sru(x) if self.use_residual: residual = self.res_conv(x) if self.res_conv else x x = x + residual return x 为什么效果比class C3f(nn.Module): """Faster Implementation of CSP Bottleneck with 2 convolutions.""" def __init__(self, c1: int, c2: int, n: int = 1, shortcut: bool = False, g: int = 1, e: float = 0.5): """ Initialize CSP bottleneck layer with two convolutions. Args: c1 (int): Input channels. c2 (int): Output channels. n (int): Number of Bottleneck blocks. shortcut (bool): Whether to use shortcut connections. g (int): Groups for convolutions. e (float): Expansion ratio. """ super().__init__() c_ = int(c2 * e) # hidden channels self.cv1 = Conv(c1, c_, 1, 1) self.cv2 = Conv(c1, c_, 1, 1) self.cv3 = Conv((2 + n) * c_, c2, 1) # optional act=FReLU(c2) self.m = nn.ModuleList(Bottleneck(c_, c_, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n)) def forward(self, x: torch.Tensor) -> torch.Tensor: """Forward pass through C3f layer.""" y = [self.cv2(x), self.cv1(x)] y.extend(m(y[-1]) for m in self.m) return self.cv3(torch.cat(y, 1)) class C3k2(C2f): """Faster Implementation of CSP Bottleneck with 2 convolutions.""" def __init__( self, c1: int, c2: int, n: int = 1, c3k: bool = False, e: float = 0.5, g: int = 1, shortcut: bool = True ): """ Initialize C3k2 module. Args: c1 (int): Input channels. c2 (int): Output channels. n (int): Number of blocks. c3k (bool): Whether to use C3k blocks. e (float): Expansion ratio. g (int): Groups for convolutions. shortcut (bool): Whether to use shortcut connections. """ super().__init__(c1, c2, n, shortcut, g, e) self.m = nn.ModuleList( C3k(self.c, self.c, 2, shortcut, g) if c3k else Bottleneck(self.c, self.c, shortcut, g) for _ in range(n) ) class C3k(C3): """C3k is a CSP bottleneck module with customizable kernel sizes for feature extraction in neural networks.""" def __init__(self, c1: int, c2: int, n: int = 1, shortcut: bool = True, g: int = 1, e: float = 0.5, k: int = 3): """ Initialize C3k module. Args: c1 (int): Input channels. c2 (int): Output channels. n (int): Number of Bottleneck blocks. shortcut (bool): Whether to use shortcut connections. g (int): Groups for convolutions. e (float): Expansion ratio. k (int): Kernel size. """ super().__init__(c1, c2, n, shortcut, g, e) c_ = int(c2 * e) # hidden channels # self.m = nn.Sequential(*(RepBottleneck(c_, c_, shortcut, g, k=(k, k), e=1.0) for _ in range(n))) self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, k=(k, k), e=1.0) for _ in range(n))) 这个差,如何优化可以使第一个更好
10-30
我已经插入代码了啊% 多通道FMCW雷达系统仿真(高精度测距版) clear; close all; clc; %% 1. 系统参数设置(提升分辨率参数) fc = 77.0e9; % 载波频率 77 GHz B = 1.0e9; % 增大扫频带宽至1GHz(提升距离分辨率) T = 200.0e-6; % 扫频时间 200 μs Fs = 40.0e6; % 提高采样频率至40MHz c = 3e8; % 光速 num_channels = 3; % 接收通道数 num_chirps = 64; % 增加Chirp数至64(提升多普勒分辨率) lambda = c/fc; % 波长 % 性能参数计算 d_res = c/(2*B); % 距离分辨率(理论值) R_max = (c*T*Fs)/(2*B); % 最大不模糊距离 v_max = lambda/(4*T); % 最大不模糊速度 fprintf(&#39;=== 多通道FMCW雷达系统参数 ===\n&#39;); fprintf(&#39;载波频率: %.1f GHz, 波长: %.3f mm\n&#39;, fc/1e9, lambda*1e3); fprintf(&#39;扫频带宽: %.1f GHz, 扫频时间: %.1f μs\n&#39;, B/1e9, T*1e6); fprintf(&#39;通道数: %d, 每帧Chirp数: %d, 采样频率: %.1f MHz\n&#39;, num_channels, num_chirps, Fs/1e6); fprintf(&#39;距离分辨率: %.3f m, 最大不模糊距离: %.1f m\n&#39;, d_res, R_max); fprintf(&#39;最大不模糊速度: %.1f m/s\n&#39;, v_max); %% 2. 目标参数设置(含无人机微多普勒) target_params = [ 60.0 5.2 1.2 0.05; % 距离(m)、速度(m/s)、RCS、微多普勒振幅(减小微动影响) 120.0 -3.8 0.8 0.04; 210.0 0.5 0.5 0.03 ]; num_targets = size(target_params, 1); % 多径参数(弱多径设置,减少干扰) multipath_params = [ 60.5 0.2; % 多径距离略偏离真实目标,RCS降低 120.6 0.1; 210.8 0.08 ]; num_multipaths = num_targets; % 打印目标信息 fprintf(&#39;\n=== 目标设置 ===\n&#39;); for i = 1:num_targets fprintf(&#39;目标%d: 距离=%.1f m, 速度=%.1f m/s, RCS=%.1f\n&#39;, ... i, target_params(i,1), target_params(i,2), target_params(i,3)); end %% 3. 信号生成(多通道Chirp信号) t_chirp = 0:1/Fs:T-1/Fs; % 单Chirp时间向量 N = length(t_chirp); % 每Chirp采样点数 t_frame = 0:T:(num_chirps-1)*T; % 帧时间 % 发射信号(多通道,含相位偏移) slope = B/T; % 调频斜率 tx_signals = zeros(num_channels, N, num_chirps); for ch = 1:num_channels phase_offset = 2*pi*(ch-1)*0.05; % 减小通道相位差 for chirp = 1:num_chirps tx_signals(ch,:,chirp) = exp(1j*(2*pi*(fc*(t_chirp + t_frame(chirp)) + ... 0.5*slope*(t_chirp + t_frame(chirp)).^2) + phase_offset)); end end %% 4. 接收信号生成(含噪声优化) rx_signals = zeros(num_channels, N, num_chirps); for ch = 1:num_channels for chirp = 1:num_chirps rx_chirp = 0; t_current = t_chirp + t_frame(chirp); % 真实目标回波(元素级运算) for i = 1:num_targets R0 = target_params(i,1); v = target_params(i,2); rcs = target_params(i,3); v_micro = target_params(i,4); % 时变距离(含微动) R = R0 - v*t_current + v_micro*sin(2*pi*30*t_current); % 降低微动频率 % 衰减与多普勒(元素级运算) tau = 2*R/c; attenuation = rcs ./ (R .^ 2); % 修复矩阵运算错误 f_doppler = 2*(v - v_micro*30*2*pi*cos(2*pi*30*t_current))/lambda; rx_chirp = rx_chirp + attenuation .* exp(1j*(2*pi*(fc*(t_current - tau) + ... 0.5*slope*(t_current - tau).^2) + 2*pi*f_doppler.*t_current)); end % 多径回波 for i = 1:num_multipaths R_mp = multipath_params(i,1); rcs_mp = multipath_params(i,2); tau_mp = 2*R_mp/c; attenuation_mp = rcs_mp ./ (R_mp .^ 2); rx_chirp = rx_chirp + attenuation_mp .* exp(1j*(2*pi*(fc*(t_current - tau_mp) + ... 0.5*slope*(t_current - tau_mp).^2))); end rx_signals(ch,:,chirp) = rx_chirp; end end % 提高信噪比(减少噪声影响) SNR_dB = 25; % 信噪比提升至25dB rx_power = mean(abs(rx_signals(1,:,:)).^2, &#39;all&#39;); noise_power = rx_power / (10^(SNR_dB/10)); for ch = 1:num_channels noise = sqrt(noise_power/2) * (randn(1, N, num_chirps) + 1j*randn(1, N, num_chirps)); rx_signals(ch,:,:) = rx_signals(ch,:,:) + noise; end %% 5. 高精度信号处理 % 5.1 通道均衡(自适应算法) eq_weights = ones(num_channels, 1); ref_ch = 1; for ch = 2:num_channels % 基于互相关的精确均衡 corr_vals = xcorr(abs(rx_signals(ref_ch,:,1)), abs(rx_signals(ch,:,1))); [~, max_idx] = max(corr_vals); delay = max_idx - length(rx_signals(ref_ch,:,1)); rx_shifted = circshift(rx_signals(ch,:,1), delay); % 补偿时延 eq_weights(ch) = mean(rx_signals(ref_ch,:,1) ./ rx_shifted); % 幅度相位补偿 rx_signals(ch,:,:) = rx_signals(ch,:,:) .* eq_weights(ch); end % 5.2 去斜处理 if_signals = zeros(num_channels, N, num_chirps); for ch = 1:num_channels for chirp = 1:num_chirps if_signals(ch,:,chirp) = tx_signals(ch,:,chirp) .* conj(rx_signals(ch,:,chirp)); end end % 5.3 距离FFT(明确度,确保存储正确) range_fft_size = 2^nextpow2(16*N); % 大幅提高FFT点数 range_spectra = zeros(num_channels, range_fft_size, num_chirps); % 度:[通道数 × range_fft_size × Chirp数] window = chebwin(N, 60); % 切比雪夫窗(更低旁瓣) for ch = 1:num_channels for chirp = 1:num_chirps if_windowed = if_signals(ch,:,chirp) .* window; % FFT后是长度为range_fft_size的一数组,直接赋值到对应度 range_spectra(ch,:,chirp) = fft(if_windowed, range_fft_size); end end % 5.4 多普勒FFT doppler_fft_size = 2^nextpow2(4*num_chirps); doppler_axis = (-doppler_fft_size/2 : doppler_fft_size/2-1) * (lambda/(4*T*doppler_fft_size)) * doppler_fft_size; rd_spectra = zeros(num_channels, range_fft_size, doppler_fft_size); for ch = 1:num_channels for r = 1:range_fft_size chirp_data = squeeze(range_spectra(ch,r,:)); % 提取距离门的Chirp序列 chirp_padded = [chirp_data, zeros(1, doppler_fft_size - num_chirps)]; % 补零 rd_spectra(ch,r,:) = fftshift(fft(chirp_padded, doppler_fft_size)); % 多普勒FFT end end % 5.5通道相干融合 rd_spectrum = sum(rd_spectra, 1); % 相干累加(提升信噪比) rd_spectrum = squeeze(rd_spectrum); rd_mag = abs(rd_spectrum); rd_dB = 20*log10(rd_mag + eps); % 5.6 多径抑制(CFAR算法) [n_rows, n_cols] = size(rd_dB); guard_cells = 3; train_cells = 10; cfar_threshold = zeros(n_rows, n_cols); for i = 1:n_rows for j = 1:n_cols % 训练单元选择 train_idx = [max(1,j-train_cells-guard_cells):max(1,j-guard_cells-1), ... min(n_cols,j+guard_cells+1):min(n_cols,j+train_cells+guard_cells)]; if ~isempty(train_idx) noise_level = mean(rd_dB(i,train_idx)); cfar_threshold(i,j) = noise_level + 12; % 12dB检测门限 end end end rd_dB(rd_dB < cfar_threshold) = -60; % 抑制噪声和弱多径 %% 6. 高精度目标检测与参数估计 % 6.1 峰值检测(三峰值搜索) peaks = []; peak_locs = []; for i = 1:num_targets [max_val, max_idx] = max(rd_dB(:)); [r_idx, v_idx] = ind2sub(size(rd_dB), max_idx); peaks = [peaks; max_val]; peak_locs = [peak_locs; r_idx, v_idx]; rd_dB(r_idx-2:r_idx+2, v_idx-2:v_idx+2) = -60; % 标记后抑制,避免重复检测 end % 6.2 高斯拟合优化峰值位置(比抛物线插值更精确) detected_ranges = zeros(1, num_targets); detected_velocities = zeros(1, num_targets); for i = 1:num_targets r_idx = peak_locs(i,1); v_idx = peak_locs(i,2); % 提取峰值周围数据用于拟合 r_win = max(1, r_idx-2):min(length(range_axis), r_idx+2); v_win = max(1, v_idx-2):min(length(doppler_axis), v_idx+2); [R_grid, V_grid] = meshgrid(range_axis(r_win), doppler_axis(v_win)); Z = rd_dB(r_win, v_win); % 高斯拟合(最小二乘估计) X0 = [range_axis(r_idx); doppler_axis(v_idx); 1; peaks(i); -1]; % 初始值 model = @(p, x) p(4)*exp(-((x(:,1)-p(1))/p(3)).^2 - ((x(:,2)-p(2))/p(3)).^2); x_data = [R_grid(:), V_grid(:)]; y_data = Z(:); p_fit = lsqcurvefit(model, X0, x_data, y_data); detected_ranges(i) = p_fit(1); % 拟合后的距离 detected_velocities(i) = p_fit(2); % 拟合后的速度 end %% 7. 测距误差计算 true_ranges = target_params(:,1); range_errors = detected_ranges - true_ranges; % 测距误差 % 误差统计指标 mean_abs_error = mean(abs(range_errors)); % 平均绝对误差 rmse = sqrt(mean(range_errors.^2)); % 均方根误差 max_error = max(abs(range_errors)); % 最大误差 %% 8. 结果可视化 figure(&#39;Position&#39;, [100, 100, 1400, 1000]); % 8.1 距离-多普勒谱 subplot(2,2,1); imagesc(range_axis, doppler_axis, rd_dB&#39;); colormap(&#39;jet&#39;); colorbar; title(&#39;距离-多普勒谱(高精度处理后)&#39;); xlabel(&#39;距离 (m)&#39;); ylabel(&#39;速度 (m/s)&#39;); xlim([0, 250]); ylim([-8, 8]); axis xy; hold on; plot(true_ranges, target_params(:,2), &#39;go&#39;, &#39;MarkerSize&#39;, 8, &#39;LineWidth&#39;, 2); plot(detected_ranges, detected_velocities, &#39;ro&#39;, &#39;MarkerSize&#39;, 6, &#39;LineWidth&#39;, 2); legend(&#39;真实目标&#39;, &#39;检测目标&#39;); hold off; % 8.2 测距误差条形图 subplot(2,2,2); bar(range_errors); title(&#39;各目标测距误差&#39;); xlabel(&#39;目标序号&#39;); ylabel(&#39;误差 (m)&#39;); grid on; ylim([-0.05, 0.05]); xticks(1:num_targets); % 8.3 通道均衡效果 subplot(2,2,3); plot(range_axis, abs(range_spectra(1,:,1)), &#39;b-&#39;, &#39;LineWidth&#39;, 1.2); hold on; plot(range_axis, abs(range_spectra(2,:,1)), &#39;r--&#39;, &#39;LineWidth&#39;, 1.2); plot(range_axis, abs(range_spectra(2,:,1).*eq_weights(2)), &#39;g-&#39;, &#39;LineWidth&#39;, 1.2); title(&#39;通道均衡效果&#39;); xlabel(&#39;距离 (m)&#39;); ylabel(&#39;幅度&#39;); legend(&#39;通道1&#39;, &#39;通道2(均衡前)&#39;, &#39;通道2(均衡后)&#39;); xlim([0, 250]); grid on; % 8.4 目标1的距离谱细节 t1_range = true_ranges(1); t1_idx = find(range_axis >= t1_range-1 & range_axis <= t1_range+1); subplot(2,2,4); plot(range_axis(t1_idx), rd_dB(t1_idx, abs(doppler_axis - target_params(1,2)) < 0.2), &#39;b-&#39;, &#39;LineWidth&#39;, 1.5); hold on; plot(detected_ranges(1), max(rd_dB(t1_idx,:)), &#39;ro&#39;, &#39;MarkerSize&#39;, 8); plot(t1_range, max(rd_dB(t1_idx,:))-5, &#39;go&#39;, &#39;MarkerSize&#39;, 8); title(&#39;目标1距离谱细节&#39;); xlabel(&#39;距离 (m)&#39;); ylabel(&#39;幅度 (dB)&#39;); legend(&#39;距离谱&#39;, &#39;检测峰值&#39;, &#39;真实位置&#39;); grid on; %% 9. 结果输出 fprintf(&#39;\n=== 高精度测距结果 ===\n&#39;); fprintf(&#39;%-8s %-12s %-12s %-12s\n&#39;, &#39;目标&#39;, &#39;真实距离(m)&#39;, &#39;检测距离(m)&#39;, &#39;测距误差(m)&#39;); fprintf(&#39;------------------------------------------------\n&#39;); for i = 1:num_targets fprintf(&#39;目标%-6d %-12.4f %-12.4f %-12.6f\n&#39;, ... i, true_ranges(i), detected_ranges(i), range_errors(i)); end fprintf(&#39;\n=== 误差统计 ===\n&#39;); fprintf(&#39;平均绝对误差: %.6f m\n&#39;, mean_abs_error); fprintf(&#39;均方根误差(RMSE): %.6f m\n&#39;, rmse); fprintf(&#39;最大误差: %.6f m\n&#39;, max_error); fprintf(&#39;\n仿真完成!\n&#39;);
最新发布
11-02
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给算法爸爸上香

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值