The time spent on finding a solution showed that it is difficult to disagree with the authors of comments on the use of blurring and clustering. Found that to implement the second item (actually clustering), you can use the K-means method. Of course, provided that the number of color bars in the image is known in advance:
const int cluster_count = 10;
Load an image from a file and divide its matrix into separate channels:
cv::Mat src_mat = cv::imread("image.jpg"); if(src_mat.empty()) return; std::vector<cv::Mat> channels; cv::split(src_mat, channels);
By default, OpenCV will load the image in BGR format. You can convert it to other color spaces (for example, HSV or YCbCr ), but this did not bring any further benefit. I even tried to combine different channels of different color spaces with each other, but this improvement also did not work.
Next, you need to create a matrix whose height will be equal to the number of points of the original image, and the width to the number of channels obtained earlier:
const int rows = src_mat.rows * src_mat.cols; const int cols = channels.size(); cv::Mat mat = cv::Mat::zeros(rows, cols, CV_8U); for(int col = 0; col < cols; ++col) { // Применяем размытие с ядром 4х4. // Как оказалось, это даёт самый лучший результат. // Больший размер ядра фильтра размытия ведёт // к большей деформации результата, так что 4х4 - это компромисс. cv::Mat blr_mat; cv::blur(channels[col], blr_mat, cv::Size(4,4)); // Размытое изображение переформатируем в матрицу с одной колонкой. blr_mat.reshape(1,rows).copyTo(mat.col(col)); }
Convert the matrix data into a floating point type - float:
mat.convertTo(mat, CV_32F);
The K-means clustering itself remains:
cv::Mat labels_mat; cv::kmeans(mat, cluster_count, labels_mat, cv::TermCriteria(), 1 , cv::KMEANS_PP_CENTERS);
Now labels_mat will contain the property values of each pixel of the image to a particular cluster. For ease of drawing, you can normalize these values:
cv::convertScaleAbs(labels_mat.reshape(0,src_mat.rows) , labels_mat, 255/cluster_count, 1);
The result:

It is noticeable that everything is far from ideal, however, in general, the color strips are highlighted correctly and you just need to work on eliminating artifacts. This can be done with the help of morphological operations or even through the processing of contours, eliminating small ones by their area.