Voglio posterizzare un'immagine con k-means e OpenCV nell'interfaccia C++ (spazio dei nomi cv) e ottengo risultati strani. Ne ho bisogno per ridurre un po 'di rumore. Questo è il mio codice:OpenCV che utilizza k-means per posterizzare un'immagine
#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;
}
ma ottengo un risultato strano
Prima immagine: originale
seconda immagine: dopo k-means.
Qualche consiglio?
Aggiornamento: la soluzione giusta. forse qualcuno può aiutarmi a ottimizzare il codice?
#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;
}
Risultato:
Potrebbe essere solo che avete bisogno di più iterazioni e/o un epsilon più piccolo. Ti suggerisco di provare a rimuovere "CV_TERMCRIT_EPS" per ora e giocare con il numero di iterazioni nel tuo TermCriteria. Vedi se questo aiuta. –
Mi sto avvicinando alla visione del computer, all'elaborazione delle immagini e all'apprendimento automatico, ma per me c'è un altro errore in quello che sto facendo e non solo una regolazione dei parametri. – nkint
Non sto suggerendo di iniziare la sintonizzazione dei parametri, sono suggerendo di semplificare il codice per verificare che ciò che stai cercando funzioni nella sua forma più semplice. La rimozione di epsilon e l'aumento del numero di iterazioni rimuove gli inganni non necessari. –