大家好:我想拍张照片并检索分析其调色板的主要颜色(我认为这应该是最简单的方法),但我真的不知道从哪里开始。
1 回答
假设您有一个原始的 24 位 RGB 图像,并且您想要找到每种颜色出现的次数:
确实有两种简单的方法可以做到这一点:
我最喜欢的只是为每种可能的颜色创建一个整数数组,然后索引到该数组中,++ 该方法确实使用了 64 兆内存。
另一种方法是创建一个链表,每次遇到新颜色时添加到它,存储在列表中的结构将存储颜色和遇到的次数,它的速度很慢,因为你必须搜索每个像素的完整列表,但按使用次数排序会更快,因为列表中只有实际使用的颜色(也更适合小图像)
我喜欢两者之间的妥协:
比如说,红色和绿色索引到链接列表的数组中,这样数组只有 256k(假设它只存储指向列表的指针)并且要搜索的列表将相对较短,因为它只有蓝色的变体红色,绿色。如果您只对最常用的单一颜色感兴趣,我会将其存储在“最大颜色”变量中,每次迭代像素并增加颜色时,我都会与该变量进行比较,这样您就不必遍历整个结构,寻找最后最常用的。
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 节点,并且只需要遍历整个数组以查找要删除的列表。