3分钟网页打包神器:无需代码经验,一键将网站变桌面应用
2026/7/12 17:35:44
遥感图像因成像环境复杂(传感器干扰、宇宙射线、大气抖动等),易产生针对性噪声,且需保留地物边缘、纹理等关键信息以支撑后续解译任务。本文聚焦遥感图像专用去噪算法,剔除通用图像处理算法,仅围绕遥感场景特有噪声的解决方案展开,包含专用传统算法、深度学习优化方案及可直接落地的实战代码,助力精准解决遥感数据去噪痛点。
importtorchimporttorch.nnasnnimporttorch.optimasoptimfromtorch.utils.dataimportDataset,DataLoaderimportcv2importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.model_selectionimporttrain_test_splitfromtqdmimporttqdmimportos# 设备配置device=torch.device("cuda"iftorch.cuda.is_available()else"cpu")torch.backends.cudnn.benchmark=True# 加速卷积运算classRemoteSensingDenoiseDataset(Dataset):def__init__(self,clean_img_paths,noise_level=25,num_bands=3):self.clean_img_paths=clean_img_paths self.noise_level=noise_level# 高斯噪声强度self.num_bands=num_bands# 多波段数量(如RGB、多光谱3-8波段)def__len__(self):returnlen(self.clean_img_paths)def__getitem__(self,idx):# 读取多波段遥感图像(假设为num_bands通道图像)img_path=self.clean_img_paths[idx]clean_img=cv2.imread(img_path,cv2.IMREAD_UNCHANGED)# 保留原始通道iflen(clean_img.shape)==2:# 单波段转多波段clean_img=np.stack([clean_img]*self.num_bands,axis=0)else:clean_img=clean_img.transpose(2,0,1)# (C, H, W)clean_img=clean_img/255.0# 归一化到[0,1]# 模拟遥感特有混合噪声(高斯+椒盐+条纹)H,W=clean_img.shape[1],clean_img.shape[2]# 1. 高斯噪声(各波段独立,模拟传感器噪声)gauss_noise=np.random.normal(0,self.noise_level/255.0,(self.num_bands,H,W))# 2. 椒盐噪声(模拟宇宙射线)salt_mask=np.random.choice([0,1],size=(self.num_bands,H,W),p=[0.98,0.02])# 2%盐噪声pepper_mask=np.random.choice([0,1],size=(self.num_bands,H,W),p=[0.98,0.02])# 2%椒噪声salt_pepper_noise=np.zeros_like(clean_img)salt_pepper_noise[salt_mask==1]=1.0salt_pepper_noise[pepper_mask==1]=0.0# 3. 条纹噪声(模拟电路干扰,沿水平方向)stripe_noise=np.zeros((self.num_bands,H,W))stripe_freq=np.random.choice([5,10,15])# 条纹频率forcinrange(self.num_bands):stripe_noise[c]=0.05*np.sin(2*np.pi*np.arange(W)/stripe_freq)stripe_noise[c]=np.tile(stripe_noise[c],(H,1))# 叠加噪声noisy_img=clean_img+gauss_noise+salt_pepper_noise+stripe_noise noisy_img=np.clip(noisy_img,0,1)# 转换为Tensorclean_img=torch.from_numpy(clean_img).float()noisy_img=torch.from_numpy(noisy_img).float()returnnoisy_img,clean_img# 数据集路径配置(替换为你的遥感图像路径)clean_img_paths=["./rs_data/"+fforfinos.listdir("./rs_data/")iff.endswith((".png",".tif"))]train_paths,val_paths=train_test_split(clean_img_paths,test_size=0.2,random_state=42)# 数据加载器train_dataset=RemoteSensingDenoiseDataset(train_paths,noise_level=25,num_bands=3)val_dataset=RemoteSensingDenoiseDataset(val_paths,noise_level=25,num_bands=3)train_loader=DataLoader(train_dataset,batch_size=16,shuffle=True,num_workers=4)val_loader=DataLoader(val_dataset,batch_size=16,shuffle=False,num_workers=4)classRS_DnCNN(nn.Module):def__init__(self,in_channels=3,out_channels=3,num_layers=15,num_filters=48,kernel_size=3):super(RS_DnCNN,self).__init__()layers=[]# 输入层(适配多波段输入)layers.append(nn.Conv2d(in_channels,num_filters,kernel_size=kernel_size,padding=1,bias=False))layers.append(nn.ReLU(inplace=True))# 中间层(含空洞卷积+BatchNorm)foriinrange(num_layers-2):ifi%3==0:# 每3层插入空洞卷积,扩大感受野layers.append(nn.Conv2d(num_filters,num_filters,kernel_size=kernel_size,padding=2,dilation=2,bias=False))else:layers.append(nn.Conv2d(num_filters,num_filters,kernel_size=kernel_size,padding=1,bias=False))layers.append(nn.BatchNorm2d(num_filters))layers.append(nn.ReLU(inplace=True))# 输出层(预测噪声残差)layers.append(nn.Conv2d(num_filters,out_channels,kernel_size=kernel_size,padding=1,bias=False))self.model=nn.Sequential(*layers)# 权重初始化self._initialize_weights()def_initialize_weights(self):forminself.modules():ifisinstance(m,nn.Conv2d):nn.init.kaiming_normal_(m.weight,mode='fan_out',nonlinearity='relu')elifisinstance(m,nn.BatchNorm2d):nn.init.constant_(m.weight,1)nn.init.constant_(m.bias,0)defforward(self,x):residual=self.model(x)returnx-residual# 含噪图像 - 噪声残差 = 纯净图像# 模型实例化model=RS_DnCNN(in_channels=3,out_channels=3,num_layers=15).to(device)# 联合损失函数(适配遥感细节保留需求)classJointLoss(nn.Module):def__init__(self):super(JointLoss,self).__init__()self.mse=nn.MSELoss()defforward(self,pred,target):# MSE损失(像素级误差)mse_loss=self.mse(pred,target)# SSIM损失(结构一致性)ssim_loss=1-self._ssim(pred,target)return0.7*mse_loss+0.3*ssim_lossdef_ssim(self,x,y):C1=(0.01*1.0)**2C2=(0.03*1.0)**2x=x.clamp(0,1)y=y.clamp(0,1)mu_x=nn.functional.avg_pool2d(x,3,1,1)mu_y=nn.functional.avg_pool2d(y,3,1,1)mu_x_sq=mu_x**2mu_y_sq=mu_y**2mu_xy=mu_x*mu_y sigma_x_sq=nn.functional.avg_pool2d(x**2,3,1,1)-mu_x_sq sigma_y_sq=nn.functional.avg_pool2d(y**2,3,1,1)-mu_y_sq sigma_xy=nn.functional.avg_pool2d(x*y,3,1,1)-mu_xy ssim_map=((2*mu_xy+C1)*(2*sigma_xy+C2))/((mu_x_sq+mu_y_sq+C1)*(sigma_x_sq+sigma_y_sq+C2))returnssim_map.mean()# 优化器与调度器criterion=JointLoss()optimizer=optim.Adam(model.parameters(),lr=1e-3,weight_decay=1e-6)scheduler=optim.lr_scheduler.ReduceLROnPlateau(optimizer,patience=3,factor=0.5,verbose=True)# 训练参数epochs=40best_val_loss=float('inf')# 训练循环forepochinrange(epochs):model.train()train_loss=0.0fornoisy_imgs,clean_imgsintqdm(train_loader,desc=f"Epoch{epoch+1}/{epochs}"):noisy_imgs,clean_imgs=noisy_imgs.to(device),clean_imgs.to(device)# 前向传播outputs=model(noisy_imgs)loss=criterion(outputs,clean_imgs)# 反向传播与优化optimizer.zero_grad()loss.backward()optimizer.step()train_loss+=loss.item()*noisy_imgs.size(0)# 验证model.eval()val_loss=0.0withtorch.no_grad():fornoisy_imgs,clean_imgsinval_loader:noisy_imgs,clean_imgs=noisy_imgs.to(device),clean_imgs.to(device)outputs=model(noisy_imgs)loss=criterion(outputs,clean_imgs)val_loss+=loss.item()*noisy_imgs.size(0)# 计算平均损失train_loss/=len(train_loader.dataset)val_loss/=len(val_loader.dataset)# 学习率调整scheduler.step(val_loss)# 保存最佳模型ifval_loss<best_val_loss:best_val_loss=val_loss torch.save(model.state_dict(),"rs_dncnn_denoise.pth")print(f"Best model saved (val loss:{best_val_loss:.6f})")print(f"Epoch{epoch+1}| Train Loss:{train_loss:.6f}| Val Loss:{val_loss:.6f}")print("Training completed!")# 加载最佳模型model.load_state_dict(torch.load("rs_dncnn_denoise.pth"))model.eval()# 测试函数(支持多波段可视化)defrs_denoise_demo(img_path,model,device,num_bands=3):# 读取测试图像img=cv2.imread(img_path,cv2.IMREAD_UNCHANGED)iflen(img.shape)==2:img=np.stack([img]*num_bands,axis=0)else:img=img.transpose(2,0,1)img=img/255.0H,W=img.shape[1],img.shape[2]# 模拟遥感混合噪声gauss_noise=np.random.normal(0,25/255.0,(num_bands,H,W))salt_mask=np.random.choice([0,1],size=(num_bands,H,W),p=[0.98,0.02])pepper_mask=np.random.choice([0,1],size=(num_bands,H,W),p=[0.98,0.02])salt_pepper_noise=np.zeros_like(img)salt_pepper_noise[salt_mask==1]=1.0salt_pepper_noise[pepper_mask==1]=0.0stripe_noise=np.zeros((num_bands,H,W))stripe_freq=10forcinrange(num_bands):stripe_noise[c]=0.05*np.sin(2*np.pi*np.arange(W)/stripe_freq)stripe_noise[c]=np.tile(stripe_noise[c],(H,1))noisy_img=img+gauss_noise+salt_pepper_noise+stripe_noise noisy_img=np.clip(noisy_img,0,1)# 模型推理noisy_tensor=torch.from_numpy(noisy_img).unsqueeze(0).float().to(device)withtorch.no_grad():denoised_tensor=model(noisy_tensor)denoised_img=denoised_tensor.squeeze().cpu().numpy()denoised_img=np.clip(denoised_img,0,1)# 转换为可视化格式(C, H, W)→(H, W, C)img_vis=img.transpose(1,2,0)noisy_img_vis=noisy_img.transpose(1,2,0)denoised_img_vis=denoised_img.transpose(1,2,0)# 计算评价指标(按波段平均)psnr_noisy=0psnr_denoised=0ssim_noisy=0ssim_denoised=0forcinrange(num_bands):psnr_noisy+=cv2.PSNR(img[c],noisy_img[c],R=1.0)psnr_denoised+=cv2.PSNR(img[c],denoised_img[c],R=1.0)ssim_noisy+=cv2.SSIM(img[c],noisy_img[c],data_range=1.0)ssim_denoised+=cv2.SSIM(img[c],denoised_img[c],data_range=1.0)psnr_noisy/=num_bands psnr_denoised/=num_bands ssim_noisy/=num_bands ssim_denoised/=num_bands# 可视化plt.figure(figsize=(18,6))plt.subplot(1,3,1)plt.imshow(img_vis)plt.title("Clean Remote Sensing Image")plt.axis("off")plt.subplot(1,3,2)plt.imshow(noisy_img_vis)plt.title(f"Noisy Image\nAvg PSNR:{psnr_noisy:.2f}, Avg SSIM:{ssim_noisy:.4f}")plt.axis("off")plt.subplot(1,3,3)plt.imshow(denoised_img_vis)plt.title(f"Denoised Image\nAvg PSNR:{psnr_denoised:.2f}, Avg SSIM:{ssim_denoised:.4f}")plt.axis("off")plt.tight_layout()plt.show()# 执行测试rs_denoise_demo("./rs_data/test_img.tif",model,device,num_bands=3)| 噪声类型 | 推荐算法 | 核心优势 | 适用场景 |
|---|---|---|---|
| 高斯+椒盐混合 | 遥感适配DnCNN | 轻量化、多波段适配 | 多光谱图像快速预处理 |
| 条纹噪声为主 | 改进型傅里叶变换去噪 | 定向抑制、无振铃效应 | 卫星电路干扰、大气抖动图像 |
| 多光谱波段差异大 | 波段注意力DnCNN | 动态调整波段权重 | 高光谱、多模态遥感数据 |
| 高分辨率+混合噪声 | Restormer-RS | 长距离特征捕捉、细节保留好 | 地形测绘、高分辨率卫星图像 |
| 细节保留优先 | 多波段自适应双边滤波 | 无训练依赖、边缘保留好 | 紧急解译、资源受限场景 |
本文聚焦遥感图像特有噪声与专用去噪需求,剔除通用算法与无关背景,系统梳理了针对混合噪声、条纹噪声、多波段差异的专用解决方案,包括改进型传统算法与深度学习模型,并提供了可直接落地的多波段适配代码。
遥感图像去噪的核心是“针对性噪声抑制+地物细节保留”,选择算法时需结合噪声类型、图像分辨率、波段数量及实时性要求。后续可进一步探索方向:一是结合遥感图像的地物先验知识(如地形、植被分布)优化模型;二是针对SAR等特殊遥感图像设计专用去噪网络;三是提升模型在极端噪声(如强宇宙射线、严重大气干扰)下的鲁棒性。