EMGUCV设置最快的像素
本文关键字:像素 设置 EMGUCV | 更新日期: 2023-09-27 18:00:39
我需要最快的方法来迭代EmguCV位图矩阵并设置像素。我在谷歌上找到了这个,但700x500图片需要大约3秒:
文献指出,访问(get)数据矩阵只是o(1),但它并没有明确声明集合数据。
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;
}
提前谢谢。
Emgu.CV.Image<>
的Data
属性的getter返回对该类内部使用的三维数组的引用。当您分配给该数组的一个元素时(正如您在上面的代码中所做的那样),您不是在为Data
属性调用setter,而是在操纵数组本身。
我怀疑您所经历的速度减慢与调用非托管代码有关,因为EmguCV代码在很大程度上是非托管的。
试试这个,看看速度是否有任何变化:
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;
}
}
此外,Image
类具有将每个像素设置为特定值的方法SetValue
。如果您试图实现的是将图像清除为白色,请尝试调用img.SetValue(new Rgb(255,255,255))
(或图像使用的任何颜色类型),而不是手动执行。可能会更快。
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;
}
使用安全或不安全的方法将Emgu.Cv.Image
转换为System.Drawing.Bitmap
并迭代位图会快得多。
-
安全方法使用
color.toargb = bmp.getpixel(X, Y).toargb / bmp.setpixel(X, Y).toargb
它是相当直接的。
- 这种不安全的方法速度极快,依赖于
bmp.lockbits(bmp_data)
和interopservices.marshal
将bmp数据复制到数组中。你可以在网上找到很多例子
我对EmguCV 3.0像素访问感到非常失望。
这里有一个我用来替换颜色的方法,它将不在给定(差异)范围内的任何给定颜色替换为所需颜色。它非常快,使用不安全的
/// <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);
}