So, I have this problem where I want to apply a kernel to an image and count the number of matches that happened.
So for example, if I have the kernel: $$\begin{bmatrix} 1 & 2 & 1\\ 1 & 2 & 1\\ 1 & 2 & 1\\ \end{bmatrix}$$ And the image: $$\begin{bmatrix} 1 & 1 & 2 & 1 & 2\\ 1 & 1 & 2 & 1 & 2\\ 1 & 1 & 2 & 1 & 2\\ \end{bmatrix}$$ The result should be (ignoring the borders): $$\begin{bmatrix} 3 & 9 & 0\\ \end{bmatrix}$$ Explanation: when the kernel is in the first position (2,2), the 3 left ones match to the kernel, in the middle position (3,2) all 9 elements match and in the right (4,2) there is no match.
I ended up doing two convolutions (or correlations), one to count the numner of ones and one to count the number of twos.
For example: First convolution (to count where value is 1): $$\begin{bmatrix} 1 & 0 & 1\\ 1 & 0 & 1\\ 1 & 0 & 1\\ \end{bmatrix}$$ $$\begin{bmatrix} 1 & 1 & 0 & 1 & 0\\ 1 & 1 & 0 & 1 & 0\\ 1 & 1 & 0 & 1 & 0\\ \end{bmatrix}$$ Result: $$\begin{bmatrix} 3 & 6 & 0 \end{bmatrix}$$ Second convolution (to count where value is 2): $$\begin{bmatrix} 0 & 1 & 0\\ 0 & 1 & 0\\ 0 & 1 & 0\\ \end{bmatrix}$$ $$\begin{bmatrix} 0 & 0 & 1 & 0 & 1\\ 0 & 0 & 1 & 0 & 1\\ 0 & 0 & 1 & 0 & 1\\ \end{bmatrix}$$ Result: $$\begin{bmatrix} 0 & 3 & 0 \end{bmatrix}$$
At the end I add up the results to get the expected result. The problem is that if my image has 256 values, I have to do that 256 times and it becomes 256x slower than a convolution. Still, this ends up being faster than doing for loops and checking all kernel positions. This is partly due to the fourier transform that makes convolution faster.
My question is if it is possible to apply this operation faster? Maybe by just modifying the convolution a little bit?
EDIT: My kernel has maximum size 64x64 and my image has size around 300x300. If I use the standard kernel convolution (Direct Convolution), then it will try to match the kernel for every position of the image. To match the kernel it takes 64x64 comparisons, and it will do that for every position in the image (300x300), so this will take 300x300x64x64 comparisons (total 368.640.000 operations).
If I compute first the fourier transform of the images (FFT Convolution), then I can do the multiplication directly and it will cost only (300x300 operations). There is a cost to compute the fourier of the images in the first place, so at the end it will take around 300x300xlog(300)xlog(300) operations (this takes a total of around 500.000 operations).
OpenCV has a convolution method (filter2D) and a template matching method (matchTemplate) that are very fast, and I believe they use fourier plus some other optimizations.
The function matchTemplate in OpenCv has different methods to compute the match https://www.docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/template_matching/template_matching.html, but none of them work for what I need.
What I need is a function to count the matches, and I want to know if it is possible to that similar to other template matching methods in opencv (that I assume use the FFT Convolution).
An approximate result should be fine, so if the output for the first example is, lets say, [3.28, 9.45, 0.32], it shouldn't be a problem.