我希望你能帮助我。
我正在Android中拍照,生成缩略图,并使用此缩略图分析像素以获得最常用的色调。
我认为使用RGB很难将它们分组,因此我将每个像素颜色转换为HSV颜色。如您所见,我使用Float3,因此hsv.x
与hsv.h
相同,hsv.y
为hsv.s
,hsv.z
等于hsv.v
。
scores
是int[]
数组,我在那里存储每个音调的像素数量。当找到蓝色调(海蓝宝石,淡蓝色和深蓝色)时,这种算法非常有效,但很难识别单色(它将它们移动到黄色分数)和暖色(它将橙色与黄色“混淆”)。另外,作为最后一个问题,我不知道如何识别褐色(这是我认为我错过的最后一个“大颜色”。算法来了:
for (Float3 hsv: hsvs) {
if(hsv.y < 0.15)
{
if(hsv.z < 0.2)
scores[BLACK]++;
else if(hsv.z < 0.6)
scores[GREY]++;
else
scores[WHITE]++;
}
else if (hsv.x < 15f || hsv.x > 345f)
scores[RED]++;
else if (hsv.x < 40)
scores[ORANGE]++;
else if (hsv.x < 70)
scores[YELLOW]++;
else if (hsv.x < 120)
scores[GREEN]++;
else if (hsv.x < 160)
scores[AQUAMARINE]++;
else if (hsv.x < 200)
scores[LIGHT_BLUE]++;
else if (hsv.x < 240)
scores[DARK_BLUE]++;
else if (hsv.x < 300)
scores[PURPLE]++;
else
scores[PINK]++;
}
您认为我可以通过更改某些数字来改进算法,还是应该从不同的方法开始?
修改
让我把你放在上下文中。我的应用程序拍照,抓取方形缩略图(出于实际原因)并分析生成的图片。因为它是拇指,它会丢失一些细节和尺寸(比方说我创建200x200px拇指),所以在我的特定情况下,总会有40000像素。我对这张图片的处理方法是检查最常用的音色。
大多数情况下,我将它们定义为色调超过3000像素(约为图像的7.5%)。我不对它们进行排名,我只是检查一些以任意数量的颜色命名的复选框(可能是显示给你的颜色加上棕色)。然后,用户检查或取消选中他认为合适的颜色。事实上,正如Geobits指出的那样,这是一个人类问题,最常用的颜色并不意味着最相关的颜色。这就是为什么这个工具不需要完美,只是为了避免在选择不适合包装的颜色时失败。
答案 0 :(得分:3)
如果我这样做,而不是让每个像素落入几个桶中的一个,我会看到每种颜色与每种颜色的距离。例如,您可以从每个“目标色调”中获取差异,并总结所有差异。在循环遍历所有像素之后具有最低总数的那个应该是“最常用的”。当然它并不完美,但命名颜色对于计算机来说并不是一项微不足道的任务。
例如,要获得“绿色”的总数(我任意世界中的色调120):
float runningTotalForGreen = 0;
for(Float3 hsv: hsvs)
{
float diff = (hsv.x - 120) % 180; // mod 180 to normalize cw/ccw on the wheel
runningTotalForGreen += diff; // lower = closer to green
}
您可能希望将目标颜色和总数存储在数组中以便于循环,但这是一般的想法。
修改强>
我认为这比“水桶”效果更好的原因是:考虑一张图片,其中大约35%的图片是红色的。另外65%是在浅蓝色边缘的某个地方。因此,34%落入淡蓝色桶中,31%落入深蓝色。你的方法说它是红色的,因为35%比两者都大。使用色调差异很可能会返回其中一个蓝调。
当然,大多数方法都会有某些图像失败。关键是找到错误最少的那个。这在很大程度上取决于它是什么类型的图像。我同意你需要对某些颜色(黑/白/棕/等)进行特殊处理。
这里的主要问题是这是一个人为问题。对于我上面的示例图片,有些人会说淡蓝色。有些人会说深蓝色。有些甚至可能会说红色,取决于它是多么生动/对比,特别是如果蓝色是前面带红色的背景。说“这张照片是 x 颜色”并不一致,除非它基本上是单色的。
答案 1 :(得分:1)
不能说这是否是一种好方法。在Color Names上查看此页面。当您单击方向盘中的颜色时,它将为您提供用于定义颜色名称的色调范围。