I've created process that do some tricks on image to look better. One of the steps is to blur hue
channel from HSV
image. To blur channel I'm using cv::blur
.
The problem is that hue
is circular, so in some cases when i have 0
and 179
values, blur is giving results around 40-80.
I've tried to use Lab
, but does not work as good as it works with HSV
.
How can I do cv::bulr
on hue
channel and keep its circular form?
A smoothing filter such as cv::blur
is a (weighted) mean operation. To compute the mean of angles, the common approach is to instead average unit vectors with the given angle. That is, we convert each value phi
into the pair (cos(phi),sin(phi)
, average the pairs, and then compute the angle of the result (using atan2
to preserve the quadrant)
We can do the same thing when blurring an image that encodes angles, such as the hue channel of an HSV image. Simply compute the two images a=cos(H)
and b=sin(H)
, blur each image, and finally compute H=atan2(b,a)
with those blurred images.
In HSV, pixels with a zero saturation have a meaningless hue. When the saturation is low, the hue is less precise. It should also be less important in the averaging. So, we can weight the averages with S. To do so, compute a=S*cos(H)
and b=S*sin(H)
. The remainder stays the same.
But do note that HSV is not really suitable for image processing. HSV was originally designed to allow a user to pick a color in a GUI, in a drawing program. Other color spaces are more suitable. You could use, for example, CIE Yxy, where Y is the luminance and xy are the two chromaticity components. Yxy is a linear version of Lab, and doesn’t attempt to be perceptually uniform. The x and y channels can be simply blurred (the angle between the two is comparable to H and the norm is comparable to S). CIE Lab, CIE Luv, OKLab, etc could also be good color spaces to work in, depending on what the purpose of the processing is. All of these separate luminance (intensity, brightness, what have you) from chromaticity.