Cryptoucan™ Manufacturing: LEDs Revisited

Written by Dominik Joe Pantůček on July 4, 2019.

With the next batch of more than 1000 PCBs that has just arrived, we started testing and found out that the biggest issue is – again – checking whether LEDs work and if their color is correct. Read on to see some interesting math with averages in vector spaces and statistics of cyclic values.

Our first two generations of LED[1] testing software used strictly RGB[2] space for image processing and then converted the results to HSV[3] color space for color matching. It turns out, that blurring and averaging colors in RGB space skews the results and the only way to do the image analysis properly is to use HSV from the start.

In RGB space, an average of colors in some region can be expressed as:


Of course, for a weighted average it looks like:

$$\bar{\vec{c}}=\frac{\sum_{i=0}^n w_i\cdot\vec{c_i}(r,g,b)}{\sum_{i=0}^n w_i}$$

For weight we used a rotated gaussian-like shape in the form of:


Picture 1: Rotated Gaussian weight distribution.

As mentioned above, this skews results. Therefore before processing each pixel of the image, we convert it into HSV color space and get:

$$\vec{c}=(h,s,v)\quad h\in\langle 0^{\circ}; 360^{\circ})\quad s\in\langle 0,1\rangle\quad v\in\langle 0,1\rangle$$

Now in HSV color space, arithmetic average is not a tool strong enough to calculate the correct values. We need to properly address the cyclic nature of hue. See these two examples:



Of course, the second example is completely wrong. Of course the correct solution is:


Actually if we look at the HSV cone, we can treat $h$ and $s$ values as vector on a unit circle. And the points on the circle have coordinates:



With these two-dimensional coordinates in the color (hue-saturation) plane, we can compute the vector average of these:

$$\bar{x}=\frac{1}{n}\sum_{i=0}^n s_i\cdot\sin(h_i)$$

$$\bar{y}=\frac{1}{n}\sum_{i=0}^n s_i\cdot\cos(h_i)$$

And then we can get the averaged hue and saturation values in terms of:



For the value part of the HSV color specification, we can use ordinary arithmetic average without further adjustments.

There is one final piece in the averaging puzzle. We need a better weighting formula. Turns out that a simple cone centered at the middle pixel of our area of interest works the best. And the equation is super simple too:


Picture 2: Conic weight distribution.

Of course, for $w<0$ we just discard those pixels altogether. And then with the new matching in properly averaged HSV values, we can match both the LEDs on PCB or in the final product as you can see on the images below.

Picture 3: Matching LEDs on PCB.

Picture 4: Matching LEDs on Cryptoucan™.

Although it was a long way to get the right algorithm that both checks whether everything is OK and yet has a decent tolerance for different lighting conditions and slight variations in LEDs hue, it was definitely worth it. We look forward to finishing the production of the first 1000 Cryptoucans™!


Thank you for following Cryptoucan™ development and manufacturing and see you next week with usage examples again!


1. Wikipedia contributors. (2019, July 2). Light-emitting diode. In Wikipedia, The Free Encyclopedia. Retrieved 19:36, July 3, 2019, from

2. Wikipedia contributors. (2019, June 27). RGB color model. In Wikipedia, The Free Encyclopedia. Retrieved 19:36, July 3, 2019, from

3. Wikipedia contributors. (2019, June 29). HSL and HSV. In Wikipedia, The Free Encyclopedia. Retrieved 19:37, July 3, 2019, from