2013-02-23 219 views
0

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

文档说access(get)数据矩阵只是o(1),但它没有清楚地声明set数据。

 


    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; 

     } 

 

在此先感谢。

回答

3

Emgu.CV.Image<>Data属性的获取方法返回对该类内部使用的三维数组的引用。当你分配给该数组的一个元素时(正如你在上面的代码中所做的那样),你并没有调用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))(或您为图像使用的任何颜色类型),而不是手动进行。可能会更快。

+1

只是快一点。它可以节省约1秒。 – 2013-02-24 07:57:01

+0

好的,所以'Data'属性的700x500x3 = 105万个调用产生了影响,但没有太大影响。你尝试过'img.SetValue'吗? – Corey 2013-02-24 09:27:40

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

其真正的y是第一个元素,x是第二个元素 – 2017-05-04 14:02:03

1

它快得多转换您Emgu.Cv.ImageSystem.Drawing.Bitmap和遍历位图,或者使用安全或不安全的方法。

  • 的安全方法使用

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

    ,这是相当直截了当。

  • 不安全的方法是超快速的,依靠bmp.lockbits(bmp_data)interopservices.marshal复制bmp数据到数组。你可以在网上找到大量的例子。

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

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