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;
        }

提前谢谢。

EMGUCV设置最快的像素

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);
    }