颜色检测算法 - 我应该怎么做?
我在设计颜色检测系统方面有点陷入困境 - 我不太想出一种轻松完成它的方法。
-
基本上,我有一个图像库,我想按颜色排序。因此,如果用户指定“按蓝色排序”,则蓝色最多的图像将出现在结果的顶部,蓝色最少的图像将出现在底部。
问题在于图像并不都是一种颜色,因此它同时执行两件事:
1 - 查找图像中最蓝的部分
2 - 对该蓝色进行排名(基于色调和该颜色的数量)。
我尝试了大约 3 或 4 种不同的方法,但结果各不相同 - 但没有一个能很好地工作,其中 2 种是相当数学的算法(它们在纸上的效果都比实践中好得多,哈哈)。
-
整个过程我可以采取哪些不同的方式?我可能错过了一些非常明显的工作方式 - 任何帮助或想法将不胜感激:)
-
编辑:感谢所有回复 - 这是我迄今为止尝试过的:
获取整个图像的平均 RGB 值并将其与蓝色进行比较。使用归一化的 RGB 3 空间向量进行比较并查找它们之间的距离。这种方法效果最差,没有蓝色的图像很容易出现在部分蓝色非常强的图像上方。
找到主色并将其与蓝色进行比较(再次使用 3 个空间矢量距离)。这不起作用,因为图像中可能有一个大的蓝色部分,它不是最多(或在顶部的几个)主色部分。
查找接近蓝色的像素,对所有这些进行平均,并将答案与实际蓝色进行比较。
查找所有接近蓝色的像素,增加计数并根据计数/总像素查找百分比。
I'm a bit stuck on designing a color detection system - I can't quite figure out a way to do it easily.
-
Basically, I have a library of images, that I want to sort by color. So if the user specifies 'sort by blue', then the most blue images will appear at the top of the results, with the least blue appearing at the bottom.
The problem is that the images aren't all one color, so it is doing two things at the same time:
1 - finding the bluest part of the image
2 - ranking this blue color (based on color hue and amount of this color).
I've tried about 3 or 4 different approaches, with varying results - none work well though, and 2 of these were quite mathematical algorithms (which all work much better on paper than in practice haha).
-
What different ways could I go about the whole process? I'm probably missing some really obvious ways it could work - any help or ideas would be much appreciated :)
-
EDIT: Thanks for all the responses - here's what I've tried so far:
getting the average rgb value for the whole image and comparing it to blue. Comparing was done using normalised rgb 3 space vectors and finding distances between them. This works the least well, an image with no blue could easily appear above an image with partial very strong blue.
finding the dominant color and comparing it to blue (again using 3 space vector distances). This didn't work as there might have been a large blue section of the image that wasn't the most (or in the top couple) of dominant color sections.
finding pixels that are close to blue, averaging all of these and comparing the answer to actual blue.
finding all the pixels that are close to blue, incrementing a count and finding a percentage based on count/total pixels.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我想到了两个想法:
廉价版本:将图像转换为 HSV 颜色空间,并为每个像素计算
cos(H - target_hue)
或合理的近似值(对于蓝色,target_hue
将为 240 度),乘以饱和度,然后对图像中所有像素的值进行平均。高值是最好的。请注意,比蓝色更接近黄色的颜色具有“负蓝色度”,黑色、白色和纯灰色同样具有“零蓝色度”。请注意,在这种情况下,您确实需要 HSV,而不是 HSL,因为 HSL 中的“S”不能很好地映射到感知饱和度。例如,颜色 #f8f8ff(RGB 248、248、255)在 HSL 中的饱和度为 100%(即纯蓝色),但它看起来接近白色。 HSV中相同颜色的“S”坐标只有3%,这是合理的。不太便宜的版本:将图像转换为 CIELAB 颜色空间,丢弃 L,并计算 a*b* 空间中每个像素与目标颜色之间的距离,然后对每个像素求平均值或 RMS。低值是最好的。
Two thoughts come to mind:
Cheap version: convert images to HSV color space, and for each pixel compute
cos(H - target_hue)
or a reasonable approximation (for blue,target_hue
would be 240 degrees), multiply by saturation, and average that quantity over all of the pixels in the image. High values are best. Note that colors that are closer to yellow than to blue have "negative blueness", and that black, white, and pure gray have equally "zero blueness". Note that you really want HSV, not HSL, in this situation, because the "S" in HSL doesn't map well to perceptual saturation. For example, the color #f8f8ff (RGB 248, 248, 255) has a saturation of 100% in HSL (i.e. a pure blue), but it looks nearly white. The same color in HSV has an "S" coordinate of only 3%, which is reasonable.Less cheap version: convert images to CIELAB color space, discard L, and compute the distance in a*b* space between each pixel and the target color, then average or RMS over each pixel. Low values are best.
我认为要测量“蓝色”,您需要考虑所有三个组成部分,而不仅仅是蓝色。举例来说,[255,255,255] 是纯白色,而不是蓝色,但 [0, 0, 30] 是纯蓝色,尽管其蓝色分量的值要低得多。
或者,您可以转换为 HSL 或 HSV 之类的东西,在这种情况下,“蓝色”应该更容易测量(仅色调和饱和度)。
I think to measure "blueness" you'll need to take all three components into account, not just the blue. Just for example, [255,255,255] is pure white, not blue -- but [0, 0, 30] is pure blue, even though its blue component is much lower in value.
Alternatively, you could convert to something like HSL or HSV, in which case the "blueness" should be a bit simpler to measure (hue and saturation only).
我会在 google 上搜索从 24 位图像创建 256 种调色板的算法(请参阅 http://en.wikipedia。 org/wiki/Color_quantization 了解更多信息),然后查看该调色板中哪些颜色在图像映射到该调色板时占主导地位。即,为每个 256 个调色板条目运行一个计数,记录有多少像素被映射到其中。
笔记,
你当然不需要整个256,它只是说256来帮助解释我的想法。
另外,通过直接研究这个调色板生成的算法可能会直接给你一个答案。
I'd google for an algorythm for creating 256 colour palettes from 24bit images (see http://en.wikipedia.org/wiki/Color_quantization for more info) then see which colours in this palette dominate if the image was mapped to it. ie, running a tally for each 256 palette entry of how many pixels get mapped into it.
notes,
you of course don't need the whole 256, it's just saying 256 to help explain my thinking.
also by directly studying the algorythim for this palette generation might directly give you an answer.
您真的需要找到图像中最蓝的部分吗?为什么不直接将图像的“蓝色度”排名为所有像素的平均蓝色分量值?
另一种可能性是找到通过阈值的像素密度,或者有资格成为蓝色像素所需的最小蓝色值。
Do you really need to find the bluest part of the image? Why not just rank the "blueness" of an image as the average blue-component value for all pixels?
Another possibility would be to find the density of pixels that pass a threshold, or minimum blue value necessary to qualify as a blue pixel.
如果你有一个像素,我会说它的 RGB 蓝色度是 B / (R + G + B) 的值,所以 1 完全是蓝色,0 根本不是蓝色,白色是 1/3 蓝色。 (注意黑色,这是一种特殊情况。)图像的蓝色度是其像素的平均蓝色度。如果成本太高,只需取固定数量的随机选择像素的平均值即可。
If you have one pixel, I'd say its blueness in terms of RGB is the the value of B / (R + G + B), so 1 is totally blue and 0 is not blue at all and white is 1/3 blue. (Watch out for black, which is a special case.) And the blueness of an image is the average blueness of its pixels. And if that's too costly, just take the average of a fixed number of randomly-chosen pixels.
我想说的是取整个图片的 RGB 值本身的平均值。我想说下面的伪图应该给你图片的“平均蓝色”。
如果这不起作用;那么我认为您需要根据 G/B 值将“蓝色”像素排名为较高/较低权重。然后将您的加权值相加并进行比较。
I would say to take the average of the RGB value itself over the whole picture. I would say that the pseudo below should give you the "average blue" of the picture.
If this doesn't work out; then I would think that you would need to rank a "blue" pixel as being higher/lower weighted based on the G/B values. Then add up your weighted value(s) and compare those.