Получите процент использования каждого цвета в изображении - PullRequest
4 голосов
/ 24 октября 2011

У меня есть этот рабочий, но он очень чертовски медленный на изображениях в формате JPEG и также нуждается в некотором изменении.

Мне нужно знать отдельные цвета на изображении (с допуском +/- 1 для RGB) и% к изображению этого цвета.

, поэтому, если изображение было черно-белым, оно будет выглядеть примерно так: Белый: 74% Черный: 26%

Код ниже работает следующим образомЯ сказал, но мне нужно также добавить систему допусков, и я понятия не имею, как я это сделаю.

private Dictionary<string, string> getPixelData(Bitmap image)
{
    Dictionary<string, string> pixelData = new Dictionary<string, string>();
    //int col, row;
    //int r, g, b;
    Color pixel;

    double offset = 0.000001;
    int hmm = (image.Height * image.Width);
    double current = 0;
    offset = 100 / double.Parse(hmm.ToString());// 0.01;// 100 / (image.Height * image.Width) * 10000;

    try
    {
        for (int i = 0; i < image.Height; i++)
        {
            for (int j = 0; j < image.Width; j++)
            {
                current = current + offset;
                pixel = image.GetPixel(i, j);                        
                pixelData.Add(i + "," + j, (pixel.R.ToString() + " " + pixel.G.ToString() + " " + pixel.B.ToString()));
                pBarprocess.Value = int.Parse(Math.Floor(current).ToString());
                pBarprocess.Update();
                Application.DoEvents();
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Unable to parse image " + ex);
    }

    return pixelData;
}

И другая функция

private void btnProcess_Click(object sender, EventArgs e)
{
    pBarprocess.Value = 0;
    pBarprocess.Enabled = false;
    Bitmap foo = Bitmap.FromFile(@txtFileName.Text) as Bitmap;
    Dictionary<string, string> pixelData = new Dictionary<string, string>();

    lblProcess.Text = "Processing pixel map";
    pixelData = getPixelData(foo);

    lblProcess.Text = "Calculating Density";
    lblProcess.Update();

    var distinctList = pixelData.Values.Distinct().ToList();

    Console.WriteLine("DL = " + distinctList.Count);
    double offset = 100 / double.Parse(distinctList.Count.ToString());
    double current = 0;

    foreach (var value in distinctList)
    {
        IEnumerable<string> query = pixelData.Values.Where(fruit => fruit == value);
        double perc = (double.Parse(query.Count().ToString()) / double.Parse(pixelData.Count.ToString())) * 100;
        Console.WriteLine(value + " = " + query.Count() + "(" + perc + "%)");
        txtAnalysis.Text = "Colour " + value + " : " + query.Count() + " (" + perc.ToString() + "%)\r\n" + txtAnalysis.Text;
        txtAnalysis.Update();
        pBarprocess.Value = int.Parse(Math.Floor(current).ToString());
        pBarprocess.Update();
        Application.DoEvents();
    }

    lblProcess.Text = "Finished.";
    pBarprocess.Value = 0;
    pBarprocess.Enabled = false;
}

Ответы [ 3 ]

11 голосов
/ 24 октября 2011

GetPixel не очень быстрый способ доступа к данным изображения. Используйте метод LockBits .

EDIT:

Ну, ты много делаешь со строками. Создание словаря pixelData таким способом довольно бесполезно, почему бы вам сразу не обработать отдельные цвета? Цвет является неизменной структурой, так что это хороший ключ для нашего словаря.

Dictionary<Color, int> frequency = new Dictionary<Color, int>();
for (int i = 0; i < image.Height; i++) {
  for (int j = 0; j < image.Width; j++) {
    pixel = image.GetPixel(i, j);
    if (frequency.ContainsKey(pixel)) frequency[pixel]++;
    else frequency.Add(pixel, 1);
  }
}

// and finally
int totalPixels = image.Width * image.Height;
foreach (var kvp in frequency) {
  Console.WriteLine("Color (R={0},G={1},B={2}): {3}", kvp.Key.R, kvp.Key.G, kvp.Key.B, kvp.Value / (double)totalPixels);
}

И это должно быть сделано, за исключением случаев, когда вы хотите сделать это еще быстрее и использовать LockBits вместо GetPixel.

Некоторые другие наблюдения:

int hmm = (image.Height * image.Width);
double offset = 100 / double.Parse(hmm.ToString());

Вы используете очень странный и медленный способ приведения из int в double. Вы можете просто написать double offset = 100 / (double)hmm;, и это то же самое (вы также можете написать 100.0, а не 100, и компилятор создаст для вас double, так что вам не нужно приводить hmm).

Это заставило меня смеяться:

IEnumerable<string> query = pixelData.Values.Where(fruit => fruit == value);

Почему фрукты !? Похоже, вы скопировали это откуда-то.

8 голосов
/ 24 октября 2011

Похоже, что это часть более крупной цели обработки изображений.Платформа Aforge - это идеальный выбор для анализа и обработки изображений в .NET, и он очень быстрый.Вполне вероятно, что в нем уже есть код, который вам нужен.

Вы упомянули систему толерантности - для меня это звучит так, как будто вам нужно квантование - округление цветов .

Как только выИмея квантованное растровое изображение, вы можете создать и массив с длиной, соответствующей размеру палитры, LockBits растрового изображения и использовать индекс цвета для каждого пикселя в качестве индекса массива для каждого пикселя для накопления статистики использования.

МожетВы делитесь дополнительной информацией о своих целях для этого кода?Что именно он должен делать?

0 голосов
/ 26 мая 2014

Мой метод расчета цветового процента изображения следующий, также таким образом мы можем

рассчитать любой процент пикселей для любого цвета.

1.Используя программное обеспечение с именем «ImageJ» в этом месте, оно бесплатно.

http://rsb.info.nih.gov/ij/download.html

2.Откройте изображение с помощью этого инструмента

  1. Зайдите в меню Анализ и выберите Гистограмма, откроется окно гистограммы

4. В окне гистограммы, в левом нижнем углу нажмите кнопку «Список», откроется окно списка

5.В окне списка выберите «сохранить как», это позволит сохранить количество пикселей на цвета в диапазоне 0-256

6. Для измерения площади рассчитайте размер в пикселях по разрешению и умножьте на число

пикселей. Используйте Excel для любого другого численного анализа, особенно сводных таблиц.

Вот программное обеспечение ImageJ, файл Excel, который я использовал, и снимок экрана.

https://www.mediafire.com/?htwk83rwgio4zds

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...