def local_contrast_normalise(s, n=7, c=None): """Local contrast normalisation of an image. Perform local contrast normalisation :cite:`jarret-2009-what` of an image, consisting of subtraction of the local mean and division by the local norm. The original image can be reconstructed from the contrast normalised image as (`snrm` * `scn`) + `smn`. Parameters ---------- s : array_like Input image or array of images. n : int, optional (default 7) The size of the local region used for normalisation is :math:`2n+1`. c : float, optional (default None) The smallest value that can be used in the divisive normalisation. If `None`, this value is set to the mean of the local region norms. Returns ------- scn : ndarray Contrast normalised image(s) smn : ndarray Additive normalisation correction snrm : ndarray Multiplicative normalisation correction """ # Construct region weighting filter N = 2 * n + 1 g = gaussian((N, N), sd=1.0) # Compute required image padding pd = ((n, n), ) * 2 if s.ndim > 2: g = g[..., np.newaxis] pd += ((0, 0), ) sp = np.pad(s, pd, mode='symmetric') # Compute local mean and subtract from image smn = np.roll(sla.fftconv(g, sp), (-n, -n), axis=(0, 1)) s1 = sp - smn # Compute local norm snrm = np.roll(np.sqrt(np.clip(sla.fftconv(g, s1**2), 0.0, np.inf)), (-n, -n), axis=(0, 1)) # Set c parameter if not specified if c is None: c = np.mean(snrm, axis=(0, 1), keepdims=True) # Divide mean-subtracted image by corrected local norm snrm = np.maximum(c, snrm) s2 = s1 / snrm # Return contrast normalised image and normalisation components return s2[n:-n, n:-n], smn[n:-n, n:-n], snrm[n:-n, n:-n]
def local_contrast_normalise(s, n=7, c=None): """ Perform local contrast normalisation :cite:`jarret-2009-what` of an image, consisting of subtraction of the local mean and division by the local norm. The original image can be reconstructed from the contrast normalised image as (`snrm` * `scn`) + `smn`. Parameters ---------- s : array_like Input image or array of images. n : int, optional (default 7) The size of the local region used for normalisation is :math:`2n+1`. c : float, optional (default None) The smallest value that can be used in the divisive normalisation. If `None`, this value is set to the mean of the local region norms. Returns ------- scn : ndarray Contrast normalised image(s) smn : ndarray Additive normalisation correction snrm : ndarray Multiplicative normalisation correction """ # Construct region weighting filter N = 2 * n + 1 g = gaussian((N, N), sd=1.0) # Compute required image padding pd = ((n, n),) * 2 if s.ndim > 2: g = g[..., np.newaxis] pd += ((0, 0),) sp = np.pad(s, pd, mode='symmetric') # Compute local mean and subtract from image smn = np.roll(sla.fftconv(g, sp), (-n, -n), axis=(0, 1)) s1 = sp - smn # Compute local norm snrm = np.roll(np.sqrt(np.clip(sla.fftconv(g, s1**2), 0.0, np.inf)), (-n, -n), axis=(0, 1)) # Set c parameter if not specified if c is None: c = np.mean(snrm, axis=(0, 1), keepdims=True) # Divide mean-subtracted image by corrected local norm snrm = np.maximum(c, snrm) s2 = s1 / snrm # Return contrast normalised image and normalisation components return s2[n:-n, n:-n], smn[n:-n, n:-n], snrm[n:-n, n:-n]
def test_10(self): N = 64 M = 4 Nd = 8 D = np.random.randn(Nd, Nd, M) X0 = np.zeros((N, N, M)) xr = np.random.randn(N, N, M) xp = np.abs(xr) > 3 X0[xp] = np.random.randn(X0[xp].size) S = np.sum(sl.fftconv(D, X0), axis=2) lmbda = 1e-4 rho = 1e-1 opt = cbpdn.ConvBPDN.Options({ 'Verbose': False, 'MaxMainIter': 500, 'RelStopTol': 1e-3, 'rho': rho, 'AutoRho': { 'Enabled': False } }) b = cbpdn.ConvBPDN(D, S, lmbda, opt) b.solve() X1 = b.Y.squeeze() assert sl.rrs(X0, X1) < 5e-5 Sr = b.reconstruct().squeeze() assert sl.rrs(S, Sr) < 1e-4
def test_27(self): x = np.random.randn(5,) y = np.zeros((12,)) y[4] = 1.0 xy0 = convolve(y, x) xy1 = linalg.fftconv(x, y, axes=(0,), origin=(2,)) assert np.allclose(xy0, xy1)
def test_22(self): N = 32 M = 4 Nd = 8 D = np.random.randn(Nd, Nd, M) D /= np.sqrt(np.sum(D**2, axis=(0, 1))) X0 = np.zeros((N, N, M)) xr = np.random.randn(N, N, M) xp = np.abs(xr) > 3 X0[xp] = np.random.randn(X0[xp].size) S = np.sum(sl.fftconv(D, X0), axis=2) lmbda = 1e-3 opt = cbpdn.ConvBPDN.Options({'Verbose': False, 'MaxMainIter': 500, 'RelStopTol': 1e-5, 'rho': 5e-1, 'AutoRho': {'Enabled': False}}) bp = cbpdn.ConvBPDN(D, S, lmbda, opt) Xp = bp.solve() epsilon = np.linalg.norm(bp.reconstruct(Xp).squeeze() - S) opt = cbpdn.ConvMinL1InL2Ball.Options({'Verbose': False, 'MaxMainIter': 500, 'RelStopTol': 1e-5, 'rho': 2e2, 'RelaxParam': 1.0, 'AutoRho': {'Enabled': False}}) bc = cbpdn.ConvMinL1InL2Ball(D, S, epsilon=epsilon, opt=opt) Xc = bc.solve() assert np.linalg.norm(Xp - Xc) / np.linalg.norm(Xp) < 1e-3 assert(np.abs(np.linalg.norm(Xp.ravel(), 1) - np.linalg.norm(Xc.ravel(), 1)) < 1e-3)
def run_cbpdn_gpu(D, sl, sh, lmbda, test_blob=None, opt=None): """Run GPU version of CBPDN. Only supports grayscale images.""" assert _cfg.TEST.DATASET.GRAY, 'Only grayscale images are supported' assert cucbpdn is not None, 'GPU CBPDN is not supported' opt = cbpdn.ConvBPDN.Options(opt) if test_blob is None: test_blob = sl + sh fnc, psnr = 0., 0. for idx in range(test_blob.shape[-1]): X = cucbpdn.cbpdn(D, sh[..., idx].squeeze(), lmbda, opt=opt) shr = np.sum(spl.fftconv(D, X), axis=2) dfd = linalg.norm(shr.ravel() - sh[..., idx].ravel()) rl1 = linalg.norm(X.ravel(), 1) obj = dfd + lmbda * rl1 fnc += obj imgr = sl[..., idx] + shr psnr += sm.psnr(imgr, test_blob[..., idx].squeeze(), rng=1.) psnr /= test_blob.shape[-1] if _cfg.VERBOSE: print('.', end='', flush=True) return fnc, psnr
} }) """ Construct :class:`.admm.cbpdn.AddMaskSim` wrapper for :class:`.admm.cbpdn.ConvBPDNGradReg` and solve via wrapper. If the ``sporco-cuda`` extension is installed and a GPU is available, use the CUDA implementation of this combination. """ if cuda.device_count() > 0: opt['L1Weight'] = wl1 opt['GradWeight'] = wgr ams = None print('%s GPU found: running CUDA solver' % cuda.device_name()) tm = util.Timer() with sys_pipes(), util.ContextTimer(tm): X = cuda.cbpdngrdmsk(Di, imgwp, mskp, lmbda, mu, opt) t = tm.elapsed() imgr = crop(np.sum(linalg.fftconv(Di, X), axis=-1)) else: opt['L1Weight'] = wl1i opt['GradWeight'] = wgri ams = cbpdn.AddMaskSim(cbpdn.ConvBPDNGradReg, Di, imgwp, mskp, lmbda, mu, opt=opt) X = ams.solve().squeeze() t = ams.timer.elapsed('solve') imgr = crop(ams.reconstruct().squeeze()) """ Display solve time and reconstruction performance.
print('%s GPU found: running CUDA solver' % cuda.device_name()) tm = util.Timer() with sys_pipes(), util.ContextTimer(tm): X = cuda.cbpdn(D, sh, lmbda, opt) t = tm.elapsed() else: print('GPU not found: running Python solver') c = cbpdn.ConvBPDN(D, sh, lmbda, opt) X = c.solve().squeeze() t = c.timer.elapsed('solve') print('Solve time: %.2f s' % t) """ Reconstruct the image from the sparse representation. """ shr = np.sum(spl.fftconv(D, X), axis=2) imgr = sl + shr print("Reconstruction PSNR: %.2fdB\n" % spm.psnr(img, imgr)) """ Display representation and reconstructed image. """ fig = plot.figure(figsize=(14, 14)) plot.subplot(2, 2, 1) plot.imview(sl, title='Lowpass component', fig=fig) plot.subplot(2, 2, 2) plot.imview(np.sum(abs(X), axis=2).squeeze(), cmap=plot.cm.Blues, title='Main representation', fig=fig) plot.subplot(2, 2, 3)
def test_26(self): x = np.array([[0, 1], [2, 3]]) y = np.array([[4, 5], [6, 7]]) xy = np.array([[38, 36], [30, 28]]) assert np.allclose(linalg.fftconv(x, y), xy)
with sys_pipes(), util.ContextTimer(tm): X = cuda.cbpdngrd(D, img, lmbda, mu, opt) t = tm.elapsed() else: print('GPU not found: running Python solver') c = cbpdn.ConvBPDNGradReg(D, img, lmbda, mu, opt) X = c.solve().squeeze() t = c.timer.elapsed('solve') print('Solve time: %.2f s' % t) """ Reconstruct the image from the sparse representation. """ imgr = np.sum(spl.fftconv(D, X), axis=2) print("Reconstruction PSNR: %.2fdB\n" % spm.psnr(img, imgr)) """ Display representation and reconstructed image. """ fig = plot.figure(figsize=(14, 14)) plot.subplot(2, 2, 1) plot.imview(X[..., 0].squeeze(), title='Lowpass component', fig=fig) plot.subplot(2, 2, 2) plot.imview(np.sum(abs(X[..., 1:]), axis=2).squeeze(), cmap=plot.cm.Blues, title='Main representation', fig=fig) plot.subplot(2, 2, 3) plot.imview(imgr, title='Reconstructed image', fig=fig)
else: id = select_device_by_load() info = gpu_info() if info: print('Running on GPU %d (%s)\n' % (id, info[id].name)) b = pdcsc.ConvProdDictBPDN(np2cp(D), np2cp(B), np2cp(shc), lmbda, opt, dimK=0) X = cp2np(b.solve()) print("ConvProdDictBPDN solve time: %.2fs" % b.timer.elapsed('solve')) """ Compute partial and full reconstructions from sparse representation $X$ with respect to convolutional dictionary $D$ and standard dictionary $B$. The partial reconstructions are $DX$ and $XB$, and the full reconstruction is $DXB$. """ DX = sl.fftconv(D[..., np.newaxis, np.newaxis, :], X) XB = sl.dot(B, X, axis=2) shr = cp2np(b.reconstruct().squeeze()) imgr = slc + shr print("Reconstruction PSNR: %.2fdB\n" % sm.psnr(img, imgr)) """ Display original and reconstructed images. """ gamma = lambda x, g: np.sign(x) * (np.abs(x)**g) fig, ax = plot.subplots(nrows=2, ncols=2, figsize=(14, 14)) plot.imview(img, title='Original image', ax=ax[0, 0], fig=fig) plot.imview(slc, title='Lowpass component', ax=ax[0, 1], fig=fig)
'Enabled': False, 'StdResiduals': False } }) """ Construct :class:`.admm.cbpdn.AddMaskSim` wrapper for :class:`.admm.cbpdn.ConvBPDN` and solve via wrapper. This example could also have made use of :class:`.admm.cbpdn.ConvBPDNMaskDcpl` (see example `cbpdn_md_gry`), which has similar performance in this application, but :class:`.admm.cbpdn.AddMaskSim` has the advantage of greater flexibility in that the wrapper can be applied to a variety of CSC solver objects. If the ``sporco-cuda`` extension is installed and a GPU is available, use the CUDA implementation of this combination. """ if cuda.device_count() > 0: ams = None print('%s GPU found: running CUDA solver' % cuda.device_name()) tm = util.Timer() with sys_pipes(), util.ContextTimer(tm): X = cuda.cbpdnmsk(D, sh, mskp, lmbda, opt) t = tm.elapsed() imgr = crop(sl + np.sum(linalg.fftconv(D, X), axis=-1)) else: ams = cbpdn.AddMaskSim(cbpdn.ConvBPDN, D, sh, mskp, lmbda, opt=opt) X = ams.solve() t = ams.timer.elapsed('solve') imgr = crop(sl + ams.reconstruct().squeeze()) """ Display solve time and reconstruction performance. """ print("AddMaskSim wrapped ConvBPDN solve time: %.2fs" % t) print("Corrupted image PSNR: %5.2f dB" % metric.psnr(img, imgw)) print("Recovered image PSNR: %5.2f dB" % metric.psnr(img, imgr)) """ Display reference, test, and reconstructed image """
'rho': 5e1*lmbda + 1e-1, 'AutoRho': {'Enabled': False, 'StdResiduals': False}}) """ Construct :class:`.admm.cbpdn.AddMaskSim` wrapper for :class:`.admm.cbpdn.ConvBPDN` and solve via wrapper. This example could also have made use of :class:`.admm.cbpdn.ConvBPDNMaskDcpl` (see example `cbpdn_md_gry`), which has similar performance in this application, but :class:`.admm.cbpdn.AddMaskSim` has the advantage of greater flexibility in that the wrapper can be applied to a variety of CSC solver objects. If the ``sporco-cuda`` extension is installed and a GPU is available, use the CUDA implementation of this combination. """ if cuda.device_count() > 0: ams = None print('%s GPU found: running CUDA solver' % cuda.device_name()) tm = util.Timer() with sys_pipes(), util.ContextTimer(tm): X = cuda.cbpdnmsk(D, sh, mskp, lmbda, opt) t = tm.elapsed() imgr = crop(sl + np.sum(linalg.fftconv(D, X), axis=-1)) else: ams = cbpdn.AddMaskSim(cbpdn.ConvBPDN, D, sh, mskp, lmbda, opt=opt) X = ams.solve() t = ams.timer.elapsed('solve') imgr = crop(sl + ams.reconstruct().squeeze()) """ Display solve time and reconstruction performance. """ print("AddMaskSim wrapped ConvBPDN solve time: %.2fs" % t) print("Corrupted image PSNR: %5.2f dB" % metric.psnr(img, imgw)) print("Recovered image PSNR: %5.2f dB" % metric.psnr(img, imgr))
""" Construct :class:`.admm.cbpdn.AddMaskSim` wrapper for :class:`.admm.cbpdn.ConvBPDNGradReg` and solve via wrapper. If the ``sporco-cuda`` extension is installed and a GPU is available, use the CUDA implementation of this combination. """ if cuda.device_count() > 0: opt['L1Weight'] = wl1 opt['GradWeight'] = wgr ams = None print('%s GPU found: running CUDA solver' % cuda.device_name()) tm = util.Timer() with sys_pipes(), util.ContextTimer(tm): X = cuda.cbpdngrdmsk(Di, imgwp, mskp, lmbda, mu, opt) t = tm.elapsed() imgr = crop(np.sum(linalg.fftconv(Di, X), axis=-1)) else: opt['L1Weight'] = wl1i opt['GradWeight'] = wgri ams = cbpdn.AddMaskSim(cbpdn.ConvBPDNGradReg, Di, imgwp, mskp, lmbda, mu, opt=opt) X = ams.solve().squeeze() t = ams.timer.elapsed('solve') imgr = crop(ams.reconstruct().squeeze()) """ Display solve time and reconstruction performance. """ print("AddMaskSim wrapped ConvBPDN solve time: %.2fs" % t)