1

通常のforループをParallel.Forループに変えたいと思っていました。 this-入れ子になったParallel.Forループ内の同期

Parallel.For(0, bitmapImage.Width - 1, i => 
{ 
    Parallel.For(0, bitmapImage.Height - 1, x => 
    { 
     System.Drawing.Color oc = bitmapImage.GetPixel(i, x); 
     int gray = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11)); 
     System.Drawing.Color nc = System.Drawing.Color.FromArgb(oc.A, gray, gray, gray); 
     bitmapImage.SetPixel(i, x, nc); 
    }); 
}); 

の中へ

This-

for (int i = 0; i < bitmapImage.Width; i++) 
{ 
    for (int x = 0; x < bitmapImage.Height; x++) 
    { 
     System.Drawing.Color oc = bitmapImage.GetPixel(i, x); 
     int gray = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11)); 
     System.Drawing.Color nc = System.Drawing.Color.FromArgb(oc.A, gray, gray, gray); 
     bitmapImage.SetPixel(i, x, nc); 
    } 
} 

message-

オブジェクトが別の場所で現在使用中であるとそれは失敗します。

以下の行は、複数のスレッドがスレッドセーフではないソースにアクセスしようとしているためです。どのように私はこの作品を作ることができる任意のアイデア?

System.Drawing.Color oc = bitmapImage.GetPixel(i, x); 
+0

リソースを同時に読み取ったり変更したりすることはできません。あなたの最初のバージョンが動作する唯一のバージョンです。ロックを追加するとオーバーヘッドが増え、最初のバージョンよりも遅くなります。 – Igor

+0

@Igorありがとうございます。私は同じと思った。 –

+0

ImageはGUI関連のクラスであるため、シングルスレッドアクセス用に作成されています。あなたはスタンドアローンのmatriceで計算を行い、その後はsingle forループでイメージを更新しようとするかもしれません。 – VMAtm

答えて

1

これは、達成したいことを目の当たりにするものではありません。 1つのショットですべてのピクセルを取得してから、それらのピクセルを並列に処理する方がよいでしょう。

私が個人的に使用し、パフォーマンスを大幅に改善した代わりに、安全でない機能を使用してこの変換を行って、グレースケール画像を出力しています。

public static byte[] MakeGrayScaleRev(byte[] source, ref Bitmap bmp,int Hei,int Wid) 
     {    
      int bytesPerPixel = 4; 

      byte[] bytesBig = new byte[Wid * Hei]; //create array to contain bitmap data with padding 

      unsafe 
      { 

       int ic = 0, oc = 0, x = 0; 
       //Convert the pixel to it's luminance using the formula: 
       // L = .299*R + .587*G + .114*B 
       //Note that ic is the input column and oc is the output column     
       for (int ind = 0, i = 0; ind < 4 * Hei * Wid; ind += 4, i++) 
       {       
        int g = (int) 
          ((source[ind]/255.0f) * 
          (0.301f * source[ind + 1] + 
          0.587f * source[ind + 2] + 
          0.114f * source[ind + 3])); 
        bytesBig[i] = (byte)g; 
       }  
      } 

      try 
      { 

       bmp = new Bitmap(Wid, Hei, PixelFormat.Format8bppIndexed); 

       bmp.Palette = GetGrayScalePalette(); 

       Rectangle dimension = new Rectangle(0, 0, Wid, Hei); 
       BitmapData picData = bmp.LockBits(dimension, ImageLockMode.ReadWrite, bmp.PixelFormat); 


       IntPtr pixelStartAddress = picData.Scan0; 

       Marshal.Copy(forpictures, 0, pixelStartAddress, forpictures.Length); 

       bmp.UnlockBits(picData); 

       return bytesBig; 

      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.StackTrace); 

       return null; 

      } 

     } 

は、入力画像の全画素のバイトアレイを取得し、その高さと幅と出力計算階調アレイ、及び出力階調ビットマップBMP REFビットマップです。

+1

+1ありがとうございます。これは誰かのために役立つかもしれませんが、私は今何か他の理由のためにこの1つを使用しないかもしれません –

+0

助けが必要かどうか私に教えてください。このコードは、RTSPカメラからストリームを取得し、それをグレースケールに変換するために使用されたので、パフォーマンスは重要でした。 – farbiondriven

関連する問題