2013-02-23 220 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); 
    }