// Listing 14.2.Przykład wyszukiwania i rysowania konturów na obrazie wejściowym

#include <opencv2/opencv.hpp>
#include <algorithm>
#include <iostream>

using namespace std;

struct AreaCmp {
	AreaCmp(const vector<float>& _areas) : areas(&_areas) {}
	bool operator()(int a, int b) const { return (*areas)[a] > (*areas)[b]; }
	const vector<float>* areas;
};

int main(int argc, char* argv[]) {

	cv::Mat img, img_edge, img_color;

	// ładuje obraz lub wyświetla pomoc, jeśli obraz nie zostanie dostarczony
	//
	if (argc != 2 || (img = cv::imread(argv[1], cv::LOAD_IMAGE_GRAYSCALE)).empty()) {
		cout << "\nListing 8.2. Rysowanie konturów\nWywołanie:\n./ch8_ex8_2 image\n\n";
		return -1;
	}

	cv::threshold(img, img_edge, 128, 255, cv::THRESH_BINARY);
	cv::imshow("Obraz po zdefiniowaniu progu", img_edge);
	vector< vector< cv::Point > > contours;
	vector< cv::Vec4i > hierarchy;

	cv::findContours(
		img_edge,
		contours,
		hierarchy,
		cv::RETR_LIST,
		cv::CHAIN_APPROX_SIMPLE
	);
	cout << "\n\nNaciśnij dowolny klawisz, aby narysować kolejny kontur, lub ESC, aby zakończyć\n\n";
	cout << "Suma wykrytych konturów: " << contours.size() << endl;

	vector<int> sortIdx(contours.size());
	vector<float> areas(contours.size());
	for (int n = 0; n < (int)contours.size(); n++) {
		sortIdx[n] = n;
		areas[n] = contourArea(contours[n], false);
	}

	// sortuje kontury od największego
	//
	std::sort(sortIdx.begin(), sortIdx.end(), AreaCmp(areas));

	for (int n = 0; n < (int)sortIdx.size(); n++) {
		int idx = sortIdx[n];
		cv::cvtColor(img, img_color, cv::GRAY2BGR);
		cv::drawContours(
			img_color, contours, idx,
			cv::Scalar(0, 0, 255), 2, 8, hierarchy,
			0 // wypróbuj różne wartości parametru max_level
		);
		cout << "Kontur nr " << idx << ": obszar=" << areas[idx] <<
			", liczba wierzchołków=" << contours[idx].size() << endl;
		cv::imshow(argv[0], img_color);
		int k;
		if ((k = cv::waitKey() & 255) == 27)
			break;
	}
	cout << "Ukończono wszystkie kontury\n";

	return 0;
}