#include "cv_params.h"
#include "ui_cv_params.h"

cv_Params::cv_Params(QWidget *parent, Logger *logger) :
    QDialog(parent),
    log(logger),
    ui(new Ui::cv_Params)
{
    ui->setupUi(this);
    //initParams_Tree();
}

cv_Params::~cv_Params()
{
    delete ui;
}

void cv_Params::process()
{
    cv::Mat tmp;
    cv::blur(this->frameRAW.image, tmp, cv::Size(this->cv_parameters.Blur_kernel,this->cv_parameters.Blur_kernel));
    cv::Canny(tmp, pre_processing_img, this->cv_parameters.Canny_threshold.Low, this->cv_parameters.Canny_threshold.High);
    cv::dilate(pre_processing_img, pre_processing_img, cv::Mat(), cv::Point(-1, -1), this->cv_parameters.Dilate_thickness, 1, 1);
}

void cv_Params::setItem(features::eItem what)
{
    switch (what) {
        case features::eItem::pre_processing :
            this->eWhat = what;
            this->setWindowTitle("Setting Computer Vision parameters");
            this->initParams_Tree();
            ui->save_IMG_button->hide();
        break;

    case features::eItem::hsv_colors :
        this->eWhat = what;
        this->setWindowTitle("Setting gripper HSV mask");
        this->initParams_Tree();
        ui->save_IMG_button->show();
    break;

    default :
        this->eWhat = features::eItem::none;
    }
}

void cv_Params::unsetItem()
{
    this->eWhat = features::eItem::none;
}

void cv_Params::on_load_IMG_button_clicked()
{
    QMessageBox text;
    QString filter = "All File (*.*) ;; PNG File (*.png)";
    QString filename = QFileDialog::getOpenFileName(this, "Select calibration frame (*.PNG)", QDir::homePath(),filter);
    frameRAW.image = cv::imread(filename.toStdString());
    if(frameRAW.image.empty()){
        text.setWindowTitle("Error");
        text.setText("Is not possible to set Custom Frame");
        text.exec();
        *log<<"Loading detect test frame aborted";
    }else{
        ui->load_IMG_button->setVisible(false);
        image.load(filename);
        int const h=ui->img_Show->height();
        int const w=ui->img_Show->width();
        QPixmap qPixmap(QPixmap::fromImage(image));
        ui->img_Show->setPixmap(qPixmap.scaled(w,h,Qt::KeepAspectRatio, Qt::SmoothTransformation));
        ui->img_Show->setAlignment(Qt::AlignCenter);

        *log<<"Loaded detect test frame";
        if(this->eWhat==features::eItem::hsv_colors){
            detectHSV();
            generateShow(frameRAW.image);
        }else if(this->eWhat==features::eItem::pre_processing){
            try {
                process();
                generateShow(this->pre_processing_img);
            } catch (...) { }
        }
    }
}

void cv_Params::on_Params_tree_itemChanged(QTreeWidgetItem *item, int column)
{
    if(column == 0) return;
    QMessageBox text;
    if(item->text(column-1)=="Low Threshold") this->cv_parameters.Canny_threshold.Low = item->text(column).toUInt();
    if(item->text(column-1)=="High Threshold") this->cv_parameters.Canny_threshold.High = item->text(column).toUInt();
    if(item->text(column-1)=="kernel [n x n]") this->cv_parameters.Blur_kernel = item->text(column).toUInt();
    if(item->text(column-1)=="Thickness") this->cv_parameters.Dilate_thickness = item->text(column).toUInt();

    if(item->text(column-1)=="Show"){
        std::string text = item->text(column).toStdString();
        this->maskFLAG = (text=="Mask") ? true : false;
    }

    if(frameRAW.image.empty())
    {
        text.setWindowTitle("Error");
        text.setText("Not Loaded Frame");
        text.exec();
    }else{
        try {
            if(this->eWhat==features::eItem::pre_processing) process();
            else if(this->eWhat==features::eItem::hsv_colors) detectHSV();
            /*else{
                text.setWindowTitle("Error");
                text.setText("Not setted Side");
                text.exec();
                return;
            }*/
        } catch (...) {
            text.setWindowTitle("Error");
            text.setText("This configuration is not possible");
            text.exec();
            cv_parameters = cv_default_parameters;
            initParams_Tree();
            if(this->eWhat==features::eItem::pre_processing) process();
            else if(this->eWhat==features::eItem::hsv_colors) detectHSV();
        }
        generateShow(pre_processing_img);
    }
}

void cv_Params::on_Params_tree_itemDoubleClicked(QTreeWidgetItem *item, int column)
{
    Qt::ItemFlags flags = item->flags();
    if(column == 0){
        item->setFlags(flags & (~Qt::ItemIsEditable));
    }else{
        item->setFlags(flags | Qt::ItemIsEditable);
    }
}

void cv_Params::generateShow(cv::Mat mat2show)
{
    int const h=ui->img_Show->height();
    int const w=ui->img_Show->width();
    QString tmp_path = "/tmp/frame.png";
    cv::imwrite(tmp_path.toStdString(),mat2show);
    image.load(tmp_path);
    QPixmap qPixmap1(QPixmap::fromImage(image));
    ui->img_Show->setPixmap(qPixmap1.scaled(w,h,Qt::KeepAspectRatio, Qt::SmoothTransformation));
    ui->img_Show->setAlignment(Qt::AlignCenter);
}

void cv_Params::changedShowMask(QString text){
    if(text=="Mask"){
        this->maskFLAG = true;
        if(this->selected_HSV_side==features::eSide::front_position) generateShow(this->mask.front);
        else if(this->selected_HSV_side==features::eSide::side_position) generateShow(this->mask.side);
    }else{
        this->maskFLAG = false;
        if(this->selected_HSV_side==features::eSide::front_position) generateShow(this->maskedFrame.front);
        else if(this->selected_HSV_side==features::eSide::side_position) generateShow(this->maskedFrame.side);
    }
}

void cv_Params::changedShowSurface(QString text){
    //if(!this->maskFLAG) return;

    if(text=="Front position"){
        this->selected_HSV_side = features::eSide::front_position;
        generateShow(mask.front);
        hueL->setValue(this->HSV_parameters.front.Hue.Lower);
        hueH->setValue(this->HSV_parameters.front.Hue.Upper);
        saturL->setValue(this->HSV_parameters.front.Saturation.Lower);
        saturH->setValue(this->HSV_parameters.front.Saturation.Upper);
        valL->setValue(this->HSV_parameters.front.Value.Lower);
        valH->setValue(this->HSV_parameters.front.Value.Upper);
    }
    if(text=="Side position"){
        this->selected_HSV_side = features::eSide::side_position;
        generateShow(mask.side);
        hueL->setValue(this->HSV_parameters.side.Hue.Lower);
        hueH->setValue(this->HSV_parameters.side.Hue.Upper);
        saturL->setValue(this->HSV_parameters.side.Saturation.Lower);
        saturH->setValue(this->HSV_parameters.side.Saturation.Upper);
        valL->setValue(this->HSV_parameters.side.Value.Lower);
        valH->setValue(this->HSV_parameters.side.Value.Upper);
    }
}

void cv_Params::initParams_Tree()
{
    ui->Params_tree->clear();
    ui->Params_tree->setColumnCount(2);
    ui->Params_tree->setHeaderHidden(true);

    if(this->eWhat==features::eItem::pre_processing){

        canny_itm = new QTreeWidgetItem(ui->Params_tree);
            canny_itm->setText(0,"Canny Edge Detection");
            canny_itm->setToolTip(0,"Define thresholds for the Canny 'optimal' detector");
            ui->Params_tree->addTopLevelItem(canny_itm);

            canny_L_TR = new QTreeWidgetItem();
                canny_L_TR->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
                canny_L_TR->setText(0,"Low Threshold");
                canny_L_TR->setToolTip(0,"The value define LOW threshold of a interesting point");
                canny_L_TR->setData(1,Qt::EditRole,this->cv_parameters.Canny_threshold.Low);
                canny_itm->addChild(canny_L_TR);

            canny_H_TR = new QTreeWidgetItem();
                canny_H_TR->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
                canny_H_TR->setText(0,"High Threshold");
                canny_H_TR->setToolTip(0,"The value define HIGH threshold of a interesting point");
                canny_H_TR->setData(1,Qt::EditRole,this->cv_parameters.Canny_threshold.High);
                canny_itm->addChild(canny_H_TR);

        blur_itm = new QTreeWidgetItem(ui->Params_tree);
            blur_itm->setText(0,"Image blurring");
            blur_itm->setToolTip(0,"Convolving the image with a low-pass filter kernel");
            ui->Params_tree->addTopLevelItem(blur_itm);

            blur_kernel = new QTreeWidgetItem();
                blur_kernel->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
                blur_kernel->setText(0,"kernel [n x n]");
                blur_kernel->setToolTip(0,"The value define n x n averaging kernel");
                blur_kernel->setData(1,Qt::EditRole,this->cv_parameters.Blur_kernel);
                blur_itm->addChild(blur_kernel);

        dilate_itm = new QTreeWidgetItem(ui->Params_tree);
            dilate_itm->setText(0,"Dilation");
            dilate_itm->setToolTip(0,"Basic morphological operation");
            ui->Params_tree->addTopLevelItem(dilate_itm);

            dilate_thickness = new QTreeWidgetItem();
                dilate_thickness->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
                dilate_thickness->setText(0,"Thickness");
                dilate_thickness->setToolTip(0,"The value define number of times dilation is applied");
                dilate_thickness->setData(1,Qt::EditRole,this->cv_parameters.Dilate_thickness);
                dilate_itm->addChild(dilate_thickness);

    }else{
        setSurf = new QTreeWidgetItem();
            surfBox = new QComboBox(this);
                setSurf->setText(0,"Surface");
                surfBox->addItems(QStringList() << "Front position" << "Side position");
                this->selected_HSV_side = features::eSide::front_position;
                connect(surfBox,SIGNAL(currentIndexChanged(QString)),SLOT(changedShowSurface(QString)));
            setSurf->setToolTip(0,"Select for which position you want to set HSV filter.");
            ui->Params_tree->addTopLevelItem(setSurf);
            ui->Params_tree->setItemWidget(setSurf, 1, surfBox);

        hueL_itm = new QTreeWidgetItem();
            hueL = new QSlider(Qt::Orientation::Horizontal);
                hueL_itm->setText(0,"Hue threshold L");
                hueL_itm->setToolTip(0,"The value define LOW threshold for Hue (HSV)");
                connect(hueL,SIGNAL(sliderMoved(int)),SLOT(changed_Hue_L(int)));
                hueL->setRange(0,255);
                hueL->setValue(this->HSV_parameters.front.Hue.Lower);
                hueL->setToolTip(QString::number(this->HSV_parameters.front.Hue.Lower));
            ui->Params_tree->addTopLevelItem(hueL_itm);
            ui->Params_tree->setItemWidget(hueL_itm, 1, hueL);

        hueH_itm = new QTreeWidgetItem();
            hueH = new QSlider(Qt::Orientation::Horizontal);
                hueH_itm->setText(0,"Hue threshold H");
                hueH_itm->setToolTip(0,"The value define HIGH threshold for Hue (HSV)");
                connect(hueH,SIGNAL(sliderMoved(int)),SLOT(changed_Hue_H(int)));
                hueH->setRange(0,255);
                hueH->setValue(this->HSV_parameters.front.Hue.Upper);
                hueH->setToolTip(QString::number(this->HSV_parameters.front.Hue.Upper));
            ui->Params_tree->addTopLevelItem(hueH_itm);
            ui->Params_tree->setItemWidget(hueH_itm, 1, hueH);

        saturL_itm = new QTreeWidgetItem();
            saturL = new QSlider(Qt::Orientation::Horizontal);
                saturL_itm->setText(0,"Saturation threshold L");
                saturL_itm->setToolTip(0,"The value define  LOW threshold for Saturation (HSV)");
                connect(saturL,SIGNAL(sliderMoved(int)),SLOT(changed_Saturation_L(int)));
                saturL->setRange(0,255);
                saturL->setValue(this->HSV_parameters.front.Saturation.Lower);
                saturL->setToolTip(QString::number(this->HSV_parameters.front.Saturation.Lower));
            ui->Params_tree->addTopLevelItem(saturL_itm);
            ui->Params_tree->setItemWidget(saturL_itm, 1, saturL);

        saturH_itm = new QTreeWidgetItem();
            saturH = new QSlider(Qt::Orientation::Horizontal);
                saturH_itm->setText(0,"Saturation threshold H");
                saturH_itm->setToolTip(0,"The value define  HIGH threshold for Saturation (HSV)");
                connect(saturH,SIGNAL(sliderMoved(int)),SLOT(changed_Saturation_H(int)));
                saturH->setRange(0,255);
                saturH->setValue(this->HSV_parameters.front.Saturation.Upper);
                saturH->setToolTip(QString::number(this->HSV_parameters.front.Saturation.Upper));
            ui->Params_tree->addTopLevelItem(saturH_itm);
            ui->Params_tree->setItemWidget(saturH_itm, 1, saturH);

        valL_itm = new QTreeWidgetItem();
            valL = new QSlider(Qt::Orientation::Horizontal);
                valL_itm->setText(0,"Value threshold L");
                valL_itm->setToolTip(0,"The value define  LOW threshold for Value (HSV)");
                connect(valL,SIGNAL(sliderMoved(int)),SLOT(changed_Value_L(int)));
                valL->setRange(0,255);
                valL->setValue(this->HSV_parameters.front.Value.Lower);
                valL->setToolTip(QString::number(this->HSV_parameters.front.Value.Lower));
            ui->Params_tree->addTopLevelItem(valL_itm);
            ui->Params_tree->setItemWidget(valL_itm, 1, valL);

        valH_itm = new QTreeWidgetItem();
            valH = new QSlider(Qt::Orientation::Horizontal);
                valH_itm->setText(0,"Value threshold H");
                valH_itm->setToolTip(0,"The value define  HIGH threshold for Value (HSV)");
                connect(valH,SIGNAL(sliderMoved(int)),SLOT(changed_Value_H(int)));
                valH->setRange(0,255);
                valH->setValue(this->HSV_parameters.front.Value.Upper);
                valH->setToolTip(QString::number(this->HSV_parameters.front.Value.Upper));
            ui->Params_tree->addTopLevelItem(valH_itm);
            ui->Params_tree->setItemWidget(valH_itm, 1, valH);

        setShow = new QTreeWidgetItem();
            showBox = new QComboBox(this);
                setShow->setText(0,"Show");
                showBox->addItems(QStringList() << "Result" << "Mask");
                this->maskFLAG = false;
                connect(showBox,SIGNAL(currentIndexChanged(QString)),SLOT(changedShowMask(QString)));
            setSurf->setToolTip(0,"Select what you want to see.");
            ui->Params_tree->addTopLevelItem(setShow);
            ui->Params_tree->setItemWidget(setShow, 1, showBox);      
    }
    ui->Params_tree->resizeColumnToContents(0);
    ui->Params_tree->resizeColumnToContents(1);
}

void cv_Params::changed_Hue_L(int value)
{
    if(this->frameRAW.image.empty()){
        QMessageBox text;
        text.setWindowTitle("Error");
        text.setText("Not Loaded Frame");
        text.exec();
        return;
    }
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            this->HSV_parameters.side.Hue.Lower = value;
            break;
        case features::eSide::front_position:
            this->HSV_parameters.front.Hue.Lower = value;
            break;
    }
    hueL->setToolTip(QString::number(value));
    this->detectHSV();
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            generateShow((this->maskFLAG) ?this->mask.side : this->maskedFrame.side);
            break;
        case features::eSide::front_position:
            generateShow((this->maskFLAG) ?this->mask.front : this->maskedFrame.front);
            break;
    }
}

void cv_Params::changed_Hue_H(int value)
{
    if(this->frameRAW.image.empty()){
        QMessageBox text;
        text.setWindowTitle("Error");
        text.setText("Not Loaded Frame");
        text.exec();
        return;
    }
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            this->HSV_parameters.side.Hue.Upper = value;
            break;
        case features::eSide::front_position:
            this->HSV_parameters.front.Hue.Upper = value;
            break;
    }
    hueH->setToolTip(QString::number(value));
    this->detectHSV();
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            generateShow((this->maskFLAG) ?this->mask.side : this->maskedFrame.side);
            break;
        case features::eSide::front_position:
            generateShow((this->maskFLAG) ?this->mask.front : this->maskedFrame.front);
            break;
    }
}

void cv_Params::changed_Saturation_L(int value)
{
    if(this->frameRAW.image.empty()){
        QMessageBox text;
        text.setWindowTitle("Error");
        text.setText("Not Loaded Frame");
        text.exec();
        return;
    }
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            this->HSV_parameters.side.Saturation.Lower = value;
            break;
        case features::eSide::front_position:
            this->HSV_parameters.front.Saturation.Lower = value;
            break;
    }
    saturL->setToolTip(QString::number(value));
    this->detectHSV();
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            generateShow((this->maskFLAG) ?this->mask.side : this->maskedFrame.side);
            break;
        case features::eSide::front_position:
            generateShow((this->maskFLAG) ?this->mask.front : this->maskedFrame.front);
            break;
    }
}

void cv_Params::changed_Saturation_H(int value)
{
    if(this->frameRAW.image.empty()){
        QMessageBox text;
        text.setWindowTitle("Error");
        text.setText("Not Loaded Frame");
        text.exec();
        return;
    }
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            this->HSV_parameters.side.Saturation.Upper = value;
            break;
        case features::eSide::front_position:
            this->HSV_parameters.front.Saturation.Upper = value;
            break;
    }
    saturH->setToolTip(QString::number(value));
    this->detectHSV();
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            generateShow((this->maskFLAG) ?this->mask.side : this->maskedFrame.side);
            break;
        case features::eSide::front_position:
            generateShow((this->maskFLAG) ?this->mask.front : this->maskedFrame.front);
            break;
    }
}

void cv_Params::changed_Value_L(int value)
{
    if(this->frameRAW.image.empty()){
        QMessageBox text;
        text.setWindowTitle("Error");
        text.setText("Not Loaded Frame");
        text.exec();
        return;
    }
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            this->HSV_parameters.side.Value.Lower = value;
            break;
        case features::eSide::front_position:
            this->HSV_parameters.front.Value.Lower = value;
            break;
    }
    valL->setToolTip(QString::number(value));
    this->detectHSV();
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            generateShow((this->maskFLAG) ?this->mask.side : this->maskedFrame.side);
            break;
        case features::eSide::front_position:
            generateShow((this->maskFLAG) ?this->mask.front : this->maskedFrame.front);
            break;
    }
}

void cv_Params::changed_Value_H(int value)
{
    if(this->frameRAW.image.empty()){
        QMessageBox text;
        text.setWindowTitle("Error");
        text.setText("Not Loaded Frame");
        text.exec();
        return;
    }
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            this->HSV_parameters.side.Value.Upper = value;
            break;
        case features::eSide::front_position:
            this->HSV_parameters.front.Value.Upper = value;
            break;
    }
    valH->setToolTip(QString::number(value));
    this->detectHSV();
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            generateShow((this->maskFLAG) ?this->mask.side : this->maskedFrame.side);
            break;
        case features::eSide::front_position:
            generateShow((this->maskFLAG) ?this->mask.front : this->maskedFrame.front);
            break;
    }
}

void cv_Params::getParameters(tcpc::sCV_parameters& CV_parameters)
{
    CV_parameters = this->cv_parameters;
}

void cv_Params::getParameters(tcpc::sHSV_boundaries& HSV_parameters)
{
    HSV_parameters = this->HSV_parameters;
}

void cv_Params::setParameters(tcpc::sCV_parameters CV_parameters)
{
    this->cv_default_parameters = CV_parameters;
    this->cv_parameters = CV_parameters;
    this->initParams_Tree();
}

void cv_Params::setParameters(tcpc::sHSV_boundaries HSV_parameters)
{
    this->HSV_parameters = HSV_parameters;
    this->initParams_Tree();
}

void cv_Params::on_buttonBox_rejected()
{
    this->cv_parameters = cv_default_parameters;
}

void cv_Params::on_cv_Params_rejected()
{
    on_buttonBox_rejected();
}

void cv_Params::detectHSV(){
    cv::Mat hsv, mask1, mask2;
    tcpc::sHSV_Mat_Pattern tmp;
    cv::cvtColor(this->frameRAW.image, hsv, CV_BGR2HSV);

    cv::inRange(hsv, cv::Scalar(this->HSV_parameters.front.Hue.Lower, this->HSV_parameters.front.Saturation.Lower, this->HSV_parameters.front.Value.Lower),
                     cv::Scalar(this->HSV_parameters.front.Hue.Upper, this->HSV_parameters.front.Saturation.Upper, this->HSV_parameters.front.Value.Upper),tmp.front);
    cv::inRange(hsv, cv::Scalar(this->HSV_parameters.side.Hue.Lower, this->HSV_parameters.side.Saturation.Lower, this->HSV_parameters.side.Value.Lower),
                     cv::Scalar(this->HSV_parameters.side.Hue.Upper, this->HSV_parameters.side.Saturation.Upper, this->HSV_parameters.side.Value.Upper),tmp.side);

    cv::Mat kernel = cv::Mat::ones(3, 3, CV_32F);

    cv::morphologyEx(tmp.front, tmp.front, cv::MORPH_OPEN, kernel);
    cv::morphologyEx(tmp.front, tmp.front, cv::MORPH_DILATE, kernel);
    cv::morphologyEx(tmp.side, tmp.side, cv::MORPH_OPEN, kernel);
    cv::morphologyEx(tmp.side, tmp.side, cv::MORPH_DILATE, kernel);

    cv::bitwise_not(tmp.front,mask.front);
    cv::bitwise_not(tmp.side,mask.side);

    cv::bitwise_and(hsv,hsv,maskedFrame.front,mask.front);
    cv::bitwise_and(hsv,hsv,maskedFrame.side,mask.side);

    cv::cvtColor(this->maskedFrame.front, this->maskedFrame.front, CV_HSV2RGB_FULL);
    cv::cvtColor(this->maskedFrame.side, this->maskedFrame.side, CV_HSV2RGB_FULL);
}

void cv_Params::on_save_IMG_button_clicked()
{
    QMessageBox text;
    QString filter = "All File (*.*) ;; PNG File (*.png)";
    QString filename = QFileDialog::getSaveFileName(this, "Save frame (*.PNG)", QDir::homePath(),filter);
    cv::Mat toSave;
    switch (this->selected_HSV_side){
        case features::eSide::side_position:
            toSave = (this->maskFLAG) ?this->mask.side : this->maskedFrame.side;
            break;
        case features::eSide::front_position:
            toSave = (this->maskFLAG) ?this->mask.front : this->maskedFrame.front;
            break;
    }
    if(toSave.empty()){
        text.setWindowTitle("Error");
        text.setText("Is not possible to save Custom Frame");
        text.exec();
        *log<<"Saving tested frame aborted";
        return;
    }else{
        if(filename.contains(".png", Qt::CaseInsensitive) || filename.contains(".jpg", Qt::CaseInsensitive)
           || filename.contains(".JPG" || filename.contains(".PNG", Qt::CaseInsensitive), Qt::CaseInsensitive)){
        }else{
            if(filename == ""){
                filename = QDir::homePath() +"/"+ QDateTime::currentDateTimeUtc().toString();
            }
            filename.append(".png");
        }
        cv::imwrite(filename.toStdString(),toSave);
        *log<<"Tested Frame saved as: "+filename;
    }
}
