问题
I Need fastest way to iterate an EmguCV bitmap matrix and set pixel. i found this after google but it takes about 3 sec for 700x500 image:
Documents says that access (get) data matrix is just o(1) but its not clearly declare about set data.
for(int i = 0; i < img.Rows ; i++)
for(int j = 0; j < img.Cols; j++){
img.Data[x,y,0] = 255;
img.Data[x,y,1] = 255;
img.Data[x,y,2] = 255;
}
Thanks in advance.
回答1:
The getter for Emgu.CV.Image<>'s Data property returns a reference to the three-dimension array that is used internally by the class. When you assign to an element of that array (as you are doing in the code above) you are not calling the setter for the Data property, you are manipulating the array itself.
I suspect that the slowdown you are experiencing is related to calling unmanaged code, since the EmguCV code is largely unmanaged.
Try this and see if there is any change in speed:
Byte[,,] data = img.Data;
int rows = img.Rows;
int cols = img.Cols;
for (int y = 0; y < rows; ++i)
{
for (int x = 0; x < cols; ++x)
{
data[x, y, 0] = 255;
data[x, y, 1] = 255;
data[x, y, 2] = 255;
}
}
Also the Image class has a method SetValue that sets every pixel to a specific value. If what you are trying to achieve is to clear the image to white, try calling img.SetValue(new Rgb(255,255,255)) (or whichever color type you're using for the image) instead of doing it manually. May be quicker.
回答2:
for (int y = 0; y < rows; y++)
{
for (int x = 0; x < cols; x++)
{
b = (int)frameClone.Data[y, x, 0];
g = (int)frameClone.Data[y, x, 1];
r = (int)frameClone.Data[y, x, 2];
}
currIntensity = b + g + r;
}
回答3:
It is much faster to convert your Emgu.Cv.Image to System.Drawing.Bitmap and iterate through the bitmap, either using safe or unsafe method.
The safe method uses
color.toargb = bmp.getpixel(X, Y).toargb / bmp.setpixel(X, Y).toargband it is fairly straight forward.
- The unsafe method is super fast, relies on
bmp.lockbits(bmp_data)andinteropservices.marshalto copy bmp data to array. You can find tons of examples online.
I am very disappointed with EmguCV 3.0 pixel access.
回答4:
Here is a method I use to replace color, it replaces any color given that is not within a given (difference) to the desired one. Its very fast, uses unsafe
/// <summary>
/// Replaces a given color in a bitmap
/// </summary>
/// <param name="image"></param>
/// <returns></returns>
public static unsafe void ReplaceColor(Bitmap image,
Color FindColor,
int WithinDistance,
Color ReplaceColor
)
{
byte FindColorR = (byte)FindColor.R;
byte FindColorG = (byte)FindColor.G;
byte FindColorB = (byte)FindColor.B;
byte ReplaceColorR = (byte)ReplaceColor.R;
byte ReplaceColorG = (byte)ReplaceColor.G;
byte ReplaceColorB = (byte)ReplaceColor.B;
byte WithinDistanceByte = (byte)WithinDistance;
BitmapData imageData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
int bytesPerPixel = 3;
byte* scan0 = (byte*)imageData.Scan0.ToPointer();
int stride = imageData.Stride;
PixelData NewData = new PixelData(image.Height,image.Size);
for (int y = 0; y < imageData.Height; y++)
{
byte* row = scan0 + (y * stride);
for (int x = 0; x < imageData.Width; x++)
{
int bIndex = x * bytesPerPixel;
int gIndex = bIndex + 1;
int rIndex = bIndex + 2;
byte pixelR = row[rIndex];
byte pixelG = row[gIndex];
byte pixelB = row[bIndex];
if( Math.Abs(FindColorR - pixelR) > WithinDistanceByte &&
Math.Abs(FindColorG - pixelG) > WithinDistanceByte &&
Math.Abs(FindColorB - pixelB) > WithinDistanceByte )
{
row[rIndex] = ReplaceColorR;
row[gIndex] = ReplaceColorG;
row[bIndex] = ReplaceColorB;
}
else
{
row[rIndex] = FindColorR;
row[gIndex] = FindColorG;
row[bIndex] = FindColorB;
}
}
}
image.UnlockBits(imageData);
}
来源:https://stackoverflow.com/questions/15045295/emgucv-fastest-set-pixel