// ćwiczenia z końca rozdziału 7
// 1-4
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;


void help(const char **argv) {
	cout << "\n\n"
		<< " Ten program rozwiązuje ćwiczenia z końca rozdzialu 7.\n"
		<< endl;
}


int main( int argc, const char** argv )
{
	help(argv);
	
	/************************************************************************/
	/* 1.	Za pomocą generatora liczb losowych cv::RNG:
a.	Wygeneruj i wydrukuj trzy liczby zmiennoprzecinkowe wylosowane z jednostajnego rozkładu na przedziale od 0.0 do 1.0.
b.	Wygeneruj i wydrukuj trzy liczby o podwójnej precyzji wylosowane z rozkładu Gaussa o środku 0.0 i z odchyleniem standardowym 1.0.
c.	Wygeneruj i wydrukuj 3 bajty bez znaku wylosowane z rozkładu jednostajnego na przedziale od 0 do 255.                                                                     
	/************************************************************************/
	RNG rng = theRNG();
	// a
	float f1 = rng.uniform(0.f,1.f);
	float f2 = rng.uniform(0.f,1.f);
	float f3 = rng.uniform(0.f,1.f);
	cout<<" f1 " << f1 <<" f2 "<<f2<<" f3 "<<f3<<endl;
	// b
	Vec3d vec3d;
    rng.fill(vec3d,RNG::NORMAL,0.,1.);
	cout<<" d1 "<<vec3d[0]<<" d2 "<<vec3d[1]<<" d3 "<<vec3d[2]<<endl;
	// c
	unsigned byte1 = rng.uniform(0,255);
	unsigned byte2 = rng.uniform(0,255);
	unsigned byte3 = rng.uniform(0,255);
	cout<<" byte1 " << byte1 <<" byte2 "<<byte2<<" byte3 "<<byte3<<endl;

	/************************************************************************/
	/* 2.	Za pomocą metody fill() generatora liczb losowych cv::RNG utwórz tablicę zawierającą:
a.	20 liczb zmiennoprzecinkowych o rozkładzie jednostajnym w przedziale od 0.0 do 1.0.
b.	20 liczb o podwójnej precyzji wylosowane z rozkładu Gaussa o środku 0.0 i z odchyleniem standardowym 1.0.
c.	20 bajtów bez znaku z rozkładem jednostajnym w przedziale od 0 do 255.
d.	20 trójek wartości koloru, z których każda składa się z 3 bajtów z rozkładem jednostajnym w przedziale od 0 do 255.
                                                                     */
	/************************************************************************/
	// a
	Mat matFloat20 = Mat(20,1,CV_32FC1,Scalar(0));
	rng.fill(matFloat20,RNG::UNIFORM,0.f,1.f);
	// b
	rng.fill(matFloat20,RNG::NORMAL,0.f,1.f);
	// c
	Mat matUbyte20 = Mat(20,1,CV_8UC1,Scalar(0));
	rng.fill(matUbyte20,RNG::UNIFORM,0,255);
	// d
	Mat matColor20 = Mat(20,1,CV_8UC3,Scalar(0));
	rng.fill(matColor20,RNG::UNIFORM,0,255);

	/************************************************************************/
	/* 3.	Za pomocą generatora liczb losowych cv::RNG utwórz tablicę stu 3-bajtowych obiektów:
a.	Pierwszy i drugi wymiar mają rozkład Gaussa o środkach odpowiednio 64 i 192, każdy z wariancją 10.
b.	Trzeci wymiar ma rozkład Gaussa o środku 128 i z wariancją 2.
c.	Za pomocą obiektu cv::PCA oblicz rzut, dla którego maxComponents=2.
d.	Oblicz średnią w obu wymiarach rzutu i wyjaśnij wynik.
                                                                     */
	/************************************************************************/
	Mat matInt100 = Mat(100,1,CV_32FC3,Scalar(0));
	// a
	vector<Mat> planes;
	split(matInt100,planes);
	rng.fill(planes[0],RNG::NORMAL,64,10);
	rng.fill(planes[1],RNG::NORMAL,192,10);
	// b
	rng.fill(planes[2],RNG::NORMAL,128,2);
	// c 
	PCA pca(planes[0],Mat(),CV_PCA_DATA_AS_ROW,2);
	planes[0] = pca.project(planes[0]);
	pca(planes[1],Mat(),CV_PCA_DATA_AS_ROW,2);
	planes[1] = pca.project(planes[1]);
	pca(planes[2],Mat(),CV_PCA_DATA_AS_ROW,2);
	planes[2] = pca.project(planes[2]);
	//d
	f1 = 0;
	f2 = 0;
	f3 = 0;
	for (int i = 0;i<100;i++)
	{
		f1 += planes[0].at<float>(i,0);
		f2 += planes[1].at<float>(i,0);
		f3 += planes[2].at<float>(i,0);
	}
	f1 = f1/100;
	f2 = f2/100;
	f3 = f3/100;
	/************************************************************************/
	/* 4. Zobacz ćwiczenia w rozdziale 7.                                                            
	/************************************************************************/
	Matx32d AX(1, 1,
		       0, 1,
		      -1 ,1); 
	Mat A = static_cast<Mat>(AX);
	Mat U, W, V;
	SVD::compute(A, W, U, V);

	waitKey();
	getchar();
	return 0;

}
