First question:
To make color highlighting, you first need to train EM with your input pixels. After that, you simply loop all the input pixels and use the prediction function () to classify each of them. I have attached a small example that uses EM to separate color-based foreground and background. It shows you how to extract the dominant color (medium) for each gauss and how to access the original color of the pixels.
#include <opencv2/opencv.hpp> int main(int argc, char** argv) { cv::Mat source = cv::imread("test.jpg"); //ouput images cv::Mat meanImg(source.rows, source.cols, CV_32FC3); cv::Mat fgImg(source.rows, source.cols, CV_8UC3); cv::Mat bgImg(source.rows, source.cols, CV_8UC3); //convert the input image to float cv::Mat floatSource; source.convertTo(floatSource, CV_32F); //now convert the float image to column vector cv::Mat samples(source.rows * source.cols, 3, CV_32FC1); int idx = 0; for (int y = 0; y < source.rows; y++) { cv::Vec3f* row = floatSource.ptr<cv::Vec3f > (y); for (int x = 0; x < source.cols; x++) { samples.at<cv::Vec3f > (idx++, 0) = row[x]; } } //we need just 2 clusters cv::EMParams params(2); cv::ExpectationMaximization em(samples, cv::Mat(), params); //the two dominating colors cv::Mat means = em.getMeans(); //the weights of the two dominant colors cv::Mat weights = em.getWeights(); //we define the foreground as the dominant color with the largest weight const int fgId = weights.at<float>(0) > weights.at<float>(1) ? 0 : 1; //now classify each of the source pixels idx = 0; for (int y = 0; y < source.rows; y++) { for (int x = 0; x < source.cols; x++) { //classify const int result = cvRound(em.predict(samples.row(idx++), NULL)); //get the according mean (dominant color) const double* ps = means.ptr<double>(result, 0); //set the according mean value to the mean image float* pd = meanImg.ptr<float>(y, x); //float images need to be in [0..1] range pd[0] = ps[0] / 255.0; pd[1] = ps[1] / 255.0; pd[2] = ps[2] / 255.0; //set either foreground or background if (result == fgId) { fgImg.at<cv::Point3_<uchar> >(y, x, 0) = source.at<cv::Point3_<uchar> >(y, x, 0); } else { bgImg.at<cv::Point3_<uchar> >(y, x, 0) = source.at<cv::Point3_<uchar> >(y, x, 0); } } } cv::imshow("Means", meanImg); cv::imshow("Foreground", fgImg); cv::imshow("Background", bgImg); cv::waitKey(0); return 0; }
I checked the code with the following image and it works pretty well.

Second question:
I noticed that the maximum number of clusters has a huge impact on performance. Therefore, it is better to set this to a very conservative value, instead of leaving it blank or setting it to the number of samples, as in your example. In addition, the documentation refers to an iterative procedure for repeatedly optimizing a model with less limited parameters. Perhaps this gives you some acceleration. To learn more, check out the docs inside the example code that is provided for the train () here .
AD-530
source share