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

속으로

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

This-

그것은

객체가 다른 곳에서 현재 사용중인 메시지 -

실패합니다.

이하의 줄은 비 스레드 안전 Reasources에 액세스하려고하는 여러 스레드 때문입니다. 내가 어떻게이 일을 할 수 있는지 아는가?

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

리소스를 동시에 읽거나 변경할 수 없기 때문에 할 수 없습니다. 첫 번째 버전 만 작동하는 유일한 버전이며 잠금을 추가하면 오버 헤드가 증가하고 첫 번째 버전보다 속도가 느려집니다. – Igor

+0

@Igor 감사합니다. 나는 똑같이 생각했다. –

+0

Image가 GUI 관련 클래스이므로 단일 스레드 액세스 사용을 위해 만들어졌습니다. 독립형 matrice에서 계산을 시도한 다음 단일 for 루프에서 이미지를 업데이트 할 수 있습니다. – VMAtm

답변

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; 

      } 

     } 

그것은 입력 화상의 모든 픽셀이 ByteArray를 가져, 그 높이 및 폭 계산하여 출력 계조 어레이, 출력 계조 맵 BMP REF 비트 맵이다.

+1

+1 감사합니다. 이것은 누군가에게 도움이 될 수 있지만 다른 이유로 지금 이걸 사용하지 않을 수도 있습니다. –

+0

도움이 필요하면 알려주세요. 이 코드는 RTSP 카메라에서 스트림을 가져와 그레이 스케일로 변환하는 데 사용되어 성능이 중요했습니다. – farbiondriven