Как сократить время выполнения следующего кода?

Я попытался придать изображению некоторые эффекты эскиза, для этого я использовал метод гауссовского моделирования в opencv, но столкнулся с проблемой, что для его выполнения требуется больше времени. Время уменьшается, когда размер изображения маленький, если размер большой, это занимает больше времени. Пожалуйста, кто-нибудь расскажет, как сократить время выполнения без изменения фактического размера изображения для следующего кода

#include "opencv2/opencv.hpp"
#include <iostream>
#include <vector>
#include "opencv2/ml/ml.hpp"
#include <list>
#include <iostream>
using namespace cv;
using namespace std;

void clustrize_colors(Mat& src,Mat& dst)
{
 // Number of clusters
 int NrGMMComponents = 96;

 cv::GaussianBlur(src,src,Size(3,3),1);

 int srcHeight = src.rows;
 int srcWidth  = src.cols;

 // Get datapoints
 vector<Vec3d> ListSamplePoints;

 for (int y=0; y<srcHeight; y++)
 {
  for (int x=0; x<srcWidth; x++)
  {
   // Collecting points from image
   Vec3b bgrPixel = src.at<Vec3b>(y, x);

   uchar b = bgrPixel.val[0];
   uchar g = bgrPixel.val[1];
   uchar r = bgrPixel.val[2];
   if(rand()%25==0) // peek every 25-th
   {
    ListSamplePoints.push_back(Vec3d(b,g,r));
   }
  } // for (x)
 } // for (y)


 // Form training matrix
 int NrSamples = ListSamplePoints.size();    
 Mat samples( NrSamples, 3, CV_64FC1 );

 for (int s=0; s<NrSamples; s++)
 {
  Vec3d v = ListSamplePoints.at(s);
  samples.at<double>(s,0) = (float) v[0];
  samples.at<double>(s,1) = (float) v[1];
  samples.at<double>(s,2) = (float) v[2];
 }    
 // 
 cout << "Learning to represent the sample distributions with " << NrGMMComponents << " gaussians." << endl;
 cout << "Started GMM training" << endl;

 Ptr<cv::ml::EM> em_model;
 cv::ml::EM::Params params(NrGMMComponents,cv::ml::EM::COV_MAT_GENERIC);

 Mat labels(NrSamples,1,CV_32SC1);
 Mat logLikelihoods( NrSamples, 1, CV_64FC1 );

 // Train classifier
 em_model=cv::ml::EM::train(samples,logLikelihoods,labels,noArray(),params);
 cout << "Finished GMM training" << endl;

 // result image
 Mat img  = Mat::zeros( Size( srcWidth, srcHeight ), CV_8UC3 );

 // predict cluster
 Mat sample( 1, 3, CV_64FC1 );

 Mat means=em_model->getMeans();

 for(int i = 0; i < img.rows; i++ )
 {
  for(int j = 0; j < img.cols; j++ )
  {
   Vec3b v=src.at<Vec3b>(i,j);
   sample.at<double>(0,0) = (float) v[0];
   sample.at<double>(0,1) = (float) v[1];
   sample.at<double>(0,2) = (float) v[2];
   int response = cvRound(em_model->predict( sample ));
   img.at<Vec3b>(i,j)[0]=means.at<double>(response,0);
   img.at<Vec3b>(i,j)[1]=means.at<double>(response,1);
   img.at<Vec3b>(i,j)[2]=means.at<double>(response,2);
  }
 }

 img.convertTo(img,CV_8UC3);
        namedWindow("result",WINDOW_AUTOSIZE);
 imshow("result",img);
        imwrite("D:\\nfr.jpg",img);
 waitKey();
 dst=img;
}

void processLayer(Mat& src,Mat& dst)
{
 Mat tmp=src.clone();
 Mat gx,gy,mag,blurred;
 Sobel( src, gx, -1, 1, 0, 3);
 Sobel( src, gy, -1, 0, 1, 3);
 magnitude(gx,gy,mag);
 //GaussianBlur(mag,blurred,Size(3,3),2);
 //mag+=blurred;
 normalize(mag,mag,0,1,cv::NORM_MINMAX);
 //sqrt(mag,dst);
 dst=mag.clone();
 normalize(dst,dst,0,1,cv::NORM_MINMAX);
}

int main(int ac, char** av)
{
 Mat clusterized;
 Mat frame=imread("image path"); ////load an image//////
        //resize(frame,frame,Size(256,256),0,0,INTER_LINEAR);
 clustrize_colors(frame,clusterized);
 clusterized.convertTo(clusterized,CV_32FC3,1.0/255.0);
 frame.convertTo(frame,CV_32FC3,1.0/255.0);
 Mat result1;
 vector<Mat> ch;
 split(frame, ch);

 processLayer(ch[0],ch[0]);
 processLayer(ch[1],ch[1]);
 processLayer(ch[2],ch[2]);

 merge(ch,result1);

 result1=(0.5*frame-0.9*result1+0.3*clusterized)*2.0;
        namedWindow("result1",WINDOW_AUTOSIZE);
 imshow("result1",result1);
        //cout<<result1;
        imwrite("D:\\finalresult.jpg",result1);
 waitKey(0);
 //destroyAllWindows();
 return 0;
}

1 ответ

По всей вероятности, узким местом является метод cv::ml::EM::train для opencv. Обучение классификатора не является легкой или простой задачей. Проблема классификации не была решена окончательно. Вот почему существуют большие компромиссы и различия между алгоритмами, не говоря уже о разных проблемных пространствах.

Что касается производительности, если вы настаиваете на использовании EM, проверьте документацию класса EM и, возможно, его родительские классы для изменения:

  • Максимальное количество итераций для обучения и / или
  • Срок критерии прекращения обучения.

Из-за использования сторонней библиотеки вы можете сделать немного, чтобы увеличить скорость, но не потерять точность. С другой стороны, библиотека с открытым исходным кодом, и она, вероятно, достаточно хорошо оптимизирована. Я не рекомендую пытаться оптимизировать реальный код библиотеки.

Другие вопросы по тегам