image processing 2 डी मूवी फ्रेम के अनुक्रम के लिए स्पेक्ट्रोग्राम उत्पन्न करना



image-processing numpy (1)

मेरा मानना ​​है कि आपके द्वारा वर्णित दृष्टिकोण सामान्य रूप से इस विश्लेषण को करने का सबसे अच्छा तरीका है।

हालांकि, मैंने आपके कोड में एक त्रुटि दर्ज की है। जैसा:

np.abs(f2*f2)

जटिल सरणी f2 का PSD नहीं है, आपको इसके बजाय इसके जटिल संयोग से f2 गुणा करने की आवश्यकता है (| f2 ^ 2 | | f2 | ^ 2 के समान नहीं है)।

इसके बजाय आपको कुछ करना चाहिए

(f2*np.conjugate(f2)).astype(float)

या, अधिक स्पष्ट रूप से:

np.abs(f2)**2.

2 डी पावर स्पेक्ट्रम में आवेश इस तरह की त्रुटि का एक बयान-चिह्न संकेत है (मैंने इसे पहले किया है!)

मेरे पास कुछ डेटा है जिसमें वीडियो फ्रेम का एक अनुक्रम होता है जो एक चलती आधार रेखा के सापेक्ष समय के साथ चमक में परिवर्तन का प्रतिनिधित्व करता है। इन वीडियो में दो प्रकार के 'ईवेंट' होते हैं जो हो सकते हैं - 'स्थानीयकृत' घटनाएं, जिनमें क्लस्टरर्ड पिक्सेल के छोटे समूहों में चमकदार परिवर्तन होते हैं, और 'फैलाने वाली घटनाओं' को दूषित करते हैं, जो फ्रेम में अधिकांश पिक्सेल को प्रभावित करते हैं:

मैं प्रसारित घटनाओं से चमक में स्थानीय परिवर्तनों को अलग करने में सक्षम होना चाहता हूं। मैं प्रत्येक फ्रेम के एक उचित कम-पास फ़िल्टर किए गए संस्करण को घटाकर ऐसा करने की योजना बना रहा हूं। इष्टतम फ़िल्टर को डिज़ाइन करने के लिए, मैं जानना चाहता हूं कि मेरे फ्रेम की कौन सी स्थानिक आवृत्तियों को प्रसारित और स्थानीय घटनाओं के दौरान संशोधित किया जाता है, यानी मैं समय के साथ अपनी फिल्म का एक स्पेक्ट्रोग्राम उत्पन्न करना चाहता हूं।

मुझे 1 डी डेटा (जैसे ऑडियो) के लिए स्पेक्ट्रोग्राम उत्पन्न करने के बारे में बहुत सारी जानकारी मिल सकती है, लेकिन मैं 2 डी डेटा के लिए स्पेक्ट्रोग्राम उत्पन्न करने पर बहुत अधिक नहीं आया हूं। मैंने अब तक कोशिश की है कि फ्रेम के फूरियर ट्रांसफॉर्म से 2 डी पावर स्पेक्ट्रम उत्पन्न करना है, फिर डीसी घटक के बारे में एक ध्रुवीय परिवर्तन करना और फिर 1 डी पावर स्पेक्ट्रम प्राप्त करने के लिए कोणों में औसत करना:

मैं फिर अपनी फिल्म में हर फ्रेम पर इसे लागू करता हूं, और समय के साथ वर्णक्रमीय शक्ति का रास्टर प्लॉट उत्पन्न करता हूं:

क्या यह लेने के लिए एक समझदार दृष्टिकोण की तरह लगता है? क्या 2 डी डेटा पर वर्णक्रमीय विश्लेषण करने के लिए एक और 'मानक' दृष्टिकोण है?

मेरा कोड यहाँ है:

import numpy as np
# from pyfftw.interfaces.scipy_fftpack import fft2, fftshift, fftfreq
from scipy.fftpack import fft2, fftshift, fftfreq
from matplotlib import pyplot as pp
from matplotlib.colors import LogNorm
from scipy.signal import windows
from scipy.ndimage.interpolation import map_coordinates

def compute_2d_psd(img, doplot=True, winfun=windows.hamming, winfunargs={}):

    nr, nc = img.shape
    win = make2DWindow((nr, nc), winfun, **winfunargs)

    f2 = fftshift(fft2(img*win))
    psd = np.abs(f2*f2)
    pol_psd = polar_transform(psd, centre=(nr//2, nc//2))

    mpow = np.nanmean(pol_psd, 0)
    stdpow = np.nanstd(pol_psd, 0)

    freq_r = fftshift(fftfreq(nr))
    freq_c = fftshift(fftfreq(nc))
    pos_freq = np.linspace(0, np.hypot(freq_r[-1], freq_c[-1]), 
        pol_psd.shape[1])

    if doplot:
        fig,ax = pp.subplots(2,2)

        im0 = ax[0,0].imshow(img*win, cmap=pp.cm.gray)
        ax[0,0].set_axis_off()
        ax[0,0].set_title('Windowed image')

        lnorm = LogNorm(vmin=psd.min(), vmax=psd.max())
        ax[0,1].set_axis_bgcolor('k')
        im1 = ax[0,1].imshow(psd, extent=(freq_c[0], freq_c[-1], 
            freq_r[0], freq_r[-1]), aspect='auto', 
            cmap=pp.cm.hot, norm=lnorm)
        # cb1 = pp.colorbar(im1, ax=ax[0,1], use_gridspec=True)
        # cb1.set_label('Power (A.U.)')
        ax[0,1].set_title('2D power spectrum')

        ax[1,0].set_axis_bgcolor('k')
        im2 = ax[1,0].imshow(pol_psd, cmap=pp.cm.hot, norm=lnorm, 
            extent=(pos_freq[0],pos_freq[-1],0,360), 
            aspect='auto')
        ax[1,0].set_ylabel('Angle (deg)')
        ax[1,0].set_xlabel('Frequency (cycles/px)')
        # cb2 = pp.colorbar(im2, ax=(ax[0,1],ax[1,1]), use_gridspec=True)
        # cb2.set_label('Power (A.U.)')
        ax[1,0].set_title('Polar-transformed power spectrum')

        ax[1,1].hold(True)
        # ax[1,1].fill_between(pos_freq, mpow - stdpow, mpow + stdpow, 
        #   color='r', alpha=0.3)
        ax[1,1].axvline(0, c='k', ls='--', alpha=0.3)
        ax[1,1].plot(pos_freq, mpow, lw=3, c='r')
        ax[1,1].set_xlabel('Frequency (cycles/px)')
        ax[1,1].set_ylabel('Power (A.U.)')
        ax[1,1].set_yscale('log')
        ax[1,1].set_xlim(-0.05, None)
        ax[1,1].set_title('1D power spectrum')

        fig.tight_layout()

    return mpow, stdpow, pos_freq

def make2DWindow(shape,winfunc,*args,**kwargs):
    assert callable(winfunc)
    r,c = shape
    rvec = winfunc(r,*args,**kwargs)
    cvec = winfunc(c,*args,**kwargs)
    return np.outer(rvec,cvec)

def polar_transform(image, centre=(0,0), n_angles=None, n_radii=None):
    """
    Polar transformation of an image about the specified centre coordinate
    """
    shape = image.shape
    if n_angles is None:
        n_angles = shape[0]
    if n_radii is None:
        n_radii = shape[1]
    theta = -np.linspace(0, 2*np.pi, n_angles, endpoint=False).reshape(-1,1)
    d = np.hypot(shape[0]-centre[0], shape[1]-centre[1])
    radius = np.linspace(0, d, n_radii).reshape(1,-1)
    x = radius * np.sin(theta) + centre[0]
    y = radius * np.cos(theta) + centre[1]

    # nb: map_coordinates can give crazy negative values using higher order
    # interpolation, which introduce nans when you take the log later on
    output = map_coordinates(image, [x, y], order=1, cval=np.nan, 
        prefilter=True)
    return output




spectrum