Spaces:
Running
on
Zero
Running
on
Zero
ZeroGPU optimize
Browse files- app.py +2 -2
- app_function.py +61 -74
app.py
CHANGED
@@ -130,7 +130,7 @@ with gr.Blocks(title="YOND WebUI", css="""
|
|
130 |
bl = gr.Number(label="Black Level", value=64.0, precision=1, scale=1)
|
131 |
wp = gr.Number(label="White Point", value=1023.0, precision=1, scale=1)
|
132 |
ratio = gr.Number(label="DGain (x Ratio)", value=1.0, precision=1, scale=1)
|
133 |
-
ispgain = gr.Number(label="ISPGain", value=1.0, precision=1, scale=1)
|
134 |
with gr.Row():
|
135 |
image_btn = gr.Button("Load Image", variant="primary")
|
136 |
image_update_btn = gr.Button("Update Image", variant="secondary")
|
@@ -144,7 +144,7 @@ with gr.Blocks(title="YOND WebUI", css="""
|
|
144 |
|
145 |
est_btn = gr.Button("Noise Estimation", variant="primary")
|
146 |
|
147 |
-
use_ddim = gr.Checkbox(label="DDIM Mode", value=False, scale=1)
|
148 |
with gr.Row():
|
149 |
patch_size = gr.Number(label="Patch Size", value=1024, precision=0)
|
150 |
sigsnr = gr.Number(label="SigSNR", precision=2, value=1.03)
|
|
|
130 |
bl = gr.Number(label="Black Level", value=64.0, precision=1, scale=1)
|
131 |
wp = gr.Number(label="White Point", value=1023.0, precision=1, scale=1)
|
132 |
ratio = gr.Number(label="DGain (x Ratio)", value=1.0, precision=1, scale=1)
|
133 |
+
ispgain = gr.Number(label="ISPGain (Visual Only)", value=1.0, precision=1, scale=1)
|
134 |
with gr.Row():
|
135 |
image_btn = gr.Button("Load Image", variant="primary")
|
136 |
image_update_btn = gr.Button("Update Image", variant="secondary")
|
|
|
144 |
|
145 |
est_btn = gr.Button("Noise Estimation", variant="primary")
|
146 |
|
147 |
+
use_ddim = gr.Checkbox(label="DDIM Mode (Please use large model, e.g., gru64n)", value=False, scale=1)
|
148 |
with gr.Row():
|
149 |
patch_size = gr.Number(label="Patch Size", value=1024, precision=0)
|
150 |
sigsnr = gr.Number(label="SigSNR", precision=2, value=1.03)
|
app_function.py
CHANGED
@@ -221,6 +221,40 @@ class YOND_Backend:
|
|
221 |
raise RuntimeError(f"图像更新失败: {str(e)}") from e
|
222 |
|
223 |
@spaces.GPU
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
def estimate_noise(self, double_est, ransac, patch_size):
|
225 |
"""执行噪声估计"""
|
226 |
if not self.yond:
|
@@ -246,49 +280,30 @@ class YOND_Backend:
|
|
246 |
|
247 |
if double_est:
|
248 |
log(" 使用精估计")
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
# 使用改进的 big_image_split 函数
|
275 |
-
raw_inp, metadata = big_image_split(raw_vst, target_size, overlap_ratio)
|
276 |
-
|
277 |
-
raw_dn = torch.zeros_like(raw_inp[:,:4])
|
278 |
-
with torch.no_grad():
|
279 |
-
for i in range(raw_inp.shape[0]): # 处理所有切块
|
280 |
-
input_tensor = raw_inp[i][None,].clip(None, 2).to(self.device)
|
281 |
-
raw_dn[i] = self.yond.net(input_tensor, t).clamp(0,None)
|
282 |
-
|
283 |
-
# 使用改进的 big_image_merge 函数
|
284 |
-
raw_dn = big_image_merge(raw_dn, metadata, blend_mode='avg')
|
285 |
-
|
286 |
-
################# VST逆变换 #################
|
287 |
-
raw_vst = raw_dn[0].permute(1,2,0).detach().cpu().numpy()
|
288 |
-
raw_vst = raw_vst * (upper - lower) + lower
|
289 |
-
raw_vst = inverse_VST(raw_vst, self.p['sigma'], gain=self.p['gain']) / self.p['scale']
|
290 |
-
|
291 |
-
reg, self.mask_data = SimpleNLF(rggb2bayer(lr_raw), rggb2bayer(raw_vst), k=13,
|
292 |
setting={'mode':'collab', 'thr_mode':'score3', 'ransac': self.p['ransac']})
|
293 |
self.p['gain'] = reg[0] * self.p['scale']
|
294 |
self.p['sigma'] = np.sqrt(max(reg[1], 0)) * self.p['scale']
|
@@ -302,7 +317,6 @@ class YOND_Backend:
|
|
302 |
gr.Error(f"噪声估计失败: {str(e)}")
|
303 |
raise RuntimeError(f"噪声估计失败: {str(e)}") from e
|
304 |
|
305 |
-
@spaces.GPU
|
306 |
def enhance_image(self, gain, sigma, sigsnr, ddim_mode, patch_size):
|
307 |
"""执行图像增强"""
|
308 |
if not self.yond:
|
@@ -335,38 +349,11 @@ class YOND_Backend:
|
|
335 |
raw_vst = (raw_vst - lower) / (upper - lower)
|
336 |
|
337 |
################# 准备去噪 #################
|
338 |
-
|
339 |
-
self.yond.net = self.yond.net.to(self.device)
|
340 |
-
raw_vst = torch.from_numpy(raw_vst).float().to(self.device).permute(2,0,1)[None,]
|
341 |
-
if 'guided' in self.yond.arch:
|
342 |
-
t = torch.tensor(nsr*self.p['sigsnr'], dtype=raw_vst.dtype, device=self.device)
|
343 |
-
|
344 |
-
# Denoise & pad
|
345 |
-
target_size = patch_size # 设置目标块大小,可以根据需要调整 GPU:1024
|
346 |
-
overlap_ratio = 1/8 # 设置重叠率,可以根据需要调整
|
347 |
-
|
348 |
-
# 使用改进的 big_image_split 函数
|
349 |
-
raw_inp, metadata = big_image_split(raw_vst, target_size, overlap_ratio)
|
350 |
-
|
351 |
-
raw_dn = torch.zeros_like(raw_inp[:,:4])
|
352 |
-
with torch.no_grad():
|
353 |
-
if self.p['ddim_mode']:
|
354 |
-
for i in range(raw_inp.shape[0]): # 处理所有切块
|
355 |
-
print(f'Patch: {i+1}/{len(raw_dn)}')
|
356 |
-
raw_dn[i] = ddim(raw_inp[i][None,].clip(None, 2), self.yond.net, t, epoch=self.p['epoch'],
|
357 |
-
sigma_t=self.p['sigma_t'], eta=self.p['eta_t'], sigma_corr=1.00)
|
358 |
-
else:
|
359 |
-
for i in range(raw_inp.shape[0]): # 处理所有切块
|
360 |
-
input_tensor = raw_inp[i][None,].clip(None, 2)
|
361 |
-
raw_dn[i] = self.yond.net(input_tensor, t).clamp(0,None)
|
362 |
-
|
363 |
-
# 使用改进的 big_image_merge 函数
|
364 |
-
raw_dn = big_image_merge(raw_dn, metadata, blend_mode='avg')
|
365 |
|
366 |
################# VST逆变换 #################
|
367 |
-
|
368 |
-
|
369 |
-
self.denoised_data = inverse_VST(raw_vst, self.p['sigma'], gain=self.p['gain']) / self.p['scale']
|
370 |
|
371 |
self.denoised_npy = rggb2bayer(self.denoised_data)
|
372 |
# 保存结果
|
|
|
221 |
raise RuntimeError(f"图像更新失败: {str(e)}") from e
|
222 |
|
223 |
@spaces.GPU
|
224 |
+
def denoise(self, raw_vst, patch_size, nsr):
|
225 |
+
################# 准备去噪 #################
|
226 |
+
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
227 |
+
self.yond.net = self.yond.net.to(self.device)
|
228 |
+
raw_vst = torch.from_numpy(raw_vst).float().to(self.device).permute(2,0,1)[None,]
|
229 |
+
if 'guided' in self.yond.arch:
|
230 |
+
t = torch.tensor(nsr*self.p['sigsnr'], dtype=raw_vst.dtype, device=self.device).view(-1,1,1,1)
|
231 |
+
|
232 |
+
# Denoise & pad
|
233 |
+
target_size = patch_size # 设置目标块大小,可以根据需要调整 GPU:1024
|
234 |
+
overlap_ratio = 1/8 # 设置重叠率,可以根据需要调整
|
235 |
+
|
236 |
+
# 使用改进的 big_image_split 函数
|
237 |
+
raw_inp, metadata = big_image_split(raw_vst, target_size, overlap_ratio)
|
238 |
+
|
239 |
+
raw_dn = torch.zeros_like(raw_inp[:,:4])
|
240 |
+
with torch.no_grad():
|
241 |
+
if self.p['ddim_mode']:
|
242 |
+
for i in range(raw_inp.shape[0]): # 处理所有切块
|
243 |
+
print(f'Patch: {i+1}/{len(raw_dn)}')
|
244 |
+
raw_dn[i] = ddim(raw_inp[i][None,].clip(None, 2), self.yond.net, t, epoch=self.p['epoch'],
|
245 |
+
sigma_t=self.p['sigma_t'], eta=self.p['eta_t'], sigma_corr=1.00)
|
246 |
+
else:
|
247 |
+
for i in range(raw_inp.shape[0]): # 处理所有切块
|
248 |
+
input_tensor = raw_inp[i][None,].clip(None, 2)
|
249 |
+
raw_dn[i] = self.yond.net(input_tensor, t).clamp(0,None)
|
250 |
+
|
251 |
+
# 使用改进的 big_image_merge 函数
|
252 |
+
raw_dn = big_image_merge(raw_dn, metadata, blend_mode='avg')
|
253 |
+
|
254 |
+
################# VST逆变换 #################
|
255 |
+
raw_dn = raw_dn[0].permute(1,2,0).detach().cpu().numpy()
|
256 |
+
return raw_dn
|
257 |
+
|
258 |
def estimate_noise(self, double_est, ransac, patch_size):
|
259 |
"""执行噪声估计"""
|
260 |
if not self.yond:
|
|
|
280 |
|
281 |
if double_est:
|
282 |
log(" 使用精估计")
|
283 |
+
if self.denoised_npy is None:
|
284 |
+
log(" 之前没去噪,先去噪再估计")
|
285 |
+
lr_raw_np = lr_raw * self.p['scale']
|
286 |
+
######## EM-VST矫正VST噪图期望偏差 ########
|
287 |
+
bias_base = np.maximum(lr_raw_np, 0)
|
288 |
+
bias = self.bias_lut.get_lut(bias_base, K=self.p['gain'], sigGs=self.p['sigma'])
|
289 |
+
raw_vst = VST(lr_raw_np, self.p['sigma'], gain=self.p['gain'])
|
290 |
+
raw_vst = raw_vst - bias
|
291 |
+
|
292 |
+
################# VST变换 #################
|
293 |
+
lower = VST(0, self.p['sigma'], gain=self.p['gain'])
|
294 |
+
upper = VST(self.p['scale'], self.p['sigma'], gain=self.p['gain'])
|
295 |
+
nsr = 1 / (upper - lower)
|
296 |
+
raw_vst = (raw_vst - lower) / (upper - lower)
|
297 |
+
|
298 |
+
################# 去噪 #################
|
299 |
+
raw_dn = self.denoise(raw_vst, patch_size, nsr)
|
300 |
+
|
301 |
+
################# VST逆变换 #################
|
302 |
+
raw_dn = raw_dn * (upper - lower) + lower
|
303 |
+
self.denoised_data = inverse_VST(raw_dn, self.p['sigma'], gain=self.p['gain']) / self.p['scale']
|
304 |
+
self.denoised_npy = rggb2bayer(self.denoised_data)
|
305 |
+
|
306 |
+
reg, self.mask_data = SimpleNLF(rggb2bayer(lr_raw), self.denoised_npy, k=13,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
setting={'mode':'collab', 'thr_mode':'score3', 'ransac': self.p['ransac']})
|
308 |
self.p['gain'] = reg[0] * self.p['scale']
|
309 |
self.p['sigma'] = np.sqrt(max(reg[1], 0)) * self.p['scale']
|
|
|
317 |
gr.Error(f"噪声估计失败: {str(e)}")
|
318 |
raise RuntimeError(f"噪声估计失败: {str(e)}") from e
|
319 |
|
|
|
320 |
def enhance_image(self, gain, sigma, sigsnr, ddim_mode, patch_size):
|
321 |
"""执行图像增强"""
|
322 |
if not self.yond:
|
|
|
349 |
raw_vst = (raw_vst - lower) / (upper - lower)
|
350 |
|
351 |
################# 准备去噪 #################
|
352 |
+
raw_dn = self.denoise(raw_vst, patch_size, nsr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
|
354 |
################# VST逆变换 #################
|
355 |
+
raw_dn = raw_dn * (upper - lower) + lower
|
356 |
+
self.denoised_data = inverse_VST(raw_dn, self.p['sigma'], gain=self.p['gain']) / self.p['scale']
|
|
|
357 |
|
358 |
self.denoised_npy = rggb2bayer(self.denoised_data)
|
359 |
# 保存结果
|