Reputation: 41
I have used Kmeans function integrated in OpencvSharp in this way:
Cv2.Kmeans(
data: samples,
k: clustersCount,
bestLabels: bestLabels,
criteria:
new TermCriteria(type: CriteriaType.Eps |
CriteriaType.MaxIter, maxCount: 10, epsilon: 1.0),
attempts: 3, flags: KMeansFlags.PpCenters, centers: centers);
var clusteredImage = new Mat(preprocessedImage.Rows, preprocessedImage.Cols, preprocessedImage.Type());
for (var size = 0; size < preprocessedImage.Cols * preprocessedImage.Rows; size++)
{
var clusterIndex = bestLabels.At<int>(0, size);
var newPixel = new Vec3b
{
Item0 = (byte)(centers.At<float>(clusterIndex, 0)), // B
Item1 = (byte)(centers.At<float>(clusterIndex, 1)), // G
Item2 = (byte)(centers.At<float>(clusterIndex, 2)) // R
};
clusteredImage.Set(size / preprocessedImage.Cols, size % preprocessedImage.Cols, newPixel);
}
Now I need to obtain the BGR values of each centers....how can I obtain it?
Upvotes: 0
Views: 991
Reputation: 21
The whole process to extract the "clustered image" (https://kimcblog.com/2017/12/03/c-opencv-kmeans/) with some details and modifications:
/// <summary>
/// Color Quantization using K-Means Clustering in OpenCVSharp.
/// The process of Color Quantization is used for reducing the number of colors in an image.
/// </summary>
/// <param name="input">Input image.</param>
/// <param name="output">Output image applying the number of colors defined for required clusters.</param>
/// <param name="k">Number of clusters required.</param>
public static void Kmeans(Mat input, Mat output, int k)
{
using (Mat points = new Mat())
{
using (Mat labels = new Mat())
{
using (Mat centers = new Mat())
{
int width = input.Cols;
int height = input.Rows;
points.Create(width * height, 1, MatType.CV_32FC3);
centers.Create(k, 1, points.Type());
output.Create(height, width, input.Type());
// Input Image Data
int i = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++, i++)
{
Vec3f vec3f = new Vec3f
{
Item0 = input.At<Vec3b>(y, x).Item0,
Item1 = input.At<Vec3b>(y, x).Item1,
Item2 = input.At<Vec3b>(y, x).Item2
};
points.Set<Vec3f>(i, vec3f);
}
}
// Criteria:
// – Stop the algorithm iteration if specified accuracy, epsilon, is reached.
// – Stop the algorithm after the specified number of iterations, MaxIter.
var criteria = new TermCriteria(type: CriteriaType.Eps | CriteriaType.MaxIter, maxCount: 10, epsilon: 1.0);
// Finds centers of clusters and groups input samples around the clusters.
Cv2.Kmeans(data: points, k: k, bestLabels: labels, criteria: criteria, attempts: 3, flags: KMeansFlags.PpCenters, centers: centers);
// Output Image Data
i = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++, i++)
{
int index = labels.Get<int>(i);
Vec3b vec3b = new Vec3b();
int firstComponent = Convert.ToInt32(Math.Round(centers.At<Vec3f>(index).Item0));
firstComponent = firstComponent > 255 ? 255 : firstComponent < 0 ? 0 : firstComponent;
vec3b.Item0 = Convert.ToByte(firstComponent);
int secondComponent = Convert.ToInt32(Math.Round(centers.At<Vec3f>(index).Item1));
secondComponent = secondComponent > 255 ? 255 : secondComponent < 0 ? 0 : secondComponent;
vec3b.Item1 = Convert.ToByte(secondComponent);
int thirdComponent = Convert.ToInt32(Math.Round(centers.At<Vec3f>(index).Item2));
thirdComponent = thirdComponent > 255 ? 255 : thirdComponent < 0 ? 0 : thirdComponent;
vec3b.Item2 = Convert.ToByte(thirdComponent);
output.Set<Vec3b>(y, x, vec3b);
}
}
}
}
}
}
Upvotes: 2