繁体   English   中英

加速 c# 中大图像像素的循环

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM