This Haskell package contains functions for counting colors in images, either from a file or a camera feed. The input image must in a standard format like JPEG or PNG. The analyze function outputs the RGB and CIE-LAB values for each pixel, along with the color detected there. The tally function outputs a histogram of the colors detected. The quantize function outputs an image where the pixels have been replaced by the colors detected there.
A command-line tool for detecting and tallying colors is also provided.
Please report issues at <https://bwbush.atlassian.net/projects/HCC/issues/>.
In this example we use blank colored dice on a gray felt background:
We can process this file using the command-line tool:
color-counter --analyze=analysis.tsv --tally=tallies.tsv --quantize=quantized.png data/sample.jpg
The tally of pixels is as follows:
Color | Pixels | Efficiency [pixels/cube] |
---|---|---|
black | 3222 | 128.88 |
blue | 3285 | 131.40 |
green | 3972 | 154.88 |
red | 3738 | 149.52 |
yellow | 4156 | 166.24 |
One can see that edge and shading effects cause the detection efficiency to vary by color. The following image shows where colors are detected:
Some simple R code can be used to look at the observed pixels in CIE-LAB space, and then compare that to the classification of those pixels:
require(data.table)
analysis <- fread("analysis.tsv")
analysis[, RGB:=rgb(Red/255,Green/255,Blue/255)]
pairs(analysis[, .(L, A, B)], col=analysis$RGB, pch=".", main="Observations")
pairs(analysis[, .(L, A, B)], col=analysis$Color, pch=".", main="Classifications")
The calibration parameters are stored in the ColorConfiguration
data type of the Vision.Image.Color.Detection
module. It contains a default color and a list of ColorSpecificiation
entries, one for each color to be detected. All colors must be specified by their SVG names.
The ColorSpecification
entries define the color being detected and a half plane in CIE-LAB color space. The color is considered "detected" when it lies deeper than the specified threshold into the half plane defined by the specified vertex and direction. (The threshold parameter is redundant mathematically with the vertex location, but it is convenient to have such a parameter to make it easy to make minor adjustments to calibration.) When an observation lies in the half planes for several colors, it is assigned to the one in whose half plane it is deepest. We have found that calibration using this method of CIE-LAB half planes is robust under widely different lighting conditions. (Eventually, we will add automatic calibration--see <https://bwbush.atlassian.net/projects/HCC/issues/HCC-1> for the status of this.)
Because the detection efficiency varies somewhat by color, an efficiency parameter is included in ColorSpecification
. For instance, this efficiency can be used to convert the output of the tallying function from pixels to colored cubes.
main :: IO ()
main = do
input <- readRGB "data/sample.jpg"
print $ tally def input
let output = quantize def input
writeRBG True (Nothing, Nothing) "analysis.png" output