C# 将for循环转换为并行循环
我已经编写了一个代码来计算图像的焦点值。但这需要5秒钟以上的时间C# 将for循环转换为并行循环,c#,for-loop,parallel-processing,C#,For Loop,Parallel Processing,我已经编写了一个代码来计算图像的焦点值。但这需要5秒钟以上的时间 public double GetFValue(Image image) { Bitmap source = new Bitmap(image); int count = 0; double total = 0; double totalVariance = 0; double FM = 0;
public double GetFValue(Image image)
{
Bitmap source = new Bitmap(image);
int count = 0;
double total = 0;
double totalVariance = 0;
double FM = 0;
Bitmap bm = new Bitmap(source.Width, source.Height);
Rectangle rect = new Rectangle(0,0,source.Width,source.Height);
Bitmap targetRect = new Bitmap(rect.Width, rect.Height);
// converting to grayscale
for (int y = 0; y < source.Height; y++)
{
for (int x = 0; x < source.Width; x++)
{
count++;
Color c = source.GetPixel(x, y);
int luma = (int)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11);
source.SetPixel(x, y, Color.FromArgb(luma, luma, luma)); // the image is now gray scaled
var pixelval = source.GetPixel(x, y);
// targetRect.Save(@"C:\Users\payam\Desktop\frame-42-rectangle.png", System.Drawing.Imaging.ImageFormat.Png);
int pixelValue = pixelval.G;
total += pixelValue;
double avg = total / count;
totalVariance += Math.Pow(pixelValue - avg, 2);
double stDV = Math.Sqrt(totalVariance / count); // the standard deviation, which is also the focus value
FM = Math.Round(stDV, 2);
}
}
return FM;
}
public双GetFValue(Image)
{
位图源=新位图(图像);
整数计数=0;
双倍合计=0;
双总方差=0;
双FM=0;
位图bm=新位图(source.Width、source.Height);
矩形rect=新矩形(0,0,source.Width,source.Height);
位图targetRect=新位图(矩形宽度、矩形高度);
//转换为灰度
对于(int y=0;y
我正在尝试将此代码转换为并行计算。我最终被虫子缠住了,我的头无法绕过它们。有什么建议吗
public double CalculateFvalue (Image image)
{
Bitmap myimage = new Bitmap(image);
int count = 0;
int total = 0;
double totalVariance = 0;
double FM = 0;
Parallel.For(0, image.Height, y =>
{
for (int x = 0; x < myimage.Width; x++)
{
count++;
Color c = myimage.GetPixel(x, y);
int luma = (int)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11);
myimage.SetPixel(x, y, Color.FromArgb(luma, luma, luma)); // the image is now gray scaled
var pixelval = myimage.GetPixel(x, y);
int pixelValue = pixelval.G;
total += pixelValue;
double avg = total / count;
totalVariance += Math.Pow(pixelValue - avg, 2);
double stDV = Math.Sqrt(totalVariance / count); // the standard deviation, which is also the focus value
FM = Math.Round(stDV, 2);
}
});
return Math.Round(FM,2);
}
公共双计算值(图像)
{
位图myimage=新位图(图像);
整数计数=0;
int-total=0;
双总方差=0;
双FM=0;
Parallel.For(0,image.Height,y=>
{
对于(int x=0;x
这是因为您声明的变量超出了Parallel.For
的范围。由于它们的访问(和写入)是不确定的,所以可能会用错误的数据(例如FM
)覆盖值
我建议您让每个迭代产生关于其结果的信息,然后使用收集的数据以线程安全的方式在外部操纵变量。您也可以通过使用一些
lock
语句来避免这种情况,但我个人会避免这种情况。要扩展我的评论,不要尝试并行运行GetPixel,而是使用lockBits
使用锁定位的代码:
public double GetFValue(Image image)
{
Bitmap source = new Bitmap(image);
int count = 0;
double total = 0;
double totalVariance = 0;
double FM = 0;
Bitmap bm = new Bitmap(source.Width, source.Height);
Rectangle rect = new Rectangle(0, 0, source.Width, source.Height);
//Bitmap targetRect = new Bitmap(rect.Width, rect.Height);
//new
///*
BitmapData bmd = source.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat);
int[] pixelData = new int[(rect.Height * rect.Width) -1];
System.Runtime.InteropServices.Marshal.Copy(bmd.Scan0, pixelData, 0, pixelData.Length);
for (int i = 0; i < pixelData.Length; i++)
{
count++;
Color c = Color.FromArgb(pixelData[i]);
int luma = (int)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11);
//Probably a formula for this
pixelData[i] = Color.FromArgb(luma, luma, luma).ToArgb();
total += luma;
double avg = total / count;
totalVariance += Math.Pow(luma - avg, 2);
double stDV = Math.Sqrt(totalVariance / count);
FM = Math.Round(stDV, 2);
}
source.UnlockBits(bmd);
return FM;
}
public双GetFValue(Image)
{
位图源=新位图(图像);
整数计数=0;
双倍合计=0;
双总方差=0;
双FM=0;
位图bm=新位图(source.Width、source.Height);
矩形rect=新矩形(0,0,source.Width,source.Height);
//位图targetRect=新位图(矩形宽度、矩形高度);
//新的
///*
BitmapData bmd=source.LockBits(rect,ImageLockMode.ReadWrite,source.PixelFormat);
int[]pixelData=newint[(rect.Height*rect.Width)-1];
System.Runtime.InteropServices.Marshal.Copy(bmd.Scan0,pixelData,0,pixelData.Length);
对于(int i=0;i
在使用win7示例图片(jummery.jpg)中的1024 x 768 jpg的快速测试中:
锁位:241毫秒
getPixel:2208毫秒
注意:在转换代码时,我注意到一些奇怪的事情(如getpixel、setpixel、同一像素上的getpixel?),但我想你知道你想要实现什么,并且这段代码与你的代码完全相同你看到的bug是什么?是的,你有大量的线程安全问题。但无论如何,getpixel非常慢,请查看锁位,而不是同时在不同线程上更新
count
、total
和FM
。您应该让每个循环迭代计算这些循环的局部值,然后在结束时将它们合并。谢谢,我将处理您的建议。将让您知道它是如何进行的。+1:还要确保在没有同步的情况下不要修改位图。当前代码以非线程安全方式使用SetPixel
。(如前所述,如果性能有任何问题,则不应使用Get/Set pixel调用)。W