Skip to content
Snippets Groups Projects
QuantificationOp.cpp 7.33 KiB
/*
 * Copyright 2011-2012 INSA Rennes
 *
 * This file is part of ImageINSA.
 *
 * ImageINSA is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ImageINSA is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ImageINSA.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "QuantificationOp.h"
#include "../Tools.h"
#include <Converter.h>
#include "QuantificationDialog.h"

#include <QApplication>

using namespace std;
using namespace imagein;
using namespace genericinterface;

QuantificationOp::QuantificationOp() : Operation(qApp->translate("Operations", "Quantification").toStdString())
{
}


bool QuantificationOp::needCurrentImg() const {
    return false;
}

string QuantificationOp::quantificationOpLog(unsigned int c, Quantification * quant){
    char buffer[30];
    string output_msg;
    int val;    
    sprintf(buffer, "\nCanal %d : \n", c);
    output_msg += buffer;

    output_msg += "             Valeurs :  ";

    for(int i = 0; i < quant->nbValues(); ++i) {
        
        val =(int)quant->value(i);
        if(i != 0) output_msg += " |  ";
                
        sprintf(buffer, "%d ", val);
        output_msg += buffer;
        if(val < 10) output_msg += " ";
        if(val < 100 ) output_msg += " ";


    }
    output_msg += "\n";
    output_msg += "             Seuils    :       ";
            
    for(int i = 0; i < quant->nbThresholds(); ++i) {
        val =(int)quant->threshold(i);

        if(i != 0) output_msg += " |  ";
                
        sprintf(buffer, "%d ", val);
        output_msg += buffer;
                
        if(val < 10) output_msg += " ";
        if(val < 100 ) output_msg += " ";
    }

    output_msg += "\n";

    return output_msg;
}

string checkOptimumQuantizier(const imagein::Image* image, Quantification * quant, unsigned int c){
    
    float baricenter;
    float valueCenter; 
    float centroid = 0.0;
    float neighbor = 0.0;
    int som_lum = 0;
    int nb_points = 0;
    char buffer[100];
    
    Histogram hist = image->getHistogram(c);
    for (int j=1; j<quant->nbThresholds();j++){
        som_lum = 0;
        nb_points = 0;
        //Calcul des baricentres entre deux seuils  
        for(int i= quant->threshold(j-1); i <= quant->threshold(j); i++){
            som_lum += hist[i]*i;          
            nb_points += hist[i];
        }
        if(nb_points != 0) baricenter = som_lum/nb_points;
        else baricenter =  ( quant->threshold(j) + quant->threshold(j-1) )/2;

        centroid += abs( baricenter - quant->value(j) ) /( quant->threshold(j) - quant->threshold(j-1) ) * 100;
    }

    //cas spécial 
    if( quant->nbValues() == 2){
        som_lum = 0;
        nb_points = 0;
        for(int i= 0; i <= quant->threshold(0); i++){
                som_lum += hist[i]*i;          
                nb_points += hist[i];
        }
        if(nb_points != 0) baricenter = som_lum/nb_points;
        else baricenter =  (quant->threshold(0))/2;;
        centroid = abs( baricenter - quant->value(0) ) /( quant->threshold(0) ) * 100;
        
        som_lum = 0;
        nb_points = 0;
        for(int i= quant->threshold(0); i <= 255 ; i++){
                som_lum += hist[i]*i;          
                nb_points += hist[i];
            }
        if(nb_points != 0) baricenter = som_lum/nb_points;
        else baricenter =  255 - quant->threshold(0)/2;    
        centroid += abs( baricenter - quant->value(1) ) / ( 255 - quant->threshold(0) ) * 100;
    }
    for(int i = 0; i<quant->nbThresholds(); i++){
        
        valueCenter = ( quant->value(i) + quant->value(i+1) ) / 2 ; 
        neighbor += abs( valueCenter - quant->threshold(i) ) / ( quant->value(i) - quant->value(i+1) ) * 100;
    }
    
    neighbor = neighbor / quant->nbThresholds();
    if( quant->nbValues() == 2) centroid = centroid / 2;
    else centroid = centroid / ( quant->nbThresholds() - 1 );

    sprintf(buffer, "Canal : %d           Centroïd : %.2f %          Plus proche voisin : %.2f %\n", c, (100-centroid), (100-neighbor));

    return buffer;
}





void QuantificationOp::operator()(const imagein::Image* image, const std::map<const imagein::Image*, std::string>& imgList) {
    string quantType;
    string output_msg = "";
    string optiQuant;

    bool checkOptiQuant; 

    QuantificationDialog* dialog;
    if(image != NULL) {
        QString imgName = QString::fromStdString(imgList.find(image)->second);
        
        dialog = new QuantificationDialog(QApplication::activeWindow(), imgName);
    }
    else {
        dialog = new QuantificationDialog(QApplication::activeWindow());
    }

    QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec());


    if(code!=QDialog::Accepted) return;

    if(image != NULL) {
        
        Image* resImg = new Image(image->getWidth(), image->getHeight(), image->getNbChannels());
        for(unsigned int c = 0; c < image->getNbChannels(); ++c) {
            
            
            Quantification quantification = dialog->getQuantif(image, c, quantType, &checkOptiQuant);
            
            //Generate the text to print in the information window
            output_msg += quantificationOpLog(c, &quantification);


            for(unsigned int j = 0; j < image->getHeight(); ++j) {
                for(unsigned int i = 0; i < image->getWidth(); ++i) {
                    
                    const Image::depth_t value = image->getPixelAt(i, j, c);
                    resImg->setPixelAt(i, j, c, quantification.valueOf(value));
                }
            }
            if(checkOptiQuant)
                optiQuant += checkOptimumQuantizier(image, &quantification, c);
        }

        
        
        outText(quantType);
        outText(output_msg);
        if(checkOptiQuant){
            outText("Respect des proprietes du quantificateur optimal : ");
            outText(optiQuant);
        }

        QString windowName;
        QString imgName;

        if(quantType=="Quantification non lineaire a valeurs centrees :")
            windowName = QString(qApp->translate("QuantificationOp","Quantification non lineaire a valeur centree"));
        else if(quantType=="Quantification non lineaire a valeurs moyennes : ")
            windowName = QString(qApp->translate("QuantificationOp","Quantification non lineaire a moyennes"));
        else if(quantType=="Quantification personnalisee :")
            windowName = QString(qApp->translate("QuantificationOp","Quantification personnalisee"));
        else if(quantType=="Quantification LloydMax :")
            windowName = QString(qApp->translate("QuantificationOp","Quantification LloydMax"));
        else windowName = QString(qApp->translate("QuantificationOp","Quantification lineaire a valeurs centrees"));


        if(image!=NULL){
            imgName = QString::fromStdString(imgList.find(image)->second);
            imgName.append(" - ");
        }
        else{
            imgName = QString("");
        }
        outImage(resImg, imgName.toStdString() + windowName.toStdString());
    }

}