I want to posterize an image with k-means and OpenCV in C++ interface (cv namespace) and I get weird results. I need it for reduce some noise. This is my code:
#include "cv.h"
#include "highgui.h"
using namespace cv;
int main() {
Mat imageBGR, imageHSV, planeH, planeS, planeV;
imageBGR = imread("fruits.jpg");
imshow("original", imageBGR);
cv::Mat labels, data;
cv::Mat centers(8, 1, CV_32FC1);
imageBGR.convertTo(data, CV_32F);
cv::kmeans(data, 8, labels,
cv::TermCriteria(CV_TERMCRIT_ITER, 10, 1.0),
3, cv::KMEANS_PP_CENTERS, ¢ers);
imshow("posterized hue", data);
data.convertTo(data, CV_32FC3);
waitKey();
return 0;
}
But I get a weird result
First image: original
Second image: after k-means.
Any advice?
Update: the right solution. maybe someone can help me in optimize the code?
#include "cv.h"
#include "highgui.h"
#include <iostream>
using namespace cv;
using namespace std;
int main() {
Mat src;
src = imread("fruits.jpg");
imshow("original", src);
blur(src, src, Size(15,15));
imshow("blurred", src);
Mat p = Mat::zeros(src.cols*src.rows, 5, CV_32F);
Mat bestLabels, centers, clustered;
vector<Mat> bgr;
cv::split(src, bgr);
// i think there is a better way to split pixel bgr color
for(int i=0; i<src.cols*src.rows; i++) {
p.at<float>(i,0) = (i/src.cols) / src.rows;
p.at<float>(i,1) = (i%src.cols) / src.cols;
p.at<float>(i,2) = bgr[0].data[i] / 255.0;
p.at<float>(i,3) = bgr[1].data[i] / 255.0;
p.at<float>(i,4) = bgr[2].data[i] / 255.0;
}
int K = 8;
cv::kmeans(p, K, bestLabels,
TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0),
3, KMEANS_PP_CENTERS, centers);
int colors[K];
for(int i=0; i<K; i++) {
colors[i] = 255/(i+1);
}
// i think there is a better way to do this mayebe some Mat::reshape?
clustered = Mat(src.rows, src.cols, CV_32F);
for(int i=0; i<src.cols*src.rows; i++) {
clustered.at<float>(i/src.cols, i%src.cols) = (float)(colors[bestLabels.at<int>(0,i)]);
// cout << bestLabels.at<int>(0,i) << " " <<
// colors[bestLabels.at<int>(0,i)] << " " <<
// clustered.at<float>(i/src.cols, i%src.cols) << " " <<
// endl;
}
clustered.convertTo(clustered, CV_8U);
imshow("clustered", clustered);
waitKey();
return 0;
}
Result:
(float)(colors[bestLabels.at<int>(0,i)]);
you need to switch 0 and i to access the Mat bestLabels. – ConsignorOpencv Error : Assertion failed ( dims <=2 && data && (unsigned)i0 .....
– Dunant(i/src.cols) / src.rows
doesn't that set everything to zero (C++ integer division by a larger number)? – Little