示例#1
0
def main():
    # DCT1 on the test array
    # f = np.array([231, 32, 233, 161, 24, 71, 140, 245])
    # c = DCT2_homemade.dct(f)
    # print(c)
    # f = DCT2_homemade.idct(c)
    # print(f)

    # DCT2 on the test matrix
    # f = np.matrix('231 32 233 161 24 71 140 245; 247 40 248 245 124 204 36 107; 234 202 245 167 9 217 239 173; 193 190 100 167 43 180 8 70; 11 24 210 177 81 243 8 112; 97 195 203 47 125 114 165 181; 193 70 174 167 41 30 127 245; 87 149 57 192 65 129 178 228')
    # c = DCT2_homemade.dct2(f)
    # print(c)
    # f = DCT2_homemade.idct2(c)
    # print(f)
    # c = DCT2_library.dctn(f, 2, norm='ortho')
    # print(c)
    # f = DCT2_library.idctn(c, 2, norm='ortho')
    # print(f)

    max_value = 255
    times_DCT2_homemade = []
    times_DCT2_library = []

    n_min = 50
    n_max = 500
    steps = 50
    for n in range(n_min, (n_max + 1), steps):
        f = np.matrix(np.random.randint(max_value, size=(n, n))).astype(float)

        begin_time = datetime.datetime.now()
        DCT2_homemade.dct2(f)
        time = datetime.datetime.now() - begin_time
        times_DCT2_homemade.append(time.seconds * 1000 +
                                   time.microseconds / 1000)
        print("Execution time of DCT2_homemade (n={}): {}".format(n, time))

        begin_time = datetime.datetime.now()
        DCT2_library.dctn(f, 2, norm='ortho')
        time = datetime.datetime.now() - begin_time
        times_DCT2_library.append(time.seconds * 1000 +
                                  time.microseconds / 1000)
        print("Execution time of DCT2_library (n={}): {}".format(n, time))

    palette = plt.get_cmap('Set1')
    plt.xlabel('N')
    plt.ylabel('Time (milliseconds in log scale)')
    plt.yscale('log')
    plt.grid(True, alpha=0.2)
    plt.plot(range(n_min, (n_max + 1), steps),
             times_DCT2_homemade,
             color=palette(1),
             linewidth=2)
    plt.plot(range(n_min, (n_max + 1), steps),
             times_DCT2_library,
             color=palette(4),
             linewidth=2)
    plt.legend(['DCT2_homemade', 'DCT2_library'], loc=2, ncol=2)
    plt.show()
示例#2
0
def unwrap_phase_based_cosine_transform(mat, window=None):
    """
    Unwrap a phase image using the cosine transform as described in Ref. [1]_.

    Parameters
    ----------
    mat : array_like
        2D array. Wrapped phase-image in the range of [-Pi; Pi].
    window : array_like
        2D array. Window is used for the cosine transform. Generated if None.

    Returns
    -------
    array_like
        2D array. Unwrapped phase-image.

    References
    ----------
    .. [1] https://doi.org/10.1364/JOSAA.11.000107
    """
    (height, width) = mat.shape
    if window is None:
        window = _make_cosine_window(height, width)
    else:
        if window.shape != mat.shape:
            raise ValueError("Window must be the same size as the image!!!")
    rho_x = _wrap_to_pi(np.diff(mat, axis=1))
    rho_y = _wrap_to_pi(np.diff(mat, axis=0))
    rho_x2 = np.diff(rho_x, axis=1, prepend=0, append=0)
    rho_y2 = np.diff(rho_y, axis=0, prepend=0, append=0)
    rho = rho_x2 + rho_y2
    mat_unwrap = idctn(dctn(rho) / window, overwrite_x=True)
    return mat_unwrap
示例#3
0
def convJPG(im, Q):
    # Separarea canaleleor RGB
    r = im[:, :, 0]
    g = im[:, :, 1]
    b = im[:, :, 2]

    #Trecerea din RGB in YCbCr
    y, cb, cr = RGBtoYCbCr(r, g, b)
    for i in range(1, im.shape[0]):
        for j in range(1, im.shape[1]):
            if i % 8 == 0 and j % 8 == 0:
                xy = y[i - 8:i, j - 8:j]
                xcb = cb[i - 8:i, j - 8:j]
                xcr = cr[i - 8:i, j - 8:j]
                x = [xy, xcb, xcr]
                for k in range(len(x)):
                    yt = dctn(x[k])
                    yjpeg = Q * (np.round(yt / Q))
                    xjpeg = idctn(yjpeg)
                    x[k] = xjpeg
                y[i - 8:i, j - 8:j] = x[0]
                cb[i - 8:i, j - 8:j] = x[1]
                cr[i - 8:i, j - 8:j] = x[2]
    imr = im.copy()

    # Trecerea din YCrCb in RGB
    r, g, b = YCbCrtoRGB(y, cb, cr)

    imr[:, :, 0] = r
    imr[:, :, 1] = g
    imr[:, :, 2] = b
    return imr
示例#4
0
    def transform(self, obv: np.ndarray):
        obv = obv.astype(np.float32)

        if self.arrangement == "flipped_grid":
            top_row = np.concatenate([obv[0], np.fliplr(obv[1])], axis=1)
            bottom_row = np.concatenate(
                [np.flipud(obv[2]),
                 np.fliplr(np.flipud(obv[3]))], axis=1)
            obv = np.concatenate([top_row, bottom_row], axis=0)

        elif self.arrangement == "grid":
            top_row = np.concatenate([obv[0], obv[1]], axis=1)
            bottom_row = np.concatenate([obv[2], obv[3]], axis=1)
            obv = np.concatenate([top_row, bottom_row], axis=0)

        elif self.arrangement == "stacked":
            obv = np.vstack(obv)

        elif self.arrangement == "row":
            obv = np.hstack(obv)

        elif self.arrangement == "flipped_grid":
            obv = np.concatenate(
                [obv[0], np.flipud(obv[1]), obv[2],
                 np.flipud(obv[3])], axis=0)
        else:
            raise Exception("No valid transformatoin specified")

        proj = dctn(obv, norm="ortho", type=2, overwrite_x=True)
        proj = proj[1:self.cut + 1, 1:self.cut + 1].flatten()
        return proj
示例#5
0
def solvePoisson_precomped(rho, scale):
    """Solve the poisson equation "P phi = rho" using DCT

    Uses precomputed scaling factors `scale`
    """
    dctPhi = dctn(rho) / scale
    # now invert to get the result
    phi = idctn(dctPhi, overwrite_x=True)
    return phi
示例#6
0
def low_removed(filename):
    img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
    height, width = img.shape[:2]
    dct_coef = dctn(img)
    dct_coef = dct_coef[30:, 30:]
    img = idctn(dct_coef)
    img = cv2.resize(img,
                     dsize=(width, height),
                     interpolation=cv2.INTER_LINEAR)
    cv2.imwrite("low_removed_" + filename, img)
示例#7
0
def swap_dct_coef():
    img_building = cv2.imread("img_building.png", cv2.IMREAD_GRAYSCALE)
    img_face = cv2.imread("img_face.png", cv2.IMREAD_GRAYSCALE)
    img_pattern = cv2.imread("img_pattern.png", cv2.IMREAD_GRAYSCALE)

    dct_building = dctn(img_building)
    dct_face = dctn(img_face)
    dct_pattern = dctn(img_pattern)

    # swap first 50x50 building and pattern coefficients
    dct_bp = dct_building.copy()
    dct_bp[:50, :50] = dct_pattern[:50, :50]
    img_bp = idctn(dct_bp)
    cv2.imwrite("swapped_bp.png", img_bp)

    # swap first 50x50 face and building coefficients
    dct_fb = dct_face.copy()
    dct_fb[:50, :50] = dct_building[:50, :50]
    img_fb = idctn(dct_fb)
    cv2.imwrite("swapped_fb.png", img_fb)
示例#8
0
def low_frequencies(filename):
    img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
    height, width = img.shape[:2]
    low_width = width // 4
    low_height = height // 4
    dct_coef = dctn(img)
    dct_coef = dct_coef[:low_height, :low_width]
    img = idctn(dct_coef)
    img = cv2.resize(img,
                     dsize=(width, height),
                     interpolation=cv2.INTER_LINEAR)
    cv2.imwrite("low_" + filename, img)
示例#9
0
def solvePoisson(rho):
    """Solve the poisson equation "P phi = rho" using DCT
    """
    dctRho = dctn(rho)
    N, M = rho.shape
    I, J = np.ogrid[0:N, 0:M]
    with np.errstate(divide='ignore'):
        dctPhi = dctRho / 2 / (np.cos(np.pi * I / M) + np.cos(np.pi * J / N) -
                               2)
    dctPhi[0, 0] = 0  # handling the inf/nan value
    # now invert to get the result
    phi = idctn(dctPhi)
    return phi
示例#10
0
def rescale_coef(filename):
    img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
    height, width = img.shape[:2]
    dct_coef = dctn(img)
    for i in range(dct_coef.shape[0]):
        for j in range(dct_coef.shape[1]):
            dist = (i**2 + j**2)**(1 / 3)
            if not np.isclose(dist, 0):
                dct_coef[i, j] /= dist
    img = idctn(dct_coef)
    img = cv2.resize(img,
                     dsize=(width, height),
                     interpolation=cv2.INTER_LINEAR)
    cv2.imwrite("rescaled_coef_" + filename, img)
示例#11
0
 def dct_hash(self, img, blur_dim=7):
     '''
     :param img: (np.ndarray) the grayscale image to find a difference hash function of
     :param hash_size: (int) the number of bits in the hash (ex. setting to 8 yields 2**8=64 bit address)
     :param blur_dim(int) size of square mean-filter
     :return: (tuple(np.ndarray, np.ndarray)) 2 ** hash_size bit image hash binary array and DCT matrix output
     '''
     if self.size != 8:
         print(
             "Original DCT was 8 x 8 so size parameter of ImageHash object may be off"
         )
     dct_matx = dctn(cv2.blur(img, (blur_dim, blur_dim)),
                     type=2,
                     norm="ortho")
     tr_matx = dct_matx[:self.size, :self.size].flatten(
     )  # original algorithm selects top 8x8=64
     return tr_matx > np.median(tr_matx), dct_matx
示例#12
0
def middle_frequencies(filename):
    img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
    height, width = img.shape[:2]
    dct_coef = dctn(img)

    new_coef = np.zeros((height - 100, width - 10))
    height = (height - 150) // 2
    width = (width - 150) // 2
    new_coef[:height, :width] = dct_coef[:height, :width]

    common_height = min(dct_coef.shape[0], new_coef.shape[0])
    common_width = min(dct_coef.shape[1], new_coef.shape[1])

    new_coef[-height:, :common_width] = dct_coef[-height:, :common_width]
    new_coef[:common_height, -width:] = dct_coef[:common_height, -width:]

    img = idctn(new_coef)
    img = cv2.resize(img,
                     dsize=(width, height),
                     interpolation=cv2.INTER_LINEAR)
    cv2.imwrite("middle_" + filename, img)
示例#13
0
文件: input_map.py 项目: jfelding/esn
 def __call__(self, img):
     #Two dimensional discrete cosine transform
     #of image. Keep first (nk1,nk2) components
     Fkk = dctn(img, type=2, workers=-1, norm='forward')
     Fkk = Fkk[:self.size[0], :self.size[1]]
     return Fkk.reshape(-1)
示例#14
0
    def update_controls(self, target_belief, x_obs, x):
        ts = time.time()
        self.x = x
        nx, ny = target_belief.shape
        xmin, xmax, ymin, ymax = self.bounds
        L1 = xmax - xmin
        L2 = ymax - ymin

        if self.mode == 'mi':
            mu = convolve2d(target_belief, self.footprint_mask, mode='same')
            pos = self.tp_rate * mu + self.fp_rate * (1 - mu)
            mi = (-self.tp_rate * mu * np.log(pos / self.tp_rate) -
                  (1 - self.tp_rate) * mu * np.log(
                      (1 - pos) / (1 - self.tp_rate)) - self.fp_rate *
                  (1 - mu) * np.log(pos / self.fp_rate) - (1 - self.fp_rate) *
                  (1 - mu) * np.log((1 - pos) / (1 - self.fp_rate)))
            info = mi / np.sum(mi)
        elif self.mode == 'p':
            mu = convolve2d(target_belief, self.footprint_mask, mode='same')
            info = mu / np.sum(mu)
        elif self.mode == 'b':
            info = target_belief / np.sum(target_belief)
        elif self.mode == 'alpha':
            mu = convolve2d(target_belief, self.footprint_mask, mode='same')
            pos = self.tp_rate * mu + self.fp_rate * (1 - mu)
            alpha = .5
            ami = (1 /
                   (1 - alpha)) * (pos * np.log(mu *
                                                (self.tp_rate / pos)**alpha +
                                                (1 - mu) *
                                                (self.fp_rate / pos)**alpha) +
                                   (1 - pos) * np.log(mu *
                                                      ((1 - self.tp_rate) /
                                                       (1 - pos))**alpha +
                                                      (1 - mu) *
                                                      ((1 - self.fp_rate) /
                                                       (1 - pos))**alpha))
            info = ami / np.sum(ami)

        muk = dctn(info * np.sqrt(nx) * np.sqrt(ny), type=2, norm='ortho')
        muk = muk[0:self.nfourier, 0:self.nfourier].flatten()

        x1_comp = np.cos(np.outer((x_obs[:, 0] - xmin) / L1, self.k1))
        x2_comp = np.cos(np.outer((x_obs[:, 1] - ymin) / L2, self.k2))
        ck_prev = (1 / self.hk) * np.sum(x1_comp * x2_comp, axis=0)

        if len(self.ck_history_cum) == 0:
            self.ck_history_cum.append(ck_prev)
            ck_init = np.zeros(self.k1.shape[0])
            t_total = self.t_horizon
        else:
            prev_cum = self.ck_history_cum[-1]
            self.ck_history_cum.append(prev_cum + ck_prev)
            if len(self.ck_history_cum) > self.t_history:
                ck_init = self.ck_history_cum[-1] - self.ck_history_cum[
                    -self.t_history - 1]
                t_total = self.t_history + self.t_horizon
            else:
                ck_init = self.ck_history_cum[-1]
                t_total = len(self.ck_history_cum) + self.t_horizon

        opti = casadi.Opti()
        v_u = [opti.variable(2, self.t_horizon) for i in range(self.nagents)]
        v_x = [casadi.cumsum(v_u[i], 2) + x[i, :] for i in range(self.nagents)]
        v_ck = (ck_init + (1 / self.hk) * sum([
            casadi.sum2(
                casadi.cos(self.k1 @ (v_x[i][0, :] - xmin) / L1) *
                casadi.cos(self.k2 @ (v_x[i][1, :] - ymin) / L2))
            for i in range(self.nagents)
        ])) / (self.nagents * t_total)

        erg_metric = casadi.sum1(self.Lambdak * (v_ck - muk)**2)
        change_penalties = []
        for i in range(self.nagents):
            opti.subject_to(casadi.sum2(v_u[i]**2) < self.u_max**2)
            opti.subject_to(v_x[i][0, :] > xmin)
            opti.subject_to(v_x[i][0, :] < xmax)
            opti.subject_to(v_x[i][1, :] > ymin)
            opti.subject_to(v_x[i][1, :] < ymax)
            for j in range(i + 1, self.nagents):
                opti.subject_to(
                    casadi.sum1((v_x[i] - v_x[j])**2) > self.min_dist**2)

            u_init = np.zeros((2, self.t_horizon))
            u_init[:, 0:-1] = self.u[i][:, 1:]

            opti.set_initial(v_u[i], u_init)
            change_penalties.append(
                self.change_paramt0 *
                casadi.sum1(casadi.sum2((v_u[i][:, 0] - self.u[i][:, 0])**2)))
            change_penalties.append(
                self.change_param *
                casadi.sum1(casadi.sum2((v_u[i][:, 1:] - v_u[i][:, 0:-1])**2)))

        change_cost = sum(change_penalties)
        opti.minimize(erg_metric + change_cost)

        p_opts = {}
        # s_opts = {'max_cpu_time': .09, 'print_level': 0}
        s_opts = {'print_level': 0}
        opti.solver('ipopt', p_opts, s_opts)
        sol = opti.solve()
        self.u = [sol.value(v_u[i]) for i in range(self.nagents)]
        xs = [sol.value(v_x[i]) for i in range(self.nagents)]

        # try:
        # 	sol = opti.solve()
        # 	self.u = [sol.value(v_u[i]) for i in range(self.nagents)]
        # 	xs = [sol.value(v_x[i]) for i in range(self.nagents)]
        # except:
        # 	self.u = [opti.debug.value(v_u[i]) for i in range(self.nagents)]
        # 	xs = [opti.debug.value(v_x[i]) for i in range(self.nagents)]

        action = np.zeros((self.nagents, 2))
        for i in range(self.nagents):
            action[i, :] = xs[i][:, 0]

        t_comp = time.time() - ts
        self.x = x

        if self.gui:
            xs_plot = [
                np.insert(xs[i], 0, self.x[i, :], axis=1)
                for i in range(self.nagents)
            ]
            # display information map, planned trajectories, and
            if self.image1 is None:
                fig, (ax1, ax2) = plt.subplots(2, 1, num='erg', figsize=(2, 4))
                self.image1 = ax1.imshow(info.T / np.max(info),
                                         extent=self.bounds,
                                         origin='lower',
                                         cmap='gray')
                self.image2 = ax2.imshow(target_belief.T /
                                         np.max(target_belief),
                                         extent=self.bounds,
                                         origin='lower',
                                         cmap='gray')
                ax1.set_title('Information Map')
                ax2.set_title('Target Belief')
                ax1.axis('off')
                ax2.axis('off')
                self.lines = []
                self.inits = []
                for i in range(self.nagents):
                    line, = ax1.plot(xs[i][0, :], xs[i][1, :],
                                     'r.-')  #, linestyle=':')
                    self.lines.append(line)
                    init, = ax1.plot(self.x[i, 0], self.x[i, 1], 'g.')
                    self.inits.append(init)
            else:
                plt.figure('erg')
                self.image1.set_data(info.T / np.max(info))
                self.image2.set_data(target_belief.T / np.max(target_belief))
                for i in range(self.nagents):
                    self.lines[i].set_xdata(xs[i][0, :])
                    self.lines[i].set_ydata(xs[i][1, :])
                    self.inits[i].set_xdata(self.x[i, 0])
                    self.inits[i].set_ydata(self.x[i, 1])

            plt.draw()
            plt.pause(.001)

        return action, t_comp
示例#15
0
def comp_ch(ch, f):
    xch = dctn(ch)
    xch[f:] = 0
    return idctn(xch)
示例#16
0
def dct2(sub_img):
    return DCT2_library.dctn(sub_img, 2, norm='ortho')
示例#17
0
def unwrap(
    f_wrapped,
    phi_x=None,
    phi_y=None,
    max_iters=500,
    tol=np.pi / 5,
    lmbda=1,
    p=0,
    c=1.3,
    dtype="float32",
    debug=False,
    #     boundary_conditions="neumann",
):
    """Unwrap interferogram phase

    Parameters
    ----------
        f_wrapped (ndarray): wrapped phase image (interferogram)
        phi_x (ndarray): estimate of the x-derivative of the wrapped phase
            If not passed, will compute using `est_wrapped_gradient`
        phi_y (ndarray): estimate of the y-derivative of the wrapped phase
            If not passed, will compute using `est_wrapped_gradient`
        max_iters (int): maximum number of ADMM iterations to run
        tol (float): maximum allowed change for any pixel between ADMM iterations
        lmbda (float): splitting parameter of ADMM. Smaller = more stable, Larger = faster convergence.
        p (float): value used in shrinkage operator
        c (float): acceleration constant using in updating lagrange multipliers in ADMM
        dtype: numpy datatype for output
        debug (bool): print diagnostic ADMM information
    """
    rows, columns = f_wrapped.shape
    num = rows * columns

    if dtype is None:
        dtype = f_wrapped.dtype
    else:
        f_wrapped = f_wrapped.astype(dtype)

    boundary_conditions = "neumann"
    if debug:
        print(f"Making Dx, Dy with BCs={boundary_conditions}")
    Dx, Dy = make_differentiation_matrices(
        *f_wrapped.shape, boundary_conditions=boundary_conditions)

    if phi_x is None or phi_y is None:
        phi_x, phi_y = est_wrapped_gradient(f_wrapped, Dx, Dy, dtype=dtype)

    # Lagrange multiplier variables
    Lambda_x = np.zeros_like(phi_x, dtype=dtype)
    Lambda_y = np.zeros_like(phi_y, dtype=dtype)

    # aux. variables for ADMM, holding difference between
    # unwrapped phase gradient and measured gradient from igram
    w_x = np.zeros_like(phi_x, dtype=dtype)
    w_y = np.zeros_like(phi_y, dtype=dtype)

    F_old = np.zeros_like(f_wrapped)

    # Get K ready once for solving linear system
    K = make_laplace_kernel(rows, columns, dtype=dtype)

    for iteration in range(max_iters):

        # update Unwrapped Phase F: solve linear eqn in fourier domain
        # rhs = dx.T @ phi[0].ravel() + dy.T @ phi[1].ravel()
        rx = w_x.ravel() + phi_x.ravel() - Lambda_x.ravel()
        ry = w_y.ravel() + phi_y.ravel() - Lambda_y.ravel()
        RHS = Dx.T * rx + Dy.T * ry
        # Use DCT for neumann:
        rho_hat = dctn(RHS.reshape(rows, columns),
                       type=2,
                       norm='ortho',
                       workers=-1)
        F = idctn(rho_hat * K, type=2, norm='ortho', workers=-1)

        # calculate x, y gradients of new unwrapped phase estimate
        Fx = (Dx @ F.ravel()).reshape(rows, columns)
        Fy = (Dy @ F.ravel()).reshape(rows, columns)

        input_x = Fx - phi_x + Lambda_x
        input_y = Fy - phi_y + Lambda_y
        w_x, w_y = p_shrink(np.stack((input_x, input_y), axis=0),
                            lmbda=lmbda,
                            p=p,
                            epsilon=0)

        # update lagrange multipliers
        Lambda_x += c * (Fx - phi_x - w_x)
        Lambda_y += c * (Fy - phi_y - w_y)

        change = np.max(np.abs(F - F_old))
        if debug:
            print(f"Iteration:{iteration} change={change}")

        if change < tol or np.isnan(change):
            break
        else:
            F_old = F

    if debug:
        print(f"Finished after {iteration} with change={change}")
    return F
示例#18
0
def kde2d(x, y, n=256, limits=None):
    """

    Return the 2d density map from discrete observations via 
    2-dimensional diffusion Kernel density estimation.

    First the input data is binned. After binning, the function 
    determines the optimal bandwidth according to the diffusion-based 
    method. It then smooths the binned data over the grid using a 
    Gaussian kernel with a standard deviation corresponding to 
    that bandwidth.

        This module is based on the KDE-diffusion of 

            Z. I. Botev, J. F. Grotowski, D. P. Kroese: 
            Kernel density estimation via diffusion. 
            Annals of Statistics 38 (2010), no. 5, 2916--2957. 
            doi:10.1214/10-AOS799

        and

            John Hennig
            DOI: 10.5281/zenodo.3830437
            https://doi.org/10.5281/zenodo.3830437

        **Parameters**

            x

                A lists of array of numbers that represent discrete 
                observations of a random variable with two coordinate 
                components. The observations are binned on a grid of 
                n*n points, where ``n`` must be a power of 2 or will 
                be coerced to the next one. If ``x`` and ``y`` are not 
                the same length, the algorithm will raise a ``ValueError``.

            y

                A lists of array of numbers that represent discrete 
                observations of a random variable with two coordinate 
                components. The observations are binned on a grid of 
                n*n points, where ``n`` must be a power of 2 or will 
                be coerced to the next one. If ``x`` and ``y`` are not 
                the same length, the algorithm will raise a ``ValueError``.

            n (optional)

                The number of grid points. It must be a power of 2. 
                Otherwise, it will be coerced to the next power of two.
                The default is 256.

            limits (optional)

                Data ``limits`` specified as a tuple of tuples denoting
                ``((xmin, xmax), (ymin, ymax))``. If any of the values 
                are ``None``, they will be inferred from the data. Each 
                tuple, or even both of them, may also be replaced by a 
                single value denoting the upper bound of a range 
                centered at zero. The default is ``None``.

        **Returns**

            A tuple whose elements are the following:

                density

                    The density map of the data.

                grid

                    The grid at which the density is computed.

                bandwidth

                    The optimal values (per axis) that the algorithm has 
                    determined. If the algorithm does not converge, it 
                    will raise a ``ValueError``.

    ---------------------------------------------------------------------------
    """

    # Convert to arrays in case lists are passed in.

    x = np.array(x)
    y = np.array(y)

    # Make sure numbers of data points are consistent.

    N = len(x)
    if len(y) != N:
        raise ValueError('x and y must have the same length.')

    # Round up number of bins to next power of two.

    n = int(2**np.ceil(np.log2(n)))

    # Determine missing data limits.

    if limits is None:

        xmin = xmax = ymin = ymax = None

    elif isinstance(limits, tuple):

        (xlimits, ylimits) = limits
        if xlimits is None:
            xmin = xmax = None
        elif isinstance(xlimits, tuple):
            (xmin, xmax) = xlimits
        else:
            xmin = -xlimits
            xmax = +xlimits
        if ylimits is None:
            ymin = ymax = None
        elif isinstance(ylimits, tuple):
            (ymin, ymax) = ylimits
        else:
            ymin = -ylimits
            ymax = +ylimits
    else:

        xmin = -limits
        xmax = +limits
        ymin = -limits
        ymax = +limits

    if None in (xmin, xmax):
        delta = x.max() - x.min()
        if xmin is None:
            xmin = x.min() - delta / 4
        if xmax is None:
            xmax = x.max() + delta / 4

    if None in (ymin, ymax):
        delta = y.max() - y.min()
        if ymin is None:
            ymin = y.min() - delta / 4
        if ymax is None:
            ymax = y.max() + delta / 4

    deltax = xmax - xmin
    deltay = ymax - ymin

    # Bin samples on regular grid.

    (binned, xedges, yedges) = np.histogram2d(x,
                                              y,
                                              bins=n,
                                              range=((xmin, xmax), (ymin,
                                                                    ymax)))
    grid = (xedges[:-1], yedges[:-1])

    # Compute discrete cosine transform. Adjust first component.

    transformed = dctn(binned / N)
    transformed[0, :] /= 2
    transformed[:, 0] /= 2

    # Pre-compute squared indices and transform components before solver loop.

    k = np.arange(n, dtype="float")  # float avoids integer overflow.
    k2 = k**2
    a2 = transformed**2

    # Define internal functions to be solved iteratively.

    def γ(t):
        sigma = psi(0, 2, t) + psi(2, 0, t) + 2 * psi(1, 1, t)
        γ = (2 * np.pi * N * sigma)**(-1 / 3)
        return (t - γ) / γ

    def psi(i, j, t):
        if i + j <= 4:
            sigma = abs(psi(i + 1, j, t) + psi(i, j + 1, t))
            C = (1 + 1 / 2**(i + j + 1)) / 3
            pii = np.product(np.arange(1, 2 * i, 2))
            pij = np.product(np.arange(1, 2 * j, 2))
            t = (C * pii * pij / (np.pi * N * sigma))**(1 / (2 + i + j))
        w = 0.5 * np.ones(n)
        w[0] = 1
        w = w * np.exp(-np.pi**2 * k2 * t)
        wx = w * k2**i
        wy = w * k2**j
        return (-1)**(i + j) * np.pi**(2 * (i + j)) * wy @ a2 @ wx

    # Solve for optimal diffusion time t*.

    try:
        ts = brentq(lambda t: t - γ(t), 0, 0.1)
    except ValueError:
        raise ValueError('Bandwidth optimization did not converge.') from None

    # Calculate diffusion times along x- and y-axis.

    psi02 = psi(0, 2, ts)
    psi20 = psi(2, 0, ts)
    psi11 = psi(1, 1, ts)
    tx1 = (psi02**(3 / 4) / (4 * np.pi * N * psi20**(3 / 4) *
                             (psi11 + np.sqrt(psi02 * psi20))))**(1 / 3)
    tx2 = (psi20**(3 / 4) / (4 * np.pi * N * psi02**(3 / 4) *
                             (psi11 + np.sqrt(psi02 * psi20))))**(1 / 3)

    # Note:
    # The above uses the nomenclature from the paper. In the Matlab
    # reference, tx1 is called t_y, while tx2 is t_x. This is a curious
    # change in notation. It may be related to the fact that image
    # coordinates are typically in (y,x) index order, whereas matrices,
    # such as the binned histogram (in Matlab as much as in Python),
    # are in (x,y) order. The Matlab code eventually does return
    # image-like index order, though it never explicitly transposes
    # the density matrix. That is implicitly handled by its custom
    # implementation of the inverse transformation (idct2d), which
    # only employs one matrix transposition, not two as its forward
    # counterpart (dct2d).

    # Apply Gaussian filter with optimized kernel.

    smoothed = transformed * np.outer(np.exp(-np.pi**2 * k2 * tx2 / 2),
                                      np.exp(-np.pi**2 * k2 * tx1 / 2))

    # Reverse transformation.

    smoothed[0, :] *= 2
    smoothed[:, 0] *= 2
    inverse = idctn(smoothed)

    # Normalize density.

    density = np.transpose(inverse) * n / deltax * n / deltay

    # Determine bandwidth from diffusion times.

    bandwidth = np.array([np.sqrt(tx2) * deltax, np.sqrt(tx1) * deltay])

    # Return results.

    return (density, grid, bandwidth)
示例#19
0
def kde2d(x, y, n=256, limits=None):
    """
    Estimates the 2d density from discrete observations.

    The input is two lists/arrays `x` and `y` of numbers that represent
    discrete observations of a random variable with two coordinate
    components. The observations are binned on a grid of n×n points.
    `n` will be coerced to the next highest power of two if it isn't
    one to begin with.

    Data `limits` may be specified as a tuple of tuples denoting
    `((xmin, xmax), (ymin, ymax))`. If any of the values are `None`,
    they will be inferred from the data. Each tuple, or even both of
    them, may also be replaced by a single value denoting the upper
    bound of a range centered at zero.

    After binning, the function determines the optimal bandwidth
    according to the diffusion-based method. It then smooths the
    binned data over the grid using a Gaussian kernel with a standard
    deviation corresponding to that bandwidth.

    Returns the estimated `density` and the `grid` (along each of the
    two axes) upon which it was computed, as well as the optimal
    `bandwidth` values (per axis) that the algorithm determined.
    Raises `ValueError` if the algorithm did not converge or `x` and
    `y` are not the same length.
    """

    # Convert to arrays in case lists are passed in.
    x = array(x)
    y = array(y)

    # Make sure numbers of data points are consistent.
    N = len(x)
    if len(y) != N:
        raise ValueError('x and y must have the same length.')

    # Round up number of bins to next power of two.
    n = int(2**ceil(log2(n)))

    # Determine missing data limits.
    if limits is None:
        xmin = xmax = ymin = ymax = None
    elif isinstance(limits, tuple):
        (xlimits, ylimits) = limits
        if xlimits is None:
            xmin = xmax = None
        elif isinstance(xlimits, tuple):
            (xmin, xmax) = xlimits
        else:
            xmin = -xlimits
            xmax = +xlimits
        if ylimits is None:
            ymin = ymax = None
        elif isinstance(ylimits, tuple):
            (ymin, ymax) = ylimits
        else:
            ymin = -ylimits
            ymax = +ylimits
    else:
        xmin = -limits
        xmax = +limits
        ymin = -limits
        ymax = +limits
    if None in (xmin, xmax):
        delta = x.max() - x.min()
        if xmin is None:
            xmin = x.min() - delta / 4
        if xmax is None:
            xmax = x.max() + delta / 4
    if None in (ymin, ymax):
        delta = y.max() - y.min()
        if ymin is None:
            ymin = y.min() - delta / 4
        if ymax is None:
            ymax = y.max() + delta / 4
    Δx = xmax - xmin
    Δy = ymax - ymin

    # Bin samples on regular grid.
    (binned, xedges, yedges) = histogram2d(x,
                                           y,
                                           bins=n,
                                           range=((xmin, xmax), (ymin, ymax)))
    grid = (xedges[:-1], yedges[:-1])

    # Compute discrete cosine transform, then adjust first component.
    transformed = dctn(binned / N)
    transformed[0, :] /= 2
    transformed[:, 0] /= 2

    # Pre-compute squared indices and transform components before solver loop.
    k = arange(n, dtype='float')  # "float" avoids integer overflow.
    k2 = k**2
    a2 = transformed**2

    # Define internal functions to be solved iteratively.
    def γ(t):
        Σ = ψ(0, 2, t) + ψ(2, 0, t) + 2 * ψ(1, 1, t)
        γ = (2 * π * N * Σ)**(-1 / 3)
        return (t - γ) / γ

    def ψ(i, j, t):
        if i + j <= 4:
            Σ = abs(ψ(i + 1, j, t) + ψ(i, j + 1, t))
            C = (1 + 1 / 2**(i + j + 1)) / 3
            Πi = product(arange(1, 2 * i, 2))
            Πj = product(arange(1, 2 * j, 2))
            t = (C * Πi * Πj / (π * N * Σ))**(1 / (2 + i + j))
        w = 0.5 * ones(n)
        w[0] = 1
        w = w * exp(-π**2 * k2 * t)
        wx = w * k2**i
        wy = w * k2**j
        return (-1)**(i + j) * π**(2 * (i + j)) * wy @ a2 @ wx

    # Solve for optimal diffusion time t*.
    try:
        ts = brentq(lambda t: t - γ(t), 0, 0.1)
    except ValueError:
        raise ValueError('Bandwidth optimization did not converge.') from None

    # Calculate diffusion times along x- and y-axis.
    ψ02 = ψ(0, 2, ts)
    ψ20 = ψ(2, 0, ts)
    ψ11 = ψ(1, 1, ts)
    tx1 = (ψ02**(3 / 4) / (4 * π * N * ψ20**(3 / 4) *
                           (ψ11 + sqrt(ψ02 * ψ20))))**(1 / 3)
    tx2 = (ψ20**(3 / 4) / (4 * π * N * ψ02**(3 / 4) *
                           (ψ11 + sqrt(ψ02 * ψ20))))**(1 / 3)

    # Note:
    # The above uses the nomenclature from the paper. In the Matlab
    # reference, tx1 is called t_y, while tx2 is t_x. This is a curious
    # change in notation. It may be related to the fact that image
    # coordinates are typically in (y,x) index order, whereas matrices,
    # such as the binned histogram (in Matlab as much as in Python),
    # are in (x,y) order. The Matlab code eventually does return
    # image-like index order, though it never explicitly transposes
    # the density matrix. That is implicitly handled by its custom
    # implementation of the inverse transformation (idct2d), which
    # only employs one matrix transposition, not two as its forward
    # counterpart (dct2d).

    # Apply Gaussian filter with optimized kernel.
    smoothed = transformed * outer(exp(-π**2 * k2 * tx2 / 2),
                                   exp(-π**2 * k2 * tx1 / 2))

    # Reverse transformation after adjusting first component.
    smoothed[0, :] *= 2
    smoothed[:, 0] *= 2
    inverse = idctn(smoothed)

    # Normalize density.
    density = inverse * n / Δx * n / Δy

    # Determine bandwidth from diffusion times.
    bandwidth = array([sqrt(tx2) * Δx, sqrt(tx1) * Δy])

    # Return results.
    return (density, grid, bandwidth)
示例#20
0
import numpy as np
import matplotlib.pyplot as plt
from scipy import misc, ndimage
from scipy.fft import dctn, idctn

X = misc.ascent()
plt.imshow(X, cmap=plt.cm.gray)
plt.show()

Y1 = dctn(X, type=1)
Y2 = dctn(X, type=2)
Y3 = dctn(X, type=3)
Y4 = dctn(X, type=4)
freq_db_1 = 20 * np.log10(abs(Y1))
freq_db_2 = 20 * np.log10(abs(Y2))
freq_db_3 = 20 * np.log10(abs(Y3))
freq_db_4 = 20 * np.log10(abs(Y4))

plt.subplot(221).imshow(freq_db_1)
plt.subplot(222).imshow(freq_db_2)
plt.subplot(223).imshow(freq_db_3)
plt.subplot(224).imshow(freq_db_4)
plt.show()

k = 120

Y_ziped = Y2.copy()
Y_ziped[k:] = 0
X_ziped = idctn(Y_ziped)

plt.imshow(X_ziped, cmap=plt.cm.gray)
示例#21
0
assert n == ref['n']
assert n == ref['density'].shape[0]

# Determine data ranges, required for scaling.
Δx = xmax - xmin
Δy = ymax - ymin

# Bin samples on regular grid.
(binned, xedges, yedges) = histogram2d(x,
                                       y,
                                       bins=n,
                                       range=((xmin, xmax), (ymin, ymax)))
assert isclose(binned / N, ref['initial_data']).all()

# Compute 2d discrete cosine transform.
transformed = dctn(binned / N)
transformed[0, :] /= 2
transformed[:, 0] /= 2
assert isclose(transformed, ref['a']).all()

# Pre-compute squared indices and transform components before solver loop.
k = arange(n, dtype='float')  # float avoids integer overflow.
k2 = k**2
a2 = transformed**2


# Define internal functions to be solved iteratively.
def γ(t):
    Σ = ψ(0, 2, t) + ψ(2, 0, t) + 2 * ψ(1, 1, t)
    γ = (2 * π * N * Σ)**(-1 / 3)
    return (t - γ) / γ