0

我需要最快的方法来迭代 EmguCV 位图矩阵并设置像素。我在谷歌之后发现了这个,但对于 700x500 图像大约需要 3 秒:

文档说访问(获取)数据矩阵只是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;

        }


提前致谢。

4

4 回答 4

3

Emgu.CV.Image<>的属性的 getterData返回对类内部使用的三维数组的引用。当您分配给该数组的元素时(正如您在上面的代码中所做的那样),您并没有调用Data属性的设置器,而是在操作数组本身。

我怀疑您遇到的减速与调用非托管代码有关,因为 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))(或您用于图像的任何颜色类型)而不是手动执行。可能会更快。

于 2013-02-23T21:55:52.293 回答
1
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;
}
于 2014-11-17T02:44:59.593 回答
1

Emgu.Cv.Image使用安全或不安全的方法转换位System.Drawing.Bitmap图并遍历位图要快得多。

  • 安全方法使用

    color.toargb = bmp.getpixel(X, Y).toargb / bmp.setpixel(X, Y).toargb 
    

    这是相当直截了当的。

  • unsafe 方法超级快,依赖bmp.lockbits(bmp_data)并将interopservices.marshalbmp 数据复制到数组。你可以在网上找到大量的例子。

我对 EmguCV 3.0 像素访问感到非常失望。

于 2016-01-24T22:27:39.850 回答
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);
    }
于 2017-12-06T08:07:39.367 回答