问题
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).toargb
and it is fairly straight forward.
- The unsafe method is super fast, relies on
bmp.lockbits(bmp_data)
andinteropservices.marshal
to 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