/**
 * @file        standardizePose.cpp
 * @author      Ondrej Klima, BUT FIT Brno, iklima@fit.vutbr.cz
 * @version     1.0
 * @date        15 June 2020
 *
 * @brief       Standardize pose and resolution of input image with respect to found 3D pose and binary mask
 *
 *
 * @license     BUT Licence 1.0
 *
 */

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

#include "../include/standardizePose.h"

void standardizePose(const QImage & image, QString inputFileName, QString outputFileName) {
    cv::Mat mat(image.height(), image.width(), CV_8UC3, (void*)image.bits());

    cv::Mat bands[3];
    split(mat, bands);

    std::vector<std::vector<cv::Point> > contours;
    cv::findContours( bands[0], contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0));

    std::vector<cv::RotatedRect> minRect(contours.size());
    std::vector<cv::RotatedRect> minEllipse(contours.size());

    for(size_t i = 0; i < contours.size(); i++)
    {
        minRect[i] = minAreaRect(contours[i]);
    }

    cv::Mat drawing = cv::Mat::zeros(mat.size(), CV_8UC3);
    for(size_t i = 0; i< contours.size(); i++)
    {
        cv::Scalar color(255, 0, 0);
        // contour
        drawContours( drawing, contours, (int)i, color );
        // ellipse
        ellipse( drawing, minEllipse[i], color, 2 );
        // rotated rectangle
        cv::Point2f rect_points[4];
        minRect[i].points(rect_points);
        for (int j = 0; j < 4; j++)
        {
            line( drawing, rect_points[j], rect_points[(j+1)%4], color );
        }
    }

    double angle = minRect.at(0).angle;
    if(minRect.at(0).size.width > minRect.at(0).size.height) {
        angle -= 90;
    }
    cv::Point2f center = minRect.at(0).center;
    cv::Mat rotationMatrix = cv::getRotationMatrix2D(center, angle, 1);
    cv::Mat transformed;
    cv::warpAffine(drawing, transformed, rotationMatrix, drawing.size());

    cv::Mat cvRender = cv::imread(inputFileName.toStdString());
    cv::Mat masked;
    cv::bitwise_and(cvRender,cvRender, masked, bands[0]);

    cv::warpAffine(masked, transformed, rotationMatrix, drawing.size());

    // Urcit bounding box a udelat crop
    cv::Mat channels[3];
    cv::split(transformed, channels);
    cv::Rect crop = cv::boundingRect(channels[0]);

    cv::Mat resized, cropped = transformed(crop);
    cv::resize(cropped, resized, cv::Size(256, 256));

    cv::imwrite(outputFileName.toStdString(), resized);
}
