dft.py 2.8 KB
Newer Older
1
#!/usr/bin/env python
2

flp's avatar
flp committed
3 4 5 6 7 8 9 10
'''
sample for disctrete fourier transform (dft)

USAGE:
    dft.py <image_file>
'''


11 12 13
# Python 2/3 compatibility
from __future__ import print_function

14
import numpy as np
15 16
import cv2 as cv

17 18 19 20 21 22
import sys


def shift_dft(src, dst=None):
    '''
        Rearrange the quadrants of Fourier image so that the origin is at
Andrey Kamaev's avatar
Andrey Kamaev committed
23 24
        the image center. Swaps quadrant 1 with 3, and 2 with 4.

25 26
        src and dst arrays must be equal size & type
    '''
Andrey Kamaev's avatar
Andrey Kamaev committed
27

28 29 30 31 32 33
    if dst is None:
        dst = np.empty(src.shape, src.dtype)
    elif src.shape != dst.shape:
        raise ValueError("src and dst must have equal sizes")
    elif src.dtype != dst.dtype:
        raise TypeError("src and dst must have equal types")
Andrey Kamaev's avatar
Andrey Kamaev committed
34

35 36 37 38
    if src is dst:
        ret = np.empty(src.shape, src.dtype)
    else:
        ret = dst
Andrey Kamaev's avatar
Andrey Kamaev committed
39

40
    h, w = src.shape[:2]
Andrey Kamaev's avatar
Andrey Kamaev committed
41

42 43
    cx1 = cx2 = w // 2
    cy1 = cy2 = h // 2
Andrey Kamaev's avatar
Andrey Kamaev committed
44

45 46 47 48
    # if the size is odd, then adjust the bottom/right quadrants
    if w % 2 != 0:
        cx2 += 1
    if h % 2 != 0:
Andrey Kamaev's avatar
Andrey Kamaev committed
49 50
        cy2 += 1

51
    # swap quadrants
Andrey Kamaev's avatar
Andrey Kamaev committed
52

53 54 55
    # swap q1 and q3
    ret[h-cy1:, w-cx1:] = src[0:cy1 , 0:cx1 ]   # q1 -> q3
    ret[0:cy2 , 0:cx2 ] = src[h-cy2:, w-cx2:]   # q3 -> q1
Andrey Kamaev's avatar
Andrey Kamaev committed
56

57 58 59
    # swap q2 and q4
    ret[0:cy2 , w-cx2:] = src[h-cy2:, 0:cx2 ]   # q2 -> q4
    ret[h-cy1:, 0:cx1 ] = src[0:cy1 , w-cx1:]   # q4 -> q2
Andrey Kamaev's avatar
Andrey Kamaev committed
60

61 62
    if src is dst:
        dst[:,:] = ret
Andrey Kamaev's avatar
Andrey Kamaev committed
63

64 65
    return dst

Andrey Kamaev's avatar
Andrey Kamaev committed
66

67
def main():
flp's avatar
flp committed
68
    if len(sys.argv) > 1:
69
        fname = sys.argv[1]
flp's avatar
flp committed
70
    else:
71
        fname = 'baboon.jpg'
72
        print("usage : python dft.py <image_file>")
73

74 75
    im = cv.imread(cv.samples.findFile(fname))

76
    # convert to grayscale
77
    im = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
78
    h, w = im.shape[:2]
Andrey Kamaev's avatar
Andrey Kamaev committed
79

80
    realInput = im.astype(np.float64)
Andrey Kamaev's avatar
Andrey Kamaev committed
81

82
    # perform an optimally sized dft
83 84
    dft_M = cv.getOptimalDFTSize(w)
    dft_N = cv.getOptimalDFTSize(h)
85 86 87 88

    # copy A to dft_A and pad dft_A with zeros
    dft_A = np.zeros((dft_N, dft_M, 2), dtype=np.float64)
    dft_A[:h, :w, 0] = realInput
Andrey Kamaev's avatar
Andrey Kamaev committed
89

90
    # no need to pad bottom part of dft_A with zeros because of
91 92
    # use of nonzeroRows parameter in cv.dft()
    cv.dft(dft_A, dst=dft_A, nonzeroRows=h)
Andrey Kamaev's avatar
Andrey Kamaev committed
93

94
    cv.imshow("win", im)
Andrey Kamaev's avatar
Andrey Kamaev committed
95

96
    # Split fourier into real and imaginary parts
97
    image_Re, image_Im = cv.split(dft_A)
Andrey Kamaev's avatar
Andrey Kamaev committed
98

99
    # Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2)
100
    magnitude = cv.sqrt(image_Re**2.0 + image_Im**2.0)
Andrey Kamaev's avatar
Andrey Kamaev committed
101

102
    # Compute log(1 + Mag)
103
    log_spectrum = cv.log(1.0 + magnitude)
Andrey Kamaev's avatar
Andrey Kamaev committed
104

105 106 107 108 109
    # Rearrange the quadrants of Fourier image so that the origin is at
    # the image center
    shift_dft(log_spectrum, log_spectrum)

    # normalize and display the results as rgb
110 111
    cv.normalize(log_spectrum, log_spectrum, 0.0, 1.0, cv.NORM_MINMAX)
    cv.imshow("magnitude", log_spectrum)
112

113
    cv.waitKey(0)
114 115 116 117 118 119
    print('Done')


if __name__ == '__main__':
    print(__doc__)
    main()
120
    cv.destroyAllWindows()