#include <opencv2/opencv.hpp>

int main(void)
{
	cv::Mat original_image = cv::imread("capture.jpg", cv::IMREAD_COLOR);
	cv::namedWindow("Colour Image", cv::WINDOW_AUTOSIZE);
	cv::imshow("Colour Image", original_image);

	for (double canny_threshold : { 40.0, 90.0, 140.0 } )
	{
		cv::Mat canny_output;
		cv::Canny(original_image, canny_output, canny_threshold, 3.0 * canny_threshold, 3, true);

		const std::string name = "Canny Output Threshold " + std::to_string((size_t)canny_threshold);
		cv::namedWindow(name, cv::WINDOW_AUTOSIZE);
		cv::imshow(name, canny_output);
	}

	// ---------------

	cv::Mat canny_output;
	const double canny_threshold = 100.0;
	cv::Canny(original_image, canny_output, canny_threshold, 3.0 * canny_threshold, 3, true);

	typedef std::vector<cv::Point> Contour;		// a single contour is a vector of many points
	typedef std::vector<Contour> VContours;		// many of these are combined to create a vector of contour points

	VContours contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(canny_output, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

	for (auto & c : contours)
	{
		std::cout << "contour area: " << cv::contourArea(c) << std::endl;
	}

	const cv::Scalar green(0, 255, 0);
	cv::Mat output = original_image.clone();
	for (auto & c : contours)
	{
		cv::polylines(output, c, true, green, 1, cv::LINE_AA);
	}
	cv::namedWindow("Contours Drawn Onto Image", cv::WINDOW_AUTOSIZE);
	cv::imshow("Contours Drawn Over Image", output);

	// ---------------

	cv::Mat blurred_image;
	cv::GaussianBlur(original_image, blurred_image, cv::Size(3, 3), 0, 0, cv::BORDER_DEFAULT);

	const size_t erosion_and_dilation_iterations = 3;

	cv::Mat eroded;
	cv::erode(blurred_image, eroded, cv::Mat(), cv::Point(-1, -1), erosion_and_dilation_iterations);

	cv::Mat dilated;
	cv::dilate(eroded, dilated, cv::Mat(), cv::Point(-1, -1), erosion_and_dilation_iterations);

	cv::Canny(dilated, canny_output, canny_threshold, 3.0 * canny_threshold, 3, true);
	cv::findContours(canny_output, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

	cv::Mat better_output = original_image.clone();
	for (auto & c : contours)
	{
		cv::polylines(better_output, c, true, green, 1, cv::LINE_AA);
	}
	cv::namedWindow("Another Attempt At Contours", cv::WINDOW_AUTOSIZE);
	cv::imshow("Another Attempt At Contours", better_output);

	cv::waitKey(0);

	return 0;
}

