// ćwiczenia z końca rozdziału 5
// 1-6
#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 rozdziału 5.\n"
   << "Wywołanie:\n"
   << argv[0] << " <path/image_name>\n\n"
   << "Na przykład: ./" << argv[0] << " ../faces.png\n"
   << endl;
}



int main( int argc, const char** argv )
{
	help(argv);
	if(argc < 2) {
		cout << "\nBŁĄD: za mało parametrów.\n" << endl;
		return -1;
	}
	/************************************************************************/
	/* 1.	To ćwiczenie zapozna Cię z zasadą działania wielu funkcji pobierających typy macierzowe. Utwórz dwuwymiarową macierz z trzema kanałami typu byte o rozmiarze 100×100. Wszystkie elementy ustaw na 0.
       a.	Narysuj koło w macierzy za pomocą funkcji void cv::circle(InputOutputArray img, cv::point center, intradius, cv::Scalar color, int thickness=1, int line_type=8, int shift=0).
       b.	Wyświetl ten obraz za pomocą metod opisanych w rozdziale 2.
                                                                    */
	/************************************************************************/
	Mat m1 = Mat(100,100,CV_8U,Scalar(0));
	// a
	cv::circle(m1,Point(m1.cols/2,m1.rows/2),40,Scalar(255));
	// b
	cv::imshow("execrise 1",m1);

	/************************************************************************/
	/* 2.	Utwórz dwuwymiarową macierz z trzema kanałami typu byte o wymiarach 100×100 i ustaw wszystkie jej elementy na 0. Następnie za pomocą funkcji dostępu do elementów klasy cv::Mat zmodyfikuj piksele. Narysuj zielony prostokąt rozciągający się między punktami (20, 5) i (40, 20).                                                                     */
	/************************************************************************/
	Mat m2 = Mat(100,100,CV_8UC3,Scalar(0));
	for (int i=0;i<m2.rows;i++)
	{
		for (int j=0;j<m2.cols;j++)
		{
			if (j>=20&&j<=40&&i>=5&&i<=20)
			{
				m2.at<Vec3b>(i,j)[0]=0;    //b
				m2.at<Vec3b>(i,j)[1]=255;  //g
				m2.at<Vec3b>(i,j)[2]=0;    //r
			}
		}
	}
	cv::imshow("execrise 2",m2);

	/************************************************************************/
	/* 3.	Utwórz trzykanałowy obraz RGB o wymiarach 100×100. Wyczyść go. Przy użyciu arytmetyki wskaźnikowej narysuj zielony prostokąt rozciągający się między punktami (20, 5) i (40, 20).                                                                     */
	/************************************************************************/
	Mat m3 = Mat(100,100,CV_8UC3,Scalar(0));
	for(int i=0;i<m3.rows;i++)
	{       
		uchar* outData=m3.ptr<uchar>(i);     
		for(int j=0;j<m3.cols;j++)
		{
			if (j>=20&&j<=40&&i>=5&&i<=20)
			{
				outData[j*3+1] = 255;
			}
		}
	}
	cv::imshow("execrise 3",m3);

	/************************************************************************/
	// 4.	Poćwicz posługiwanie się obszarami zainteresowania(ROI).Utwórz jednokanałowy obraz typu byte o wymiarach 100×100 i wyzeruj go.W obrazie tym zbuduj piramidę rosnących wartości, posługując się ROI i funkcją cv::Mat::setTo().Innymi słowy : zewnętrzna krawędź powinna mieć wartość 0, następna wewnętrzna krawędź powinna mieć wartość 20, kolejna — 40 itd., aż ostatni wewnętrzny prostokąt będzie ustawiony na 200. Wszystkie krawędzie powinny mieć szerokość 10 pikseli.Wyświetl ten obraz.
	/************************************************************************/
	Mat m4 = Mat(210,210,CV_8U,Scalar(0));
	for (int i=0;i<210/2;i=i+10)
	{
		Mat roi = m4(cv::Rect(i,i,210-i*2,210-i*2));
		roi.setTo(i*2);// roi = i*2;
		
	}
	cv::imshow("execrise 4",m4);

	/************************************************************************/
	/* 5.	Użyj kilku nagłówków w jednym obrazie. Załaduj obraz o wymiarach przynajmniej 100×100. Utwórz dwa dodatkowe nagłówki będące ROI, gdzie width = 20, a height = 20. Ich punkty początkowe to odpowiednio (5, 10) i (50, 60). Przekaż te nowe podnagłówki do funkcji cv::bitwise_not(). Wyświetl załadowany obraz, który powinien przedstawiać odwrócone prostokąty w większym obrazie.                                                                     */
	/************************************************************************/
	Mat m5 = Mat(100,100,CV_8U,Scalar(0));
	Mat roi1 = m5(Rect(5,10,20,30));
	Mat roi2 = m5(Rect(50,60,20,30));
	bitwise_not(roi1,roi1);
	bitwise_not(roi2,roi2);
	cv::imshow("execrise 5",m5);

	/************************************************************************/
	/* 6.	Utwórz maskę za pomocą funkcji cv::compare(). Załaduj prawdziwy obraz. Za pomocą funkcji cv::split() podziel go na obraz czerwony, zielony i niebieski.
a.	Znajdź i wyświetl obraz zielony.
b.	Dwa razy sklonuj zieloną płaszczyznę (klony nazwij clone1 i clone2).
c.	Znajdź wartość minimalną i maksymalną zielonej płaszczyzny.
d.	Ustaw wartości clone1 na tresh = (unsigned char)((maximum - minimum)/2.0).
e.	Ustaw clone2 na 0 i użyj funkcji cv::compare (green_image, clone1, clone2, cv::CMP_GE). Teraz clone2 będzie zawierać maskę określającą, gdzie wartość przekracza thresh w obrazie zielonym.
f.	Na koniec użyj funkcji cv::subtract (green_image,thresh/2, green_image,clone2) i wyświetl wynik.                                                                     */
	/************************************************************************/
	Mat clone1,clone2;
	vector<cv::Mat> bgr_planes;
	Mat src = cv::imread(argv[1],1);
	split(src, bgr_planes );
	// a
	Mat green = bgr_planes[1];
	imshow("green",green);
	// b
	clone1 = green.clone();
	clone2 = green.clone();
	// c
	double minPixelValue, maxPixelValue;
	int minPixelID,maxPixelID;
	cv::minMaxIdx(green, &minPixelValue, &maxPixelValue,&minPixelID,&maxPixelID);
	// d
	double thresh= (unsigned char)((maxPixelValue - minPixelValue)/2.0);
	int ithresh = (int)thresh;
	clone1 = Mat(clone1.size(),clone1.type(),Scalar(ithresh));
	// e
	clone2 = Mat(clone2.size(),clone2.type(),Scalar(0));
	compare(green,clone1,clone2,cv::CMP_GE);
	// f
	cv::subtract(green,thresh/2,green,clone2);
	imshow("execrise 6",clone2);
	cout << "6" << endl;
	waitKey(-1); // czekanie na naciśnięcie klawisza
	return 0;
}
