[英]Accelerate loop over large image pixels in c#
我目前正在研究C# windows 表单项目,我需要计算最重要的 colors 图像并将其近似为最接近 DMC颜色表的一部分(如果颜色不是)。 我创建了一个适用于较小图像(例如 400x300 像素)的实现,如下所述。 但是,当我加载更大的图像(例如 3000x2000 像素)时,我会在大约一分钟后收到“应用程序处于中断模式”警告,并且通过每个像素循环 1000000 次(参见下面的代码)。 所以我猜这个解决方案需要一些加速,因为我们需要循环超过 3000x2000=6 000 000 像素。 是否有任何库(OpenCV?,Numpy?)可以帮助解决这个问题? 或者我应该专注于改进当前的解决方案并可能使用后台工作人员?
首先,我从 a.txt 文件中加载 DMC 表。 可以在此处找到示例 dmc 表
List<Color> all_dmc_colors = new List<Color>();
List<string> all_dmc_names = new List<string>();
private void initiate_dmc_colorpicker()
{
int counter = 0;
string line;
char[] del = { ' ' };
// Read the file and display it line by line.
System.IO.StreamReader file =
new System.IO.StreamReader(path_to_dmc);
while ((line = file.ReadLine()) != null)
{
if (counter > 0)
{
string[] splitted = line.Split(del);
listView3.Items.Add(line);
all_dmc_names.Add(line);
all_dmc_colors.Add(ColorTranslator.FromHtml("0x" + splitted[splitted.Length - 2]));
listView3.Items[listView3.Items.Count - 1].BackColor = ColorTranslator.FromHtml("0x" + splitted[splitted.Length - 2]);
}
counter++;
}
file.Close();
}
这是遍历每个像素的实现,然后进行插入排序,然后进行 dmc 颜色近似。 目前,当循环遍历图像的每个像素时,我们会收到“应用程序处于中断模式”警告。
int nr_colors_in = 5;
int nr_colors_out = 5;
private void get_recommended_colors(Bitmap loaded_image)
{
List<Color> pixelColors = new List<Color>();
List<int> occurence = new List<int>();
Console.WriteLine("Will now read "+ loaded_image.Width +"x"+ loaded_image.Height + " pixels!");
// Go through all pixels and save occurences of each color
int count = 0;
for (int i = 0; i < loaded_image.Width; i++)
{
for (int j = 0; j < loaded_image.Height; j++)
{
Console.WriteLine("Handle pixel " +count + " out of " + loaded_image.Width * loaded_image.Height);
Color currentPixel = loaded_image.GetPixel(i, j);
if (pixelColors.Contains(currentPixel))
{
occurence[pixelColors.IndexOf(currentPixel)]++;
}
else
{
occurence.Add(1);
pixelColors.Add(currentPixel);
}
/*
**We are stuck in this loop for large images **
Might help to sleep here but it will slow down the implementation
System.Threading.Thread.Sleep(1);
*/
count++;
}
}
// insertsort implementation
List<int> sortedOccurence = new List<int>();
List<Color> sortedPixelColors = new List<Color>();
for (int i = 0; i < occurence.Count; i++)
{
if (sortedOccurence.Count == 0)
{
sortedOccurence.Add(occurence[i]);
sortedPixelColors.Add(pixelColors[i]);
}
else
{
for (int index = 0; index <= sortedOccurence.Count; index++)
{
if (index == sortedOccurence.Count)
{
sortedOccurence.Insert(index, occurence[i]);
sortedPixelColors.Insert(index, pixelColors[i]);
break;
}
else
{
if (occurence[i] >= sortedOccurence[index])
{
sortedOccurence.Insert(index, occurence[i]);
sortedPixelColors.Insert(index, pixelColors[i]);
break;
}
}
}
}
}
// Approximate dmc and show output in console
List<int> exceptionList_in = new List<int>();
//rec_in.Clear();
Console.WriteLine("These IN colors are recommended:");
foreach (int i in Enumerable.Range(0, nr_colors_in))
{
Console.WriteLine("Color: " + sortedPixelColors[i] + " occurences: " + sortedOccurence[i]);
// is already dmc
if (all_dmc_colors.Contains(sortedPixelColors[i]))
{
ListViewItem item = new ListViewItem();
item.Text = all_dmc_names[all_dmc_colors.IndexOf(sortedPixelColors[i])];
item.BackColor = all_dmc_colors[all_dmc_colors.IndexOf(sortedPixelColors[i])];
//rec_in.Add(item);
Console.WriteLine("This is dmc color : " + all_dmc_names[all_dmc_colors.IndexOf(sortedPixelColors[i])]);
}
else
{
Console.WriteLine("This is no dmc color, we will approx it to: ");
int index = get_approximated_dmc_color_index(sortedPixelColors[i], exceptionList_in);
Console.WriteLine(all_dmc_names[index]);
exceptionList_in.Add(index);
ListViewItem item = new ListViewItem();
item.Text = all_dmc_names[index];
item.BackColor = all_dmc_colors[index];
//rec_in.Add(item);
}
}
List<int> exceptionList_out = new List<int>();
//rec_out.Clear();
Console.WriteLine("These OUT colors are recommended:");
foreach (int i in Enumerable.Range(0, nr_colors_out))
{
Console.WriteLine("Color: " + sortedPixelColors[i] + " occurences: " + sortedOccurence[i]);
// is already dmc
if (all_dmc_colors.Contains(sortedPixelColors[i]))
{
ListViewItem item = new ListViewItem();
item.Text = all_dmc_names[all_dmc_colors.IndexOf(sortedPixelColors[i])];
item.BackColor = all_dmc_colors[all_dmc_colors.IndexOf(sortedPixelColors[i])];
//rec_out.Add(item);
Console.WriteLine("This is dmc color : " + all_dmc_names[all_dmc_colors.IndexOf(sortedPixelColors[i])]);
}
else
{
Console.WriteLine("This is no dmc color, we will approx it to: ");
int index = get_approximated_dmc_color_index(sortedPixelColors[i], exceptionList_out);
Console.WriteLine(all_dmc_names[index]);
exceptionList_out.Add(index);
ListViewItem item = new ListViewItem();
item.Text = all_dmc_names[index];
item.BackColor = all_dmc_colors[index];
//rec_out.Add(item);
}
}
/*
// add to listviews
listView6.Items.Clear();
foreach(ListViewItem item in rec_in)
{
listView6.Items.Add(item);
}
listView7.Items.Clear();
foreach (ListViewItem item in rec_out)
{
listView7.Items.Add(item);
}
*/
}
private int get_approximated_dmc_color_index(Color c, List<int> exceptionList)
{
/*This function calculate the closest dmc color to input color!*/
int? best_index = null;
int? best_approx = null;
for (int i = 0; i < all_dmc_colors.Count; i++)
{
if (exceptionList.Contains(i))
{
continue;
}
if (best_index == null)
{
best_index = i;
best_approx = Math.Abs(all_dmc_colors[i].R - c.R) + Math.Abs(all_dmc_colors[i].G - c.G) + Math.Abs(all_dmc_colors[i].B - c.B) + Math.Abs(all_dmc_colors[i].A - c.A);
}
int curr_approx = Math.Abs(all_dmc_colors[i].R - c.R) + Math.Abs(all_dmc_colors[i].G - c.G) + Math.Abs(all_dmc_colors[i].B - c.B) + Math.Abs(all_dmc_colors[i].A - c.A);
if (curr_approx < best_approx )
{
best_approx = curr_approx;
best_index = i;
}
}
return best_index ?? default(int);
}
首先是您似乎在可能导致错误的主线程上执行此操作。 解决方案是将其转换为多线程并在后台执行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.