Контекст iPhone: как извлечь информацию о палитре из изображения? - PullRequest
0 голосов
/ 10 февраля 2010

Привет всем: я хочу сделать снимок и получить основной цвет, анализируя его палитру (я думаю, это должен быть самый простой способ), но я не знаю, с чего начать.

1 Ответ

0 голосов
/ 10 февраля 2010

Предполагая, что у вас есть необработанное 24-битное RGB-изображение, и вы хотите узнать, сколько раз каждый цвет появляется:

на самом деле есть 2 простых способа сделать это:

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

другой метод - создать связанный список, добавляя к нему каждый раз, когда встречается новый цвет, структуры, хранящиеся в списке, сохраняют цвет и количество встреченных раз, медленнее, чем все накопившиеся причины, которые у вас есть. выполнить поиск по всему списку для каждого пикселя, но сортировку по количеству использованных раз будет быстрее, поскольку в списке присутствуют только фактически используемые цвета (что делает его более подходящим и для небольших изображений)

Мне нравится компромисс между двумя:

скажем, красный и зеленый, чтобы индексировать в массив связанных списков, таким образом, массив будет только 256 КБ (при условии, что он просто хранит указатель на список), и списки для поиска будут относительно короткими, потому что это только синий варианты красного, зеленого цвета. если бы вас интересовал только один использованный цвет, я бы просто сохранил его в переменной «max color», которую я сравнивал бы с каждым разом, когда я перебирал пиксель и увеличивал цвет, так что вам не нужно пройти всю структуру в поисках наиболее используемых в конце.

struct Pixel
{
   byte R,G,B;
}

const int noPixels = 1024*768; // this is whatever the number of pixels you have is

Pixel pixels[noPixels]; // this is your raw array of pixels

unsinged int mostUsedCount = 0;
Pixel mostUsedColor;

struct ColorNode
{
    ColorNode* next;
    unsigned int count;
    byte B;
} 

ColorNode* RG = new ColorNode[256*256];
memset(RG,0,sizeof(ColorNode)*256*256);

for(int i = 0; i<noPixels; i++)
{
   int idx = pixels[i].R + pixels[i].G*256;
   ColorNode*t;
   for(t=RG[idx]; t; t = t->next)
   {
      if(t->B == pixels[i].B)
      {
          break;
      }
   }
   if(!t)
   {
       t = new ColorNode;
       t->next = RG[idx];
       RG[idx] = t;
       t->B = pixels[i].B;
       t->count = 0;
   }

   t->count++;
   if(t->count > mostUsedCount)
   {
       mostUsedCount = t->count;
       mostUsedColor = pixels[i];
   }
}

вы можете рассмотреть возможность использования Бинарного дерева или какого-либо дерева, а не просто искать в таком списке. но я не слишком разбираюсь в таких вещах ...

О да ... Я забыл об управлении памятью.

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

если возможно, выделите всю память, которая вам, возможно, понадобится в начале, это будет 256k + sizeof (ColorNode) * noPixels ~ = 256 + от 2 до 3 раз больше ваших необработанных данных изображения.

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

еще одна вещь, которую вы могли бы сделать, это также добавить узлы в другой список ссылок для ВСЕХ выделенных узлов, это увеличивает процесс итерации, добавляет данные в узел Color и просто избавляет от необходимости перебирать весь массив, чтобы найти списки для удалить.

...