Предполагая, что у вас есть необработанное 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 и просто избавляет от необходимости перебирать весь массив, чтобы найти списки для удалить.