Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
378 views
in Technique[技术] by (71.8m points)

c# - Iterate over pixels of an image with emgu cv

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 don't know how to use emgu properly. Does anybody know how I can do this? What is the data Property of Image? Is this the imagedata? If yes, which value is what? Thanks

Update:

I coded my function in C# and it worked well, but way too slow! I had already an algorhytm in c which I translated into C#. C# is 3 to 4 TIMES slower than c! (My function iterates over almost every pixel of an image to seek a shape in an image. -> Hugh Transformation)

Well, I heard that unsafe code could be faster because it does not check array boundries and stuff. Is that true? Runs unsafe code directly on the physically machine?

Anyway, I tried to put unsafe code into my function. But I was not able to get a pointer to my 3D-array or to access the 3D-array with the pointer. How can I rewrite this code from above with unsafe code? And would this bring an additional performance boost or even run as fast as c-code?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As emgu website state there are primarly two strategies:

The safe (slow) way

Suppose you are working on an Image<Bgr, Byte>. You can obtain the pixel on the y-th row and x-th column by calling

Bgr color = img[y, x];

Setting the pixel on the y-th row and x-th column is also simple

img[y,x] = color;

The fast way

The Image pixels values are stored in the Data property, a 3D array. Ok so this is true but does not tell how to do it in a real scenario. So let's see some working code and then discuss performance and optimization:

Image<Bgr, Byte> original = newImage<Bgr, byte>(1024, 768);
Stopwatch evaluator = newStopwatch(); 

int repetitions = 20;
Bgr color = newBgr(100, 40, 243);

evaluator.Start();

for (int run = 0; run < repetitions; run++)
{
    for (int j = 0; j < original.Cols; j++)
    {
        for (int i = 0; i < original.Rows; i++)
        {
            original[i, j] = color;
        }
    }
}

evaluator.Stop();
Console.WriteLine("Average execution time for {0} iteration 
 using column per row access: {1}ms
", repetitions, evaluator.ElapsedMilliseconds / repetitions);

So this is the average running time that you have after 20 runs using the safe slow way of setting image pixel On my machine it takes 1021ms...

So 1021 milliseconds as average time for looping and setting a number of pixels equal to 1024*768. We could have done a little bit better by looping on row by row

So let's refactor a little bit our code and let's use the faster way using directly Image.Data property:

evaluator.Reset();
evaluator.Start();

for (int run = 0; run < repetitions; run++)
{
    for (int i = 0; i < original.Rows; i++)
    {
        for (int j = 0; j < original.Cols; j++)
        {
            original.Data[i, j, 0] = 100;
            original.Data[i, j, 1] = 40;
            original.Data[i, j, 2] = 243;
        }
    }
}

evaluator.Stop();
Console.WriteLine("Average execution time for {0} iterations 
 using Data property: {1}ms
", repetitions, evaluator.ElapsedMilliseconds / repetitions);

On my machine it takes 519ms. So we have gained a performance boost of 50%. The execution time has been decreased by a factor of two.

So looking carefully at the code keeping in mind that we are using C#, we can do a minor change that will drastically boost again our image pixel setting performance... we should not use c# property inside a loop!!!

evaluator.Reset();
evaluator.Start();

byte[,,] data = original.Data;

for (int run = repetitions - 1; run >= 0; run--)
{
    for (int i = original.Rows - 1; i >= 0; i--)
    {
        for (int j = original.Cols - 1; j >= 0; j--)
        {
            data[i, j, 0] = 100;
            data[i, j, 1] = 40;
            data[i, j, 2] = 243;
        }
    }
}

evaluator.Stop();

With this latest piece of code you will have a huge performance boost (73ms) due to correct use of C# language.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...