Перейти к содержимому
Compvision.ru
Smorodov

Формирование изображения при помощи генетического алгоритма.

Recommended Posts

Интересный пример можно посмотреть здесь:

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/

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Соорудил простенькую реализацию ( генератор картин в стиле Ректангулизм :) )

 
#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;
	}
}

 

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×