Smorodov 579 Жалоба Опубликовано September 7, 2012 Интересный пример можно посмотреть здесь: http://www.nihilogic.dk/labs/evolving-images/ Еще один креативчик: http://blog.altsoph.ru/%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D1%8B%D0%B5-%D0%BB%D0%B8%D1%86%D0%B0/ Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано September 9, 2012 Соорудил простенькую реализацию ( генератор картин в стиле Ректангулизм ) #include "opencv2/core/gpumat.hpp" #include "opencv2/core/opengl_interop.hpp" #include "opencv2/gpu/gpu.hpp" #include "opencv2/ml/ml.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/contrib/contrib.hpp" #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/nonfree/nonfree.hpp" #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/legacy/legacy.hpp" #include <string> #include <iostream> using namespace std; using namespace cv; using namespace cv::gpu; double getPSNR(const Mat& I1, const Mat& I2); # define _STLP_NO_DEBUG_EXCEPTIONS 1 // Количество генов в ДНК const int N_GENES=500; // Пределы величин double xmax=1024; double ymax=768; double wmax=1024; double hmax=768; // Гены, в данном случае это прямоугольники class Gene { public: double x; double y; double w; double h; Scalar Col; // Gene(double x,double y,double w,double h,double Col); Gene(); Gene& operator=(const Gene& g); Gene* operator=(const Gene* g); ~Gene(); }; Gene::Gene() { // Заполняем свойства гена случайным образом Scalar tmp; randu(tmp,0,600); x=tmp[0]; y=tmp[1]; w=tmp[2]/5; h=tmp[3]/5; randu(tmp,0,255); Col=tmp; } Gene::~Gene() { } // Функтор сравнения для сортировки. struct myclass2 { bool operator() (Gene* i,Gene* j) { return (i->w*i->h>j->w*j->h); } } myobject2; // ДНК - в данном случае это изображение, сформированное генами (прямоугольниками). class DNA { public: vector<Gene*> Genes; public: DNA(int N); double Performance(Mat& img); void Draw(Mat& dst); void Mutate(void); double similarity; ~DNA(); }; DNA::~DNA(void) { for(int i=0;i<Genes.size();i++) { delete Genes[i]; } Genes.clear(); } DNA::DNA(int N) { for(int i=0;i<N;i++) { Genes.push_back(new Gene()); } } void DNA::Draw(Mat& dst) { dst=0; sort(Genes.begin(),Genes.end(),myobject2); for(int i=0;i<Genes.size();i++) { if(Genes[i]->x>0 && Genes[i]->x<dst.cols && Genes[i]->y>0 && Genes[i]->y<dst.rows) { //circle(dst,Point(Genes[i]->x,Genes[i]->y),fabs(Genes[i]->w)+1,Genes[i]->Col,-1); rectangle(dst,Point(Genes[i]->x,Genes[i]->y),Point(Genes[i]->x+Genes[i]->w,Genes[i]->y+Genes[i]->h),Genes[i]->Col,-1); } } } double DNA::Performance(Mat& img) { Mat dst(img.rows,img.cols,img.type()); Draw(dst); similarity=getPSNR(img,dst); return similarity; } // Функтор сравнения для сортировки. struct myclass { bool operator() (DNA* i,DNA* j) { return (i->similarity<j->similarity); } } myobject; // Популяция - набор ДНК (изображений) class Population { public: vector<DNA*> DNAs; public: Population(int N,Mat& img); ~Population(); void Mutate(int N); void Crossover(int N); void SelectBestN(int N,Mat& img); }; Population::Population(int N,Mat& img) { for(int i=0;i<N;i++) { DNAs.push_back(new DNA(N_GENES)); DNAs[i]->Performance(img); } } void Population::SelectBestN(int N,Mat& img) { for(int i=0;i<DNAs.size();i++) { DNAs[i]->Performance(img); } sort(DNAs.begin(),DNAs.end(),myobject); for(int i=0;i<DNAs.size()-N;i++) { delete DNAs[i]; } DNAs.erase(DNAs.begin(),DNAs.end()-N); } void Population::Crossover(int N) { for(int i=0;i<N;i++) { Scalar r; // Выбор пары randu(r,0,DNAs.size()-1); Scalar G; // Выбор места разрыва днк randu(G,1,N_GENES-1); DNA* A; A=new DNA(N_GENES); for(int g=0;g<N_GENES;g++) { Gene*& GA=DNAs[r[0]]->Genes[g];// предок 1 Gene*& GB=DNAs[r[1]]->Genes[g];// предок 2 if(g<G[0]) { A->Genes[g]->x=GA->x; A->Genes[g]->y=GA->y; A->Genes[g]->w=GA->w; A->Genes[g]->h=GA->h; A->Genes[g]->Col=GA->Col; } else { A->Genes[g]->x=GB->x; A->Genes[g]->y=GB->y; A->Genes[g]->w=GB->w; A->Genes[g]->h=GB->h; A->Genes[g]->Col=GB->Col; } } DNAs.push_back(A); //delete(A); } } void Population::Mutate(int N) { for(int i=0;i<N;i++) { DNA* A; A=new DNA(N_GENES); Scalar r; // Выбор гена для мутации randu(r,DNAs.size()/2,DNAs.size()-1); Scalar G; // Выбор места мутации randu(G,0,N_GENES-1); // Чем меньше жизнеспособность, тем больше мутация double magnitude=(DNAs.size()-r[0])*(100.0/double(DNAs.size())); Scalar tmp; randu(tmp,-magnitude,magnitude); // Копируем предка for(int g=0;g<A->Genes.size();g++) { Gene*& M=DNAs[r[0]]->Genes[g];// предок мутанта A->Genes[g]->x=M->x; A->Genes[g]->y=M->y; A->Genes[g]->w=M->w; A->Genes[g]->h=M->h; A->Genes[g]->Col=M->Col; } Gene*& GM=A->Genes[G[0]]; // Мутируемый ген // Случайным образом изменяем случайный ген GM->x+=tmp[0]; GM->y+=tmp[1]; GM->w+=tmp[2]; GM->h+=tmp[3]; // Смотрим, чтобы все было в пределах дозволенного if(GM->x<0){GM->x=-GM->x;} if(GM->y<0){GM->y=-GM->y;} if(GM->w<0){GM->w=-GM->w;} if(GM->h<0){GM->h=-GM->h;} if(GM->x>xmax){GM->x=GM->x-xmax;} if(GM->y>ymax){GM->y=GM->y-ymax;} if(GM->w>wmax){GM->w=GM->w-wmax;} if(GM->h>hmax){GM->h=GM->h-hmax;} Scalar Col; randu(Col,-magnitude,+magnitude); GM->Col+=Col; DNAs.push_back(A); } } Population::~Population() { } //---------------------------------------------------------- // Точка входа //---------------------------------------------------------- int main(int argc, char* argv[]) { // Матрица изображения Mat img; Mat result; //--------------------------------------------- // //--------------------------------------------- namedWindow("Src"); namedWindow("Dst"); // Грузим изображение img=imread("D:\\ImagesForTest\\lena.jpg",1); result=Mat::zeros(img.rows,img.cols,CV_8UC3); imshow("Src", img); //--------------------------------------------- // //--------------------------------------------- VideoWriter vw=VideoWriter::VideoWriter("output.mpeg", CV_FOURCC('P','I','M','1'), 20, img.size()); //--------------------------------------------- // //--------------------------------------------- Population d(N_GENES,img); for(unsigned char k=0;k!=27;k=cvWaitKey(15)) { // Выбрать N лучших экземпляров d.SelectBestN(10,img); d.DNAs[d.DNAs.size()-1]->Draw(result); cout << "PSNR=" << getPSNR(img,result) << endl; imshow("Dst", result); // провести скрщивание, и вывести 50 потомков d.Crossover(50); // провести мутации, это добавит еще 100 потомков d.Mutate(100); cout << "d.DNAs.size()=" << d.DNAs.size() << endl; vw << result; } vw.release(); cvWaitKey(0); return 0; } //---------------------------------------------------------- // PSNR //---------------------------------------------------------- double getPSNR(const Mat& I1, const Mat& I2) { Mat s1; absdiff(I1, I2, s1); // |I1 - I2| s1.convertTo(s1, CV_32F); // cannot make a square on 8 bits s1 = s1.mul(s1); // |I1 - I2|^2 Scalar s = sum(s1); // sum elements per channel double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels if( sse <= 1e-10) // for small values return zero return 0; else { double mse =sse /(double)(I1.channels() * I1.total()); double psnr = 10.0*log10((255*255)/mse); return psnr; } } 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах