I want to iterate over all pixel of an image and compare with a search pattern. With best performance possible and in C#. I found emgu cv, a wrapper for Intels opencv. But I
I wanted to supplement the already thorough answer of @Luce Del Tongo and @Dent7777 with one further solution for per-value operations on image data using emgucv. Whilst my testing (same method) shows only equivalent performance to that of the final solution above; I believe that it's a valuable alternative.
The Image.Convert() method has a number of powerful overloads that can be used to apply delegate Functions per-value on the calling image to return a resulting image of the same or differing TDepth. See "Generic Operation" at http://www.emgu.com/wiki/index.php/Working_with_Images for more detail.
Most significant is the ability to pass up to three additional images as parameters to the Convert method, the contained data of which will be passed to the delegate.
For example, a complex filter:
// From the input image "original"
Image original = new Image(1024, 768);
// I wish to produce an image "result"
Image result = new Image(1024, 768);
// Whereby each "result" pixel is
Bgr originalPixel;
double resultPixel =
(0.5 + Math.Log(originalPixel.Green) -
(0.5 * Math.Log(originalPixel.Red)) -
(0.5 * Math.Log(originalPixel.Blue)));
To use the solution provided in previous answer:
byte[,,] sourceData = original.Data;
double[,,] resultData = result.Data;
for (int i = original.Rows - 1; i >= 0; i--)
{
for (int j = original.Cols - 1; j >= 0; j--)
{
resultData[i,j,0] =
(0.5 + Math.Log(sourceData[i, j, 1]) -
(0.5 * Math.Log(sourceData[i, j, 2])) -
(0.5 * Math.Log(sourceData[i, j, 0])));
}
}
Average Time on my machine: (676ms)
Alternatively, I can call Convert on the Blue channel of the original, passing the other two channels as parameters, along with a delegate method of corresponding signature to perform my computation:
result =
original[0].Convert(
original[1],
original[2],
Compute);
Where:
private double Compute(byte B, byte G, byte R)
{
return (0.5 + Math.Log(G) - (0.5 * Math.Log(R)) - (0.5 * Math.Log(B)));
}
Average Time on my machine: (674ms)
Perhaps just personal preference, but I hope this may be of value to someone somewhere.