Where's Waldo?

We will use FLCC to find Waldo

using FastLocalCorrelationCoefficients, Images


img = mktemp() do fn,f
    download("https://i.stack.imgur.com/reNlF.jpg", fn)
    load(fn)
end

Our template is a noisy, darkened version of Waldo

waldo = 0.5 .* img[140:200, 160:195] .+ Gray.( 0.2*rand(200-140+1, 195-160+1) )

Transform the images into 3D tensors

T = permutedims( Float64.( collect( channelview(waldo) ) ), [2 3 1] );
F = permutedims( Float64.( collect( channelview(img) ) ), [2 3 1] );
768×1024×3 Array{Float64, 3}:
[:, :, 1] =
 1.0       0.772549  0.34902   0.654902  …  0.298039  0.772549  0.941176
 1.0       0.94902   0.501961  0.470588     0.631373  0.929412  0.929412
 0.984314  1.0       0.803922  0.423529     0.92549   0.917647  0.921569
 0.988235  0.984314  1.0       0.788235     0.941176  0.933333  0.905882
 0.894118  0.984314  1.0       1.0          0.576471  0.819608  0.72549
 0.811765  1.0       0.980392  0.976471  …  0.407843  0.541176  0.490196
 0.945098  0.996078  1.0       0.996078     0.556863  0.592157  0.717647
 1.0       1.0       1.0       1.0          0.494118  0.380392  0.545098
 0.976471  1.0       0.996078  1.0          0.470588  0.623529  0.831373
 0.737255  1.0       1.0       0.988235     0.623529  0.788235  1.0
 ⋮                                       ⋱                      
 0.964706  1.0       1.0       0.843137     0.498039  0.560784  0.815686
 1.0       1.0       1.0       0.623529  …  0.45098   0.592157  0.803922
 0.827451  0.984314  1.0       1.0          0.509804  0.482353  0.803922
 0.596078  0.745098  0.901961  1.0          0.631373  0.364706  0.784314
 0.952941  0.694118  0.505882  0.490196     0.882353  0.419608  0.380392
 1.0       0.960784  0.643137  0.517647     1.0       0.796078  0.333333
 1.0       1.0       0.882353  0.568627  …  0.992157  0.929412  0.72549
 0.972549  1.0       1.0       0.631373     0.945098  0.741176  0.784314
 0.976471  0.972549  1.0       0.94902      0.956863  0.756863  0.760784

[:, :, 2] =
 0.964706  0.737255  0.356863  0.698039  …  0.270588  0.756863  0.92549
 0.984314  0.921569  0.509804  0.501961     0.596078  0.894118  0.894118
 0.960784  1.0       0.807843  0.443137     0.87451   0.858824  0.862745
 0.968627  0.980392  1.0       0.796078     0.866667  0.85098   0.811765
 0.886275  0.976471  1.0       1.0          0.486275  0.709804  0.611765
 0.803922  0.992157  0.964706  0.956863  …  0.298039  0.419608  0.352941
 0.929412  0.980392  0.996078  0.972549     0.45098   0.454902  0.568627
 0.976471  0.984314  0.996078  0.980392     0.388235  0.25098   0.396078
 0.929412  0.988235  0.984314  1.0          0.372549  0.501961  0.698039
 0.623529  0.917647  0.992157  0.984314     0.533333  0.678431  0.905882
 ⋮                                       ⋱                      
 0.960784  0.992157  0.956863  0.780392     0.498039  0.666667  0.980392
 0.960784  0.964706  0.980392  0.537255  …  0.454902  0.709804  0.992157
 0.729412  0.882353  0.909804  0.917647     0.498039  0.588235  0.968627
 0.447059  0.603922  0.764706  0.913725     0.580392  0.407843  0.882353
 0.8       0.545098  0.360784  0.333333     0.819608  0.435294  0.431373
 0.968627  0.847059  0.513725  0.34902      0.984314  0.803922  0.376471
 0.952941  0.984314  0.772549  0.396078  …  0.972549  0.968627  0.792157
 0.980392  0.984314  0.952941  0.466667     0.976471  0.839216  0.917647
 1.0       0.972549  0.980392  0.788235     1.0       0.882353  0.92549

[:, :, 3] =
 0.964706  0.709804  0.262745  0.541176    …  0.239216  0.721569  0.890196
 0.992157  0.898039  0.423529  0.356863       0.568627  0.866667  0.866667
 0.968627  0.980392  0.737255  0.317647       0.843137  0.831373  0.835294
 0.984314  0.972549  0.956863  0.709804       0.843137  0.831373  0.796078
 0.905882  0.980392  0.980392  0.956863       0.462745  0.694118  0.596078
 0.815686  0.996078  0.960784  0.945098    …  0.282353  0.407843  0.345098
 0.917647  0.976471  1.0       0.988235       0.423529  0.439216  0.556863
 0.945098  0.960784  0.992157  1.0            0.360784  0.231373  0.384314
 0.866667  0.941176  0.956863  0.992157       0.352941  0.490196  0.690196
 0.552941  0.85098   0.952941  0.964706       0.509804  0.662745  0.890196
 ⋮                                         ⋱                      
 0.160784  0.184314  0.156863  0.00784314     0.490196  0.701961  1.0
 0.203922  0.2       0.219608  0.0         …  0.435294  0.74902   1.0
 0.12549   0.266667  0.254902  0.27451        0.470588  0.615686  1.0
 0.129412  0.235294  0.294118  0.392157       0.545098  0.415686  0.909804
 0.670588  0.360784  0.054902  0.0            0.768627  0.431373  0.454902
 0.941176  0.776471  0.352941  0.133333       0.94902   0.8       0.392157
 0.960784  0.956863  0.690196  0.282353    …  0.94902   0.976471  0.819608
 0.960784  0.952941  0.898039  0.380392       0.984314  0.866667  0.956863
 0.984314  0.941176  0.937255  0.717647       1.0       0.92549   0.980392

First, we show that the un-normalized convolution is unable to locate Waldo

R = FastLocalCorrelationCoefficients.fcorr( F, T );
R = R[CartesianIndex((size(T))):CartesianIndex(size(F))][:,:,1]
R = R / maximum(R)
Gray.( R )

The position with the maximum value is not Waldo.

idx_R = best_correlated( R ) .+ (CartesianIndex(0,0):CartesianIndex(70, 35))
img[idx_R]

Next, we compute FLCC and visualize the correlations.

M = flcc( F, T )[:,:,1];

Gray.( (M .+ 1) ./ 2 )

We found Waldo!

idx = best_correlated( M ) .+ (CartesianIndex(0,0):CartesianIndex(70, 35))
img[idx]