def wave_bases(mother, k, scale, param): n = len(k) kplus = np.array(k > 0.0, dtype=float) if mother == "MORLET": # ----------------------------------- Morlet if param == -1: param = 6.0 k0 = np.copy(param) expnt = -((scale * k - k0) ** 2) / 2.0 * kplus norm = ( np.sqrt(scale * k[1]) * (np.pi ** (-0.25)) * np.sqrt(n) ) # total energy=N [Eqn(7)] daughter = norm * np.exp(expnt) daughter = daughter * kplus # Heaviside step function fourier_factor = (4 * np.pi) / ( k0 + np.sqrt(2 + k0 ** 2) ) # Scale-->Fourier [Sec.3h] coi = fourier_factor / np.sqrt(2) # Cone-of-influence [Sec.3g] dofmin = 2 # Degrees of freedom elif mother == "PAUL": # -------------------------------- Paul if param == -1: param = 4.0 m = param expnt = -scale * k * kplus norm = ( np.sqrt(scale * k[1]) * (2 ** m / np.sqrt(m * np.prod(np.arange(1, (2 * m))))) * np.sqrt(n) ) daughter = norm * ((scale * k) ** m) * np.exp(expnt) * kplus fourier_factor = 4 * np.pi / (2 * m + 1) coi = fourier_factor * np.sqrt(2) dofmin = 2 elif mother == "DOG": # -------------------------------- DOG if param == -1: param = 2.0 m = param expnt = -((scale * k) ** 2) / 2.0 norm = np.sqrt(scale * k[1] / gamma(m + 0.5)) * np.sqrt(n) daughter = -norm * (1j ** m) * ((scale * k) ** m) * np.exp(expnt) fourier_factor = 2 * np.pi * np.sqrt(2.0 / (2 * m + 1)) coi = fourier_factor / np.sqrt(2) dofmin = 1 else: print("Mother must be one of MORLET, PAUL, DOG") return daughter, fourier_factor, coi, dofmin
def wave_bases(mother, k, scale, param): n = len(k) kplus = np.array(k > 0., dtype=float) if mother == 'MORLET': # ----------------------------------- Morlet if param == -1: param = 6. k0 = np.copy(param) # calc psi_0(s omega) from Table 1 expnt = -(scale * k - k0)**2 / 2. * kplus norm = np.sqrt(scale * k[1]) * (np.pi**(-0.25)) * np.sqrt(n) daughter = norm * np.exp(expnt) daughter = daughter * kplus # Heaviside step function # Scale-->Fourier [Sec.3h] fourier_factor = (4 * np.pi) / (k0 + np.sqrt(2 + k0**2)) coi = fourier_factor / np.sqrt(2) # Cone-of-influence [Sec.3g] dofmin = 2 # Degrees of freedom elif mother == 'PAUL': # -------------------------------- Paul if param == -1: param = 4. m = param # calc psi_0(s omega) from Table 1 expnt = -scale * k * kplus norm_bottom = np.sqrt(m * np.prod(np.arange(1, (2 * m)))) norm = np.sqrt(scale * k[1]) * (2**m / norm_bottom) * np.sqrt(n) daughter = norm * ((scale * k)**m) * np.exp(expnt) * kplus fourier_factor = 4 * np.pi / (2 * m + 1) coi = fourier_factor * np.sqrt(2) dofmin = 2 elif mother == 'DOG': # -------------------------------- DOG if param == -1: param = 2. m = param # calc psi_0(s omega) from Table 1 expnt = -(scale * k)**2 / 2.0 norm = np.sqrt(scale * k[1] / gamma(m + 0.5)) * np.sqrt(n) daughter = -norm * (1j**m) * ((scale * k)**m) * np.exp(expnt) fourier_factor = 2 * np.pi * np.sqrt(2. / (2 * m + 1)) coi = fourier_factor / np.sqrt(2) dofmin = 1 else: print('Mother must be one of MORLET, PAUL, DOG') return daughter, fourier_factor, coi, dofmin
def wave_bases(mother, k, scale, param): n = len(k) kplus = np.array(k > 0., dtype=float) if mother == 'MORLET': #----------------------------------- Morlet if param == -1: param = 6. k0 = np.copy(param) expnt = -(scale * k - k0) ** 2 / 2. * kplus norm = np.sqrt(scale * k[1]) * (np.pi ** (-0.25)) * np.sqrt(n) # total energy=N [Eqn(7)] daughter = norm * np.exp(expnt) daughter = daughter * kplus # Heaviside step function fourier_factor = (4 * np.pi) / (k0 + np.sqrt(2 + k0 ** 2)) # Scale-->Fourier [Sec.3h] coi = fourier_factor / np.sqrt(2) # Cone-of-influence [Sec.3g] dofmin = 2 # Degrees of freedom elif mother == 'PAUL': #-------------------------------- Paul if param == -1: param = 4. m = param expnt = -scale * k * kplus norm = np.sqrt(scale * k[1]) * (2 ** m / np.sqrt(m*np.prod(np.arange(1, (2 * m))))) * np.sqrt(n) daughter = norm * ((scale * k) ** m) * np.exp(expnt) * kplus fourier_factor = 4 * np.pi / (2 * m + 1) coi = fourier_factor * np.sqrt(2) dofmin = 2 elif mother == 'DOG': #-------------------------------- DOG if param == -1: param = 2. m = param expnt = -(scale * k) ** 2 / 2.0 norm = np.sqrt(scale * k[1] / gamma(m + 0.5)) * np.sqrt(n) daughter = -norm * (1j ** m) * ((scale * k) ** m) * np.exp(expnt) fourier_factor = 2 * np.pi * np.sqrt(2. / (2 * m + 1)) coi = fourier_factor / np.sqrt(2) dofmin = 1 else: print 'Mother must be one of MORLET, PAUL, DOG' return daughter, fourier_factor, coi, dofmin
def compute_pdf(sigma, alpha, gamma_inv_xi_theta): p = alpha / 2 theta = compute_cdf(sigma, gamma_inv_xi_theta) norm = p / ((sigma**2) * np.pi * gamma(1 / p)) return norm * np.exp(-((np.tan(theta)**2) / (sigma**2))**p)
class BrisqueNorefFeatureExtractor(NorefExecutorMixin, FeatureExtractor): TYPE = "BRISQUE_noref_feature" # VERSION = "0.1" VERSION = "0.2" # update PIL package to 3.2 to fix interpolation issue ATOM_FEATURES = [ "alpha_m1", "sq_m1", "alpha_m2", "sq_m2", "alpha_m3", "sq_m3", "alpha11", "N11", "lsq11", "rsq11", "alpha12", "N12", "lsq12", "rsq12", "alpha13", "N13", "lsq13", "rsq13", "alpha14", "N14", "lsq14", "rsq14", "alpha21", "N21", "lsq21", "rsq21", "alpha22", "N22", "lsq22", "rsq22", "alpha23", "N23", "lsq23", "rsq23", "alpha24", "N24", "lsq24", "rsq24", "alpha31", "N31", "lsq31", "rsq31", "alpha32", "N32", "lsq32", "rsq32", "alpha33", "N33", "lsq33", "rsq33", "alpha34", "N34", "lsq34", "rsq34", ] # order matters gamma_range = np.arange(0.2, 10, 0.001) a = gamma(2.0 / gamma_range)**2 b = gamma(1.0 / gamma_range) c = gamma(3.0 / gamma_range) prec_gammas = a / (b * c) def _generate_result(self, asset): # routine to call the command-line executable and generate feature # scores in the log file. quality_w, quality_h = asset.quality_width_height with YuvReader( filepath=asset.dis_workfile_path, width=quality_w, height=quality_h, yuv_type=self._get_workfile_yuv_type(asset)) as dis_yuv_reader: scores_mtx_list = [] for dis_yuv in dis_yuv_reader: dis_y = dis_yuv[0] fgroup1_dis, fgroup2_dis = self.mscn_extract(dis_y) scores_mtx_list.append(np.hstack((fgroup1_dis, fgroup2_dis))) scores_mtx = np.vstack(scores_mtx_list) # write scores_mtx to log file log_file_path = self._get_log_file_path(asset) with open(log_file_path, "wb") as log_file: np.save(log_file, scores_mtx) def _get_feature_scores(self, asset): # routine to read the feature scores from the log file, and return # the scores in a dictionary format. log_file_path = self._get_log_file_path(asset) with open(log_file_path, "rb") as log_file: scores_mtx = np.load(log_file) num_frm, num_features = scores_mtx.shape assert num_features == len(self.ATOM_FEATURES) feature_result = {} for idx, atom_feature in enumerate(self.ATOM_FEATURES): scores_key = self.get_scores_key(atom_feature) feature_result[scores_key] = list(scores_mtx[:, idx]) return feature_result @classmethod def mscn_extract(cls, img): img2 = imresize(img, 0.5) img3 = imresize(img, 0.25) m_image, _, _ = cls.calc_image(img) m_image2, _, _ = cls.calc_image(img2) m_image3, _, _ = cls.calc_image(img3) pps11, pps12, pps13, pps14 = cls.paired_p(m_image) pps21, pps22, pps23, pps24 = cls.paired_p(m_image2) pps31, pps32, pps33, pps34 = cls.paired_p(m_image3) alpha11, N11, bl11, br11, lsq11, rsq11 = cls.extract_aggd_features( pps11) alpha12, N12, bl12, br12, lsq12, rsq12 = cls.extract_aggd_features( pps12) alpha13, N13, bl13, br13, lsq13, rsq13 = cls.extract_aggd_features( pps13) alpha14, N14, bl14, br14, lsq14, rsq14 = cls.extract_aggd_features( pps14) alpha21, N21, bl21, br21, lsq21, rsq21 = cls.extract_aggd_features( pps21) alpha22, N22, bl22, br22, lsq22, rsq22 = cls.extract_aggd_features( pps22) alpha23, N23, bl23, br23, lsq23, rsq23 = cls.extract_aggd_features( pps23) alpha24, N24, bl24, br24, lsq24, rsq24 = cls.extract_aggd_features( pps24) alpha31, N31, bl31, br31, lsq31, rsq31 = cls.extract_aggd_features( pps31) alpha32, N32, bl32, br32, lsq32, rsq32 = cls.extract_aggd_features( pps32) alpha33, N33, bl33, br33, lsq33, rsq33 = cls.extract_aggd_features( pps33) alpha34, N34, bl34, br34, lsq34, rsq34 = cls.extract_aggd_features( pps34) alpha_m1, sq_m1 = cls.extract_ggd_features(m_image) alpha_m2, sq_m2 = cls.extract_ggd_features(m_image2) alpha_m3, sq_m3 = cls.extract_ggd_features(m_image3) mscn_features = np.array([ alpha_m1, sq_m1, #0, 1 alpha_m2, sq_m2, #0, 1 alpha_m3, sq_m3, #0, 1 ]) pp_features = np.array([ alpha11, N11, lsq11, rsq11, #6, 7, 8, 9 (V) alpha12, N12, lsq12, rsq12, #10, 11, 12, 13 (H) alpha13, N13, lsq13, rsq13, #14, 15, 16, 17 (D1) alpha14, N14, lsq14, rsq14, #18, 19, 20, 21 (D2) alpha21, N21, lsq21, rsq21, #6, 7, 8, 9 (V) alpha22, N22, lsq22, rsq22, #10, 11, 12, 13 (H) alpha23, N23, lsq23, rsq23, #14, 15, 16, 17 (D1) alpha24, N24, lsq24, rsq24, #18, 19, 20, 21 (D2) alpha31, N31, lsq31, rsq31, #6, 7, 8, 9 (V) alpha32, N32, lsq32, rsq32, #10, 11, 12, 13 (H) alpha33, N33, lsq33, rsq33, #14, 15, 16, 17 (D1) alpha34, N34, lsq34, rsq34, #18, 19, 20, 21 (D2) ]) return mscn_features, pp_features @staticmethod def gauss_window(lw, sigma): sd = float(sigma) lw = int(lw) weights = [0.0] * (2 * lw + 1) weights[lw] = 1.0 sum = 1.0 sd *= sd for ii in range(1, lw + 1): tmp = np.exp(-0.5 * float(ii * ii) / sd) weights[lw + ii] = tmp weights[lw - ii] = tmp sum += 2.0 * tmp for ii in range(2 * lw + 1): weights[ii] /= sum return weights @classmethod def calc_image(cls, image, extend_mode='constant'): avg_window = cls.gauss_window(3, 7.0 / 6.0) w, h = np.shape(image) mu_image = np.zeros((w, h)) var_image = np.zeros((w, h)) image = np.array(image).astype('float') correlate1d(image, avg_window, 0, mu_image, mode=extend_mode) correlate1d(mu_image, avg_window, 1, mu_image, mode=extend_mode) correlate1d(image**2, avg_window, 0, var_image, mode=extend_mode) correlate1d(var_image, avg_window, 1, var_image, mode=extend_mode) var_image = np.sqrt(np.abs(var_image - mu_image**2)) return (image - mu_image) / (var_image + 1), var_image, mu_image @staticmethod def paired_p(new_im): hr_shift = np.roll(new_im, 1, axis=1) hl_shift = np.roll(new_im, -1, axis=1) v_shift = np.roll(new_im, 1, axis=0) vr_shift = np.roll(hr_shift, 1, axis=0) vl_shift = np.roll(hl_shift, 1, axis=0) H_img = hr_shift * new_im V_img = v_shift * new_im D1_img = vr_shift * new_im D2_img = vl_shift * new_im return V_img, H_img, D1_img, D2_img @classmethod def extract_ggd_features(cls, imdata): nr_gam = 1.0 / cls.prec_gammas sigma_sq = np.average(imdata**2) E = np.average(np.abs(imdata)) rho = sigma_sq / E**2 pos = np.argmin(np.abs(nr_gam - rho)) return cls.gamma_range[pos], np.sqrt(sigma_sq) @classmethod def extract_aggd_features(cls, imdata): imdata_cp = imdata.copy() imdata_cp.shape = (len(imdata_cp.flat), ) imdata2 = imdata_cp * imdata_cp left_data = imdata2[imdata_cp < 0] right_data = imdata2[imdata_cp >= 0] left_mean_sqrt = 0 right_mean_sqrt = 0 if len(left_data) > 0: left_mean_sqrt = np.sqrt(np.average(left_data)) if len(right_data) > 0: right_mean_sqrt = np.sqrt(np.average(right_data)) gamma_hat = left_mean_sqrt / right_mean_sqrt # solve r-hat norm r_hat = (np.average(np.abs(imdata_cp))**2) / (np.average(imdata2)) rhat_norm = r_hat * (((gamma_hat**3 + 1) * (gamma_hat + 1)) / ((gamma_hat**2 + 1)**2)) # solve alpha by guessing values that minimize ro pos = np.argmin(np.abs(cls.prec_gammas - rhat_norm)) alpha = cls.gamma_range[pos] gam1 = gamma(1.0 / alpha) gam2 = gamma(2.0 / alpha) gam3 = gamma(3.0 / alpha) aggdratio = np.sqrt(gam1) / np.sqrt(gam3) bl = aggdratio * left_mean_sqrt br = aggdratio * right_mean_sqrt # mean parameter N = (br - bl) * (gam2 / gam1) * aggdratio return alpha, N, bl, br, left_mean_sqrt, right_mean_sqrt
def motherfunc(mother, k, scale, param): """ Compute the Fourier factor and period. Parameters ---------- mother : str A string, Equal to 'MORLET' or 'PAUL' or 'DOG'. k : 1d ndarray The Fourier frequencies at which to calculate the wavelet. scale : 1d ndarray The wavelet scale. param : int The nondimensional parameter for the wavelet function. Returns ------- nowf : 1d ndarray The nonorthogonal wavelet function. period : 1d ndarrary The vecotr of "Fourier" periods (in time units) fourier_factor : float the ratio of Fourier period to scale. coi : int The cone-of-influence size at the scale. Reference --------- * Torrence, C. and Compo, G. P., 1998, A Practical Guide to Wavelet Analysis, <I>Bull. Amer. Meteor. Soc.</I>, 79, 61-78. Example ------- >>> nowf, period, fourier_factor, coi = motherfunc(mother, k, scale,param) """ mother = mother.upper() n = len(k) kp = k > 0. scale2 = scale[:, np.newaxis] pi = np.pi if mother == 'MORLET': if not param: param = 6. expn = -(scale2 * k - param)**2 / 2. * kp norm = pi**(-0.25) * (n * k[1] * scale2)**0.5 nowf = norm * np.exp(expn) * kp * (expn > -100.) fourier_factor = 4 * pi / (param + (2 + param**2)**0.5) coi = fourier_factor / 2**0.5 elif mother == 'PAUL': if not param: param = 4. expn = -scale2 * k * kp norm = 2**param * (scale2 * k[1] * n / (param * gamma(2 * param)))**0.5 nowf = norm * np.exp(expn) * ( (scale2 * k)**param) * kp * (expn > -100.) fourier_factor = 4 * pi / (2 * param + 1) coi = fourier_factor * 2**0.5 elif mother == 'DOG': if not param: param = 2. expn = -(scale2 * k)**2 / 2. norm = (scale2 * k[1] * n / gamma(param + 0.5))**0.5 nowf = -norm * 1j**param * (scale2 * k)**param * np.exp(expn) fourier_factor = 2 * pi * (2. / (2 * param + 1))**0.5 coi = fourier_factor / 2**0.5 else: raise ValueError('Mother must be one of MORLET, PAUL, DOG\n' 'mother = %s' % repr(mother)) period = scale * fourier_factor return nowf, period, fourier_factor, coi
def iwavelet(wave, scale, dt, dj=0.25, mother='MORLET', param=False): """ Inverse the wavelet to get the time-series Parameters ---------- wave : 2d ndarray wavelet power. scale : 1d ndarray The vecotr of scale indices, given by s0*2**(j*dj) dt : float The time step between each y values. dj : (optional) float The spacing between discrete scales. The smaller, the better scale resolution. Default is 0.25 mother : (optional) str The mother wavelet function. The choices are 'MORLET', 'PAUL', or 'DOG' Default is 'MORLET' param : (optional) int The mother wavelet parameter. For 'MORLET' param is k0, default is 6. For 'PAUL' param is m, default is 4. For 'DOG' param is m, default is 2. Returns ------- iwave : 1d ndarray Inverse wavelet. Notes ----- * This function based on the IDL code WAVELET.PRO written by C. Torrence and Python code waveletFuncitions.py written by E. Predybayalo. References ---------- * Torrence, C. and Compo, G. P., 1998, A Practical Guide to Wavelet Analysis, <I>Bull. Amer. Meteor. Soc.</I>, 79, 61-78. Example ------- >>> from fisspy.analysis import wavelet >>> iwave=wavelet.iwavelet(wave,scale,dt) """ a, b = wave.shape c = len(scale) scale2 = 1 / scale**0.5 mother = mother.upper() if a != c: raise ValueError('Input array dimensions do mot match.') fourier_factor, dofmin, cdelta, gamma_fac, dj0 = motherparam(mother, param) if cdelta == -1: raise ValueError('Cdelta undefined, cannot inverse with this wavelet') if mother == 'MORLET': psi0 = np.pi**(-0.25) elif mother == 'PAUL': psi0 = 2**param * gamma(param + 1) / (np.pi * gamma(2 * param + 1))**0.5 elif mother == 'DOG': if not param: param = 2 if param == 2: psi0 = 0.867325 elif param == 6: psi0 = 0.88406 iwave = dj * dt**0.5 / (cdelta * psi0) * np.dot(scale2, wave.real) return iwave
def motherfunc(mother, k, scale, param): """ Compute the Fourier factor and period. Parameters ---------- mother : str A string, Equal to 'MORLET' or 'PAUL' or 'DOG'. k : 1d ndarray The Fourier frequencies at which to calculate the wavelet. scale : ~numpy.ndarray The wavelet scale. param : int The nondimensional parameter for the wavelet function. Returns ------- nowf : ~numpy.ndarray The nonorthogonal wavelet function. period : ~numpy.ndarrary The vecotr of "Fourier" periods (in time units) fourier_factor : float the ratio of Fourier period to scale. coi : int The cone-of-influence size at the scale. Notes ----- This function based on the IDL code WAVELET.PRO written by C. Torrence, and Python code waveletFuncitions.py written by E. Predybayalo. References ---------- Torrence, C. and Compo, G. P., 1998, A Practical Guide to Wavelet Analysis, *Bull. Amer. Meteor. Soc.*, `79, 61-78 <http://paos.colorado.edu/research/wavelets/bams_79_01_0061.pdf>`_.\n http://paos.colorado.edu/research/wavelets/ Example ------- >>> nowf, period, fourier_factor, coi = motherfunc(mother,k, scale,param) """ mother=mother.upper() n = len(k) kp = k > 0. scale2 = scale[:,np.newaxis] pi = np.pi if mother == 'MORLET': if not param: param = 6. expn = -(scale2*k-param)**2/2.*kp norm = pi**(-0.25)*(n*k[1]*scale2)**0.5 nowf = norm*np.exp(expn)*kp*(expn > -100.) fourier_factor = 4*pi/(param+(2+param**2)**0.5) coi = fourier_factor/2**0.5 elif mother == 'PAUL': if not param: param = 4. expn = -scale2*k*kp norm = 2**param*(scale2*k[1]*n/(param*gamma(2*param)))**0.5 nowf = norm*np.exp(expn)*((scale2*k)**param)*kp*(expn > -100.) fourier_factor = 4*pi/(2*param+1) coi = fourier_factor*2**0.5 elif mother == 'DOG': if not param: param = 2. expn = -(scale2*k)**2/2. norm = (scale2*k[1]*n/gamma(param+0.5))**0.5 nowf = -norm*1j**param*(scale2*k)**param*np.exp(expn) fourier_factor = 2*pi*(2./(2*param+1))**0.5 coi = fourier_factor/2**0.5 else: raise ValueError('Mother must be one of MORLET, PAUL, DOG\n' 'mother = %s' %repr(mother)) period = scale*fourier_factor return nowf, period, fourier_factor, coi
def iwavelet(wave,scale,dt,dj=0.25,mother='MORLET',param=False): """ Inverse the wavelet to get the time-series Parameters ---------- wave : ~numpy.ndarray wavelet power. scale : ~numpy.ndarray The vecotr of scale indices, given by :math:`s_0 \cdot 2^{j \cdot dj}` dt : float The time step between each y values. dj : (optional) float The spacing between discrete scales. The smaller, the better scale resolution. * Default is 0.25 mother : (optional) str The mother wavelet function. The choices are 'MORLET', 'PAUL', or 'DOG' * Default is **'MORLET'** param : (optional) int The mother wavelet parameter.\n For **'MORLET'** param is k0, default is **6**.\n For **'PAUL'** param is m, default is **4**.\n For **'DOG'** param is m, default is **2**.\n Returns ------- iwave : ~numpy.ndarray Inverse wavelet. Notes ----- This function based on the IDL code WAVELET.PRO written by C. Torrence, and Python code waveletFuncitions.py written by E. Predybayalo. References ---------- Torrence, C. and Compo, G. P., 1998, A Practical Guide to Wavelet Analysis, *Bull. Amer. Meteor. Soc.*, `79, 61-78 <http://paos.colorado.edu/research/wavelets/bams_79_01_0061.pdf>`_.\n http://paos.colorado.edu/research/wavelets/ Example ------- >>> from fisspy.analysis import wavelet >>> iwave=wavelet.iwavelet(wave,scale,dt) """ a, b = wave.shape c = len(scale) scale2=1/scale**0.5 mother=mother.upper() if a != c: raise ValueError('Input array dimensions do mot match.') fourier_factor, dofmin, cdelta, gamma_fac, dj0 = motherparam(mother,param) if cdelta == -1: raise ValueError('Cdelta undefined, cannot inverse with this wavelet') if mother == 'MORLET': psi0=np.pi**(-0.25) elif mother == 'PAUL': psi0=2**param*gamma(param+1)/(np.pi*gamma(2*param+1))**0.5 elif mother == 'DOG': if not param: param=2 if param==2: psi0=0.867325 elif param==6: psi0=0.88406 iwave=dj*dt**0.5/(cdelta*psi0)*np.dot(scale2,wave.real) return iwave