def _focusing(X, phi, Na, Nr, ftshift=False, isfft=True): d = X.dim() sizea, sizer = [1] * d, [1] * d returns = [] if Na is not None: pa = phi[0] sizea[0], sizea[-3], sizea[-1] = pa.size(0), pa.size(1), 2 epa = th.stack((th.cos(pa), -th.sin(pa)), dim=-1) epa = epa.reshape(sizea) if isfft: X = ts.fft(X, axis=-3, shift=ftshift) X = ts.ebemulcc(X, epa) X = ts.ifft(X, axis=-3, shift=ftshift) returns.append(pa.data) if Nr is not None: if Na is None: pr = phi[0] else: pr = phi[1] sizer[0], sizer[-2], sizer[-1] = pr.size(0), pr.size(1), 2 epr = th.stack((th.cos(pr), -th.sin(pr)), dim=-1) epr = epr.reshape(sizer) if isfft: X = ts.fft(X, axis=-2, shift=ftshift) X = ts.ebemulcc(X, epr) X = ts.ifft(X, axis=-2, shift=ftshift) returns.append(pr.data) return [X] + returns
def phase_correction(x, phi, nsub=None, axis=-2, ftshift=True): if th.is_complex(x): # N, Na, Nr = x.size(0), x.size(-2), x.size(-1) cplxflag = True elif x.size(-1) == 2: # N, Na, Nr = x.size(0), x.size(-3), x.size(-2) x = th.view_as_complex(x) cplxflag = False else: raise TypeError( 'x is complex and should be in complex or real represent formation!' ) if axis == -2 or axis == 1: # azimuth axis = -2 if axis == -1 or axis == 2: # range axis = -1 if x.dim() == 2: x = x.unsqueeze(0) if phi.dim() == 1: phi = phi.unsqueeze(0) if phi.size(-1) != 1: phi = phi.unsqueeze(-1) phi = phi.unsqueeze(-1) N, Na, Nr = x.size() Nx = x.size(axis) pshape = [1, 1, 1] pshape[0] = N pshape[axis] = Nx phi = phi.reshape(pshape) if nsub is None: nsub = Nx # X = ts.fft(SI, axis=axis, shift=ftshift) # X = X * np.exp(-1j * phi) # SI = ts.ifft(X, axis=axis, shift=ftshift) xc = x.clone().detach() d = xc.dim() for n in range(0, Nx, nsub): idx = ts.sl(d, axis, range(n, n + nsub)) xsub = x[idx] phisub = phi[idx] Xsub = ts.fft(xsub, axis=axis, shift=ftshift) xc[idx] = ts.ifft(Xsub * th.exp(-1j * phisub), axis=axis, shift=ftshift) if not cplxflag: xc = th.view_as_real(xc) return xc
def focus(self, X, pa=None, pr=None): # X --> N-1-Na-Nr-2 # pa --> N-Na # pr --> N-Nr if pa is None and pr is None: return X if pa is not None: X = ts.fft(X, nfft=None, axis=2, norm=False) pa = pa.reshape(pa.size(0), 1, int(pa.numel() / pa.size(0)), 1) epa = th.stack((th.cos(pa), th.sin(pa)), dim=-1) X = ts.ebemulcc(X, epa) if pr is not None: X = ts.fft(X, nfft=None, axis=3, norm=False) pr = pr.reshape(pr.size(0), 1, 1, int(pr.numel() / pr.size(0))) epr = th.stack((th.cos(pr), th.sin(pr)), dim=-1) X = ts.ebemulcc(X, epr) if pa is not None: X = ts.ifft(X, nfft=None, axis=2, norm=False) if pr is not None: X = ts.ifft(X, nfft=None, axis=3, norm=False) return X
def af_ffo(g, w=None, p=2, niter=10, eta=0.5, tol=1e-2, ftshift=False): if p < 1: raise ValueError('p should be larger than 1!') G = ts.fft(g, axis=-3, shift=ftshift) Na, Nr = G.size(-3), G.size(-2) d = G.dim() wshape = [1] * d wshape[-3] = Na if w is None: w = th.ones(wshape, device=G.device, dtype=G.dtype) if eta is None: eta = ts.PI / 2. phi0, i = 1e3, 0 phi = th.zeros(wshape, device=G.device, dtype=G.dtype) diff = th.ones(wshape, device=G.device, dtype=G.dtype) # print(i, niter, (phi - phi0).sum(), tol) # print(w.shape) while (i < niter and (phi - phi0).abs().sum() > tol): phi0 = phi while (diff.abs().sum() > tol): Gabs = th.sqrt(G[..., 0]**2 + G[..., 1]**2).unsqueeze(-1) # print(Gabs.shape, w.shape) gamman = th.sum(w * Gabs, axis=-3, keepdim=True) print(gamman.min(), gamman.max(), "===") # print(gamman.shape, w.shape, Gabs.shape) Dphi = (w * p * th.sum((gamman ** (p - 1)) * Gabs, axis=-2, keepdim=True) / 2.) / \ (-w * w * p * (p - 1) * th.sum((gamman ** (p - 2)) * (Gabs ** 2), axis=-2, keepdim=True) / 4.) # print(Dphi.shape) diff = eta * Dphi phi = phi - diff epa = th.cat((th.cos(phi), th.sin(phi)), axis=-1) G = ts.ebemulcc(G, epa) print(Dphi.min(), Dphi.max()) print(diff.min(), diff.max()) print(phi.min(), phi.max()) i += 1 eta /= 2. print(i, eta) g = ts.ifft(G, axis=-3, shift=ftshift) return g
def af_ffo_sm(x, p=2, niter=10, delta=None, toli=1e-2, tolo=1e-2, ftshift=True, islog=False): """Stage-by-Stage minimum entropy [1] Morrison Jr, Robert Lee; Autofocus, Entropy-based (2002): Entropy-based autofocus for synthetic aperture radar. Parameters ---------- x : Tensor Corrupt complex SAR image. N-Na-Nr(complex) or N-Na-Nr-2(real) niter : int, optional The number of iteration (the default is 10) delta : {float or None}, optional The change step (the default is None (i.e. PI)) toli : int, optional Tolerance error for inner loop (the default is 1e-2) tolo : int, optional Tolerance error for outer loop (the default is 1e-2) ftshift : bool, optional Shift the zero frequency to center? (the default is True) islog : bool, optional Print log information? (the default is False) """ if delta is None: delta = ts.PI if th.is_complex(x): x = th.view_as_real(x) cplxflag = True elif x.size(-1) == 2: cplxflag = False else: raise TypeError( 'x is complex and should be in complex or real represent formation!' ) d = x.dim() N, Na, Nr = x.size(0), x.size(-3), x.size(-2) wshape = [1] * d wshape[-3] = Na X = ts.fft(x, axis=-3, shift=ftshift) phio = th.zeros(wshape, device=x.device, dtype=x.dtype) ephi = th.cat((th.cos(phio), th.sin(phio)), dim=-1) # print(wshape, phio.min(), phio.max(), ephi.min(), ephi.max()) So = __fdnorm(ts.ebemulcc(X, ephi), p) ii, io, Soi0, Soo0 = 0, 0, 1e13, 1e13 print(ii, So, Soi0, Soo0) while (ii < niter): Soo0 = So while True: Soi0 = So print(ii, "===", d) for a in range(Na): phi1, phi2 = phio.clone().detach(), phio.clone().detach() for n in range(N): print(n, N, Na, a, delta) phi1[n, a] += delta phi2[n, a] -= delta ephi1 = th.cat((th.cos(phi1), -th.sin(phi1)), dim=-1) S1 = __fdnorm(ts.ebemulcc(X, ephi1), p) ephi2 = th.cat((th.cos(phi2), -th.sin(phi2)), dim=-1) S2 = __fdnorm(ts.ebemulcc(X, ephi2), p) print(phi1.shape, phi2.shape, ephi1.shape, ephi2.shape, "]]]") print(N, S1, S2, So, S1 - S2, th.sum(ephi1 - ephi2), th.sum(phi1 - phi2)) if S1 > So: So = S1 phio = phi1.clone().detach() print("111") elif S2 > So: print("222") So = S2 phio = phi2.clone().detach() print(Soi0, So, S1, S2, abs(So - Soi0), io, "+++") if abs(So - Soi0) < toli and io > niter: break io += 1 print(ii, delta, abs(So - Soo0), tolo, abs(So - Soo0) < tolo, So, Soo0, "So") print(ii, delta, abs(So - Soi0), tolo, abs(So - Soi0) < toli, So, Soi0, "So") if abs(So - Soo0) > tolo: ii += 1 delta /= 2. else: break ephi = th.cat((th.cos(phio), th.sin(phio)), dim=-1) return ts.ifft(ts.ebemulcc(X, ephi)), ephi
def defocus(x, pa=None, pr=None, isfft=True, ftshift=True): r"""Defocus image with given phase error Defocus image in azimuth by .. math:: Y(k, n_r)=\sum_{n_a=0}^{N_a-1} X(n_a, n_r) \exp \left(j \varphi_{n_a}\right) \exp \left(-j \frac{2 \pi}{N_a} k n_a\right) where, :math:`\varphi_{n_a}` is the estimated azimuth phase error of the :math:`n_a`-th azimuth line, :math:`y(k, n_r)` is the focused pixel. The defocus method in range is the same as azimuth. Args: x (Tensor): Focused image data :math:`{\mathbf X} \in{\mathbb C}^{N\times N_c\times N_a\times N_r}` or :math:`{\mathbf X} \in{\mathbb R}^{N\times N_a\times N_r\times 2}` or :math:`{\mathbf X} \in{\mathbb R}^{N\times N_c\times N_a\times N_r\times 2}`. pa (Tensor, optional): Defocus parameters in azimuth, phase error in rad unit. (the default is None, not focus) pr (Tensor, optional): Defocus parameters in range, phase error in rad unit. (the default is None, not focus) isfft (bool, optional): Is need do fft (the default is True) ftshift (bool, optional): Is shift zero frequency to center when do fft/ifft/fftfreq (the default is True) Returns: (Tensor): A tensor of defocused images. Raises: TypeError: :attr:`x` is complex and should be in complex or real represent formation! """ if type(x) is not th.Tensor: x = th.tensor(x) if th.is_complex(x): # N, Na, Nr = x.size(0), x.size(-2), x.size(-1) x = th.view_as_real(x) crepflag = True elif x.size(-1) == 2: # N, Na, Nr = x.size(0), x.size(-3), x.size(-2) crepflag = False else: raise TypeError('x is complex and should be in complex or real represent formation!') d = x.dim() sizea, sizer = [1] * d, [1] * d if pa is not None: sizea[0], sizea[-3], sizea[-1] = pa.size(0), pa.size(1), 2 epa = th.stack((th.cos(pa), th.sin(pa)), dim=-1) epa = epa.reshape(sizea) if isfft: x = ts.fft(x, axis=-3, shift=ftshift) x = ts.ebemulcc(x, epa) x = ts.ifft(x, axis=-3, shift=ftshift) if pr is not None: sizer[0], sizer[-2], sizer[-1] = pr.size(0), pr.size(1), 2 epr = th.stack((th.cos(pr), th.sin(pr)), dim=-1) epr = epr.reshape(sizer) if isfft: x = ts.fft(x, axis=-2, shift=ftshift) x = ts.ebemulcc(x, epr) x = ts.ifft(x, axis=-2, shift=ftshift) if crepflag: x = th.view_as_complex(x) return x
def imaging(self, Xc): if self.Na is not None: Xc = ts.ifft(Xc, axis=-3, shift=self.ftshift) if self.Nr is not None: Xc = ts.ifft(Xc, axis=-2, shift=self.ftshift) return Xc