フーリエ変換
ローパスフィルタ・ハイパスフィルタ・バンドパスフィルタ
library( imager )
clamp = function( array, min, max ){
array[ array < min ] = min
array[ array > max ] = max
return( array )
}
swapPixels = function( img, reverse = FALSE ){
a = as.array( img )
w = width( img )
h = height( img )
midx.minus1 = floor( w / 2 )
midy.minus1 = floor( h / 2 )
if( mod( w, 2 ) == 0 ){
left = a[ 1:midx.minus1+0, , , ]
a[ 1:midx.minus1+0, , , ] = a[ (midx.minus1+1):w, , , ]
a[ (midx.minus1 + 1):w, , , ] = left
} else {
if( reverse ){
left = a[ 1:midx.minus1+0, , , ]
a[ 1:(midx.minus1+1), , , ] = a[ (midx.minus1+1):w, , , ]
a[ (midx.minus1+2):w, , , ] = left
} else {
left = a[ 1:(midx.minus1+1), , , ]
a[ 1:midx.minus1+0, , , ] = a[ (midx.minus1+2):w, , , ]
a[ (midx.minus1+1):w, , , ] = left
}
}
if( mod( h, 2 ) == 0 ){
top = a[ , 1:midy.minus1, , ]
a[ , 1:midy.minus1, , ] = a[ , (midy.minus1 + 1):h, , ]
a[ , (midy.minus1 + 1):h, , ] = top
} else {
if( reverse ){
top = a[ , 1:midy.minus1, , ]
a[ , 1:(midy.minus1 + 1), , ] = a[ , (midy.minus1 + 1):h, , ]
a[ , (midy.minus1 + 2):h, , ] = top
} else {
top = a[ , 1:(midy.minus1 + 1), , ]
a[ , 1:(midy.minus1 + 0), , ] = a[ , (midy.minus1 + 2):h, , ]
a[ , (midy.minus1 + 1):h, , ] = top
}
}
img = as.cimg( a, dim = dim( img ) )
return( img )
}
highpass = function( img, cyclePerImage, smoothing = F ){
img = swapPixels( img, reverse = F )
a = as.vector( img )
w = width( img )
h = height( img )
origin.x = floor( w / 2 ) + 1
origin.y = floor( h / 2 ) + 1
radius2 = cyclePerImage^2
for( x in 1:w ){
for( y in 1:h ){
x2 = x - w / 2 - 1
y2 = y - h / 2 - 1
if( smoothing ){
if( !(x == origin.x & y == origin.y) ){
sigma = 1/(2*pi*cyclePerImage)
weight = 1 - exp(-2*pi*sigma^2*(x2^2+y2^2))
a[ x + (y-1) * w ] = weight * a[ x + (y-1) * w ]
}
} else {
if( x2^2 / radius2 + y2^2 / radius2 < 1 ){
if( !(x == origin.x & y == origin.y) ){
a[ x + (y-1) * w ] = 0
}
}
}
}
}
img = as.cimg( a, x = w, y = h, z = 1, cc = 1 )
img = swapPixels( img, reverse = T )
return( img )
}
lowpass = function( img, cyclePerImage, smoothing = F ){
img = swapPixels( img, reverse = F )
a = as.vector( img )
w = width( img )
h = height( img )
origin.x = floor( w / 2 ) + 1
origin.y = floor( h / 2 ) + 1
radius2 = cyclePerImage^2
for( x in 1:w ){
for( y in 1:h ){
x2 = x - w / 2 - 1
y2 = y - h / 2 - 1
if( smoothing ){
if( !(x == origin.x & y == origin.y) ){
sigma = 1/(2*pi*cyclePerImage)
weight = exp(-2*pi*sigma^2*(x2^2+y2^2))
a[ x + (y-1) * w ] = weight * a[ x + (y-1) * w ]
}
} else {
if( x2^2 / radius2 + y2^2 / radius2 > 1 ){
a[ x + (y-1) * w ] = 0
}
}
}
}
img = as.cimg( a, x = w, y = h, z = 1, cc = 1 )
img = swapPixels( img, reverse = T )
return( img )
}
bandpass = function( ff, cyclePerImage, bandwidth = 2, smoothing = F ){
low = cyclePerImage * 2^(-bandwidth/2)
high = cyclePerImage * 2^(+bandwidth/2)
ff = lapply( ff, highpass, cyclePerImage = low, smoothing = smoothing )
ff = lapply( ff, lowpass, cyclePerImage = high, smoothing = smoothing )
return( ff )
}
as.fftMagnitude = function( ff, clamp = F ){
p = sqrt( ff$real^2 + ff$imag^2 )
if( clamp ){
max_ = min( quantile( p, (10^(1:9)-1)/10^(1:9) )[ quantile( p, (10^(1:9)-1)/10^(1:9) ) > 0 ] )
p = clamp( p, min = 0, max = max_ )
return( p )
} else {
return( p )
}
}
as.fftPhase = function( ff, clamp = F ){
p = atan2( ff$imag, ff$real )
if( clamp ){
max_ = min( quantile( p, (10^(1:9)-1)/10^(1:9) )[ quantile( p, (10^(1:9)-1)/10^(1:9) ) > 0 ] )
p = clamp( p, min = 0, max = max_ )
return( p )
} else {
return( p )
}
}
as.phaseScrampled = function( img ){
ff = FFT( img )
ff.magnitude = as.fftMagnitude( ff )
# ff.phase = as.fftPhase( ff )
ff.phase2 = as.cimg( (runif(width(img)*height(img))-.5)/.5*pi, x = width(img), y = height(img), z = 1, cc = 1 )
ff.real = ff.magnitude * cos( ff.phase2 )
ff.imag = ff.magnitude * sin( ff.phase2 )
check = FFT( ff.real, ff.imag, inverse = TRUE )$real
return( check )
# m0 = as.fftMagnitude( ff )
# m1 = as.fftMagnitude( FFT( check ) )
# m = sqrt( ff.real^2 + ff.imag^2 )
# print( mean( ( m0 - m1 )^2 ) )
# print( mean( ( m0 - m )^2 ) )
# mean( ( check - img )^2 )
# layout(t(1:4))
# plot( img, rescale = F )
# plot( check, rescale = T )
# plot( swapPixels( as.fftMagnitude( ff, clamp = T ) ), rescale = T, main="Power spectrum", cex.main = 2 )
# plot( swapPixels( as.fftMagnitude( FFT( check ), clamp = T ) ), rescale = T, main="Power spectrum", cex.main = 2 )
# plot( img, rescale = F )
}
freqFilter = function( img, scheme, cyclePerImage, smoothing = F, bandwidth = 2 ){
if( scheme == "highpass" ){
ff = lapply( FFT( img ), highpass, cyclePerImage = cyclePerImage, smoothing = smoothing )
} else if( scheme == "lowpass" ){
ff = lapply( FFT( img ), lowpass, cyclePerImage = cyclePerImage, smoothing = smoothing )
} else if( scheme == "bandpass" ){
ff = bandpass( FFT( img ), cyclePerImage = cyclePerImage, smoothing = smoothing, bandwidth = bandwidth )
} else {
return( img )
}
out = FFT( ff$real, ff$imag, inverse = TRUE )$real
return( out )
}
#
inputImg = boats
img = grayscale( inputImg )
low = freqFilter( img, scheme = "lowpass", cyclePerImage = 6, smoothing = T )
high = freqFilter( img, scheme = "highpass", cyclePerImage = 28, smoothing = T )
band = freqFilter( img, scheme = "bandpass", cyclePerImage = 15, smoothing = T, bandwidth = 2 )
plot( imlist( input = inputImg, lowpass = low, highpass = high, bandpass = band ) )

コメント
始めに示されている画像のフーリエ変換のパワースペクトルの表示方法を教えていただけないでしょうか。どうぞよろしくお願いします。
後日加筆します。