From f5d8fc028e8465de8d10e05f2294efae703d931e Mon Sep 17 00:00:00 2001 From: qbigot <quentin.bigot@insa-rennes.fr> Date: Tue, 4 Jul 2017 11:03:46 +0200 Subject: [PATCH] added detiq-t modifications (save as and zoom buttons to the image window and image contextual menu + add copy image function (issues with ctrl+c shortcut)) + fixed entropy calculation + fixed DPCM predictor inversion + added information to threshold dialog about moving second threshold --- app/Operations/DPCM.cpp | 29 +++++++++---- app/Operations/DPCM.h | 2 +- app/Operations/DPCMDialog.cpp | 4 +- app/Operations/DPCMEncodingOp.cpp | 6 ++- app/Operations/EntropyOp.cpp | 66 ++++++++++++++++++++++++++++-- app/Operations/ThresholdDialog.cpp | 2 +- app/imageinsa_fr.ts | 14 ++++++- lib/detiq-t | 2 +- 8 files changed, 106 insertions(+), 19 deletions(-) diff --git a/app/Operations/DPCM.cpp b/app/Operations/DPCM.cpp index 12844a3..1d692bd 100644 --- a/app/Operations/DPCM.cpp +++ b/app/Operations/DPCM.cpp @@ -46,7 +46,7 @@ DPCM::~DPCM() } -string DPCM::execute( const GrayscaleImage *im, Prediction prediction_alg, imagein::ImageDouble **err_image, Image **recons_image, double Q ) { +string DPCM::execute( const GrayscaleImage *im, Prediction prediction_alg, imagein::ImageDouble **quant_err_image, imagein::ImageDouble **new_err_image, Image **recons_image, Image **pred_image, double Q ) { char buffer[255]; if( quantdef == NULL ) { throw "Error in DPCM::execute:\nquantdef = NULL"; @@ -65,13 +65,16 @@ string DPCM::execute( const GrayscaleImage *im, Prediction prediction_alg, image codlq(0); /* allocation mmoire pour l'image d'erreur de prdiction */ - ImageDouble *error_prediction_image = new ImageDouble(imgWidth, imgHeight, 1); + ImageDouble *quantized_error_prediction_image = new ImageDouble(imgWidth, imgHeight, 1); + ImageDouble *new_error_prediction_image = new ImageDouble(imgWidth, imgHeight, 1); Image *reconstructed_image = new GrayscaleImage(*im); + Image *prediction_image = new GrayscaleImage(*im); - // Init the error image with 0 values + // Init the error images with 0 values for(int i=0; i < imgHeight; i++) { for(int j=0; j< imgWidth; j++) { - error_prediction_image->setPixelAt(j, i, 0); + quantized_error_prediction_image->setPixelAt(j, i, 0); + new_error_prediction_image->setPixelAt(j, i, 0); } } @@ -109,9 +112,15 @@ string DPCM::execute( const GrayscaleImage *im, Prediction prediction_alg, image else P(X) = C */ - A = im->getPixelAt(j-1, i); + /* A = im->getPixelAt(j-1, i); B = im->getPixelAt(j-1, i-1); C = im->getPixelAt(j, i-1); + */ + + //correction QB + A = reconstructed_image->getPixelAt(j-1, i); + B = reconstructed_image->getPixelAt(j-1, i-1); + C = reconstructed_image->getPixelAt(j, i-1); if( ((fabs(B-C) - Q) <= fabs(B-A)) && (fabs(B-A) <= (fabs(B-C) + Q)) ) { @@ -128,8 +137,11 @@ string DPCM::execute( const GrayscaleImage *im, Prediction prediction_alg, image break; } + + prediction_image->setPixelAt(j,i,pred); depth_default_t thePixel = reconstructed_image->getPixelAt(j, i); ier = thePixel - pred; + new_error_prediction_image->setPixelAt(j, i, ier); ier = quantdef->valueOf(ier); codec(0, ier, &icode, &ireco); @@ -137,7 +149,8 @@ string DPCM::execute( const GrayscaleImage *im, Prediction prediction_alg, image pi[ier+255]++; /* proba associe a l'erreur de prdiction */ nbpt++; - error_prediction_image->setPixelAt(j, i, ier); + //TODO : changer le nom de l'image en quantized_error_prediction_image (done) + quantized_error_prediction_image->setPixelAt(j, i, ier); int tempvalue = pred + ireco; // Crop the value in [0,255] @@ -161,8 +174,10 @@ string DPCM::execute( const GrayscaleImage *im, Prediction prediction_alg, image returnval = returnval + print_iloiqu(); /* libration de la mmoire alloue */ - *err_image = error_prediction_image; + *quant_err_image = quantized_error_prediction_image; + *new_err_image = new_error_prediction_image; *recons_image = reconstructed_image; + *pred_image = prediction_image; return returnval; } diff --git a/app/Operations/DPCM.h b/app/Operations/DPCM.h index d6f2fd7..4ac1125 100644 --- a/app/Operations/DPCM.h +++ b/app/Operations/DPCM.h @@ -30,7 +30,7 @@ public: DPCM(); enum Prediction {PX_EQ_A, PX_EQ_B, PX_EQ_APC, PX_EQ_Q}; virtual ~DPCM(); - std::string execute(const imagein::GrayscaleImage *im, Prediction prediction_alg, imagein::ImageDouble **err_image, imagein::Image **recons_image, double Q = 0 ); + std::string execute(const imagein::GrayscaleImage *im, Prediction prediction_alg, imagein::ImageDouble **quant_err_image, imagein::ImageDouble **new_err_image, imagein::Image **recons_image, imagein::Image **pred_image,double Q = 0 ); void setQuantification( Quantification* tquantdef ); private: std::string print_iloiqu(); diff --git a/app/Operations/DPCMDialog.cpp b/app/Operations/DPCMDialog.cpp index d5b0b19..d57e250 100644 --- a/app/Operations/DPCMDialog.cpp +++ b/app/Operations/DPCMDialog.cpp @@ -59,8 +59,8 @@ Quantification* DPCMDialog::getQuantification() const { DPCM::Prediction DPCMDialog::getPrediction() const { if(ui->predictRadioA->isChecked()) return DPCM::PX_EQ_A; - else if(ui->predictRadioAC->isChecked()) return DPCM::PX_EQ_B; - else if(ui->predictRadioC->isChecked()) return DPCM::PX_EQ_APC; + else if(ui->predictRadioAC->isChecked()) return DPCM::PX_EQ_APC; + else if(ui->predictRadioC->isChecked()) return DPCM::PX_EQ_B; else if(ui->predictRadioGraham->isChecked()) return DPCM::PX_EQ_Q; else return DPCM::PX_EQ_A; } diff --git a/app/Operations/DPCMEncodingOp.cpp b/app/Operations/DPCMEncodingOp.cpp index 3b68814..4a0f61a 100644 --- a/app/Operations/DPCMEncodingOp.cpp +++ b/app/Operations/DPCMEncodingOp.cpp @@ -56,9 +56,13 @@ void DPCMEncodingOp::operator()(const imagein::Image* img, const std::map<const } GrayscaleImage* image = Converter<GrayscaleImage>::convert(*img); Image *reconstructedImage; + Image *predictionImage; + ImageDouble *quant_errorImage; ImageDouble *errorImage; - string s = micd.execute(image, dialog->getPrediction(), &errorImage, &reconstructedImage, dialog->getQ()); + string s = micd.execute(image, dialog->getPrediction(), &quant_errorImage, &errorImage,&reconstructedImage, &predictionImage,dialog->getQ()); outText(s); outDoubleImage(errorImage, qApp->translate("DPCM", "Error image").toStdString(), true, true, 0.1, false); + outDoubleImage(quant_errorImage, qApp->translate("DPCM", "Quantized error image").toStdString(), true, true, 0.1, false); + outImage(predictionImage, qApp->translate("DPCM", "Prediction image").toStdString()); outImage(reconstructedImage, qApp->translate("DPCM", "Reconstructed image").toStdString()); } diff --git a/app/Operations/EntropyOp.cpp b/app/Operations/EntropyOp.cpp index f978cd4..d79009c 100644 --- a/app/Operations/EntropyOp.cpp +++ b/app/Operations/EntropyOp.cpp @@ -24,6 +24,9 @@ #include "../Tools.h" #include <Image.h> +#include "../../lib/detiq-t/GenericInterface/Widgets/ImageWidgets/GraphicalHistogram.h" +#include "../../lib/detiq-t/GenericInterface/Widgets/ImageWidgets/GenericHistogramView.h" + using namespace std; using namespace imagein; @@ -31,7 +34,62 @@ EntropyOp::EntropyOp() : Operation(qApp->translate("Operations", "Calcul d'entro { } -void EntropyOp::operator()(const imagein::Image* image, const std::map<const imagein::Image*, std::string>&) { +void EntropyOp::operator()(const Image* image, const std::map<const imagein::Image*, std::string>&) { + /* + std::vector<GraphicalHistogram*> _graphicalHistos; + for(uint i = 0; i < nbChannels; ++i) + { + GraphicalHistogram* graphicalHisto; + switch(i) + { + case 0: + if(nbChannels == 1 || nbChannels == 2) + graphicalHisto = new GraphicalHistogram(tr("Black"), Qt::black); + else + graphicalHisto = new GraphicalHistogram(tr("Red"), Qt::red); + break; + case 1: + if(nbChannels == 1 || nbChannels == 2) + graphicalHisto = new GraphicalHistogram(tr("Alpha"), Qt::white); + else + graphicalHisto = new GraphicalHistogram(tr("Green"), Qt::green); + break; + case 2: + graphicalHisto = new GraphicalHistogram(tr("Blue"), Qt::blue); + break; + case 3: + graphicalHisto = new GraphicalHistogram(tr("Alpha"), Qt::black); + break; + default: + graphicalHisto = new GraphicalHistogram(tr("Channel"), Qt::black); + } + _graphicalHistos.push_back(graphicalHisto); + } + for(unsigned int channel = 0; channel < _graphicalHistos.size(); ++channel) { + GraphicalHistogram* graphicalHisto = _graphicalHistos[channel]; + + + QMap<int, int> cumulativeValues; + + uint maxw = rect.w > 0 ? rect.x + rect.w : image->getWidth(); + uint maxh = rect.h > 0 ? rect.y + rect.h : image->getHeight(); + for(uint j = rect.y; j < maxh; j++) { + for(uint i = rect.x; i < maxw; i++) { + double pixel = image->getPixel(i, j, channel); + cumulativeValues[qFloor(pixel)]++; + } + } + + QVector<QwtIntervalSample> samples; + for(int i = qFloor(image->min()); i <= qFloor(image->max()); ++i) { + QwtIntervalSample sample(cumulativeValues.value(i, 0), i, i + 1); + samples << sample; + } + + graphicalHisto->setData(new QwtIntervalSeriesData(samples)); + + } + */ double entropy = 0.; for(unsigned int c = 0; c < image->getNbChannels(); ++c) { @@ -40,16 +98,16 @@ void EntropyOp::operator()(const imagein::Image* image, const std::map<const ima if(histo[i] > 0) { double p = (double)histo[i] / image->getWidth() /image->getHeight(); entropy += p * log(p); - entropy = - entropy / log(2); - } + } } } + entropy = - entropy / log(2); outText(qApp->translate("Operations", "Entropy of the image = %1").arg(entropy).toStdString()); - } bool EntropyOp::needCurrentImg() const { return true; + //return false; } diff --git a/app/Operations/ThresholdDialog.cpp b/app/Operations/ThresholdDialog.cpp index c30b9f0..c74e42d 100644 --- a/app/Operations/ThresholdDialog.cpp +++ b/app/Operations/ThresholdDialog.cpp @@ -101,7 +101,7 @@ ThresholdDialog::ThresholdDialog(const GrayscaleImage* image, bool converted) : } QGroupBox* threshGroup = new QGroupBox(tr("Threshold"), this); QHBoxLayout* threshLayout = new QHBoxLayout(threshGroup); - _doubleBox = new QCheckBox(tr("Double threshold")); + _doubleBox = new QCheckBox(tr("Double threshold (right clic to move the second threshold)")); threshLayout->addWidget(_doubleBox); Vboxlayout->addWidget(threshGroup); diff --git a/app/imageinsa_fr.ts b/app/imageinsa_fr.ts index a7c3b17..7df49e7 100644 --- a/app/imageinsa_fr.ts +++ b/app/imageinsa_fr.ts @@ -526,6 +526,16 @@ Nombre de classes = %1 </translation> <source>Error image</source> <translation>Image d'erreur</translation> </message> + <message> + <location filename="Operations/DPCMEncodingOp.cpp" line="62"/> + <source>Quantized error image</source> + <translation>Image d'erreur quantifiée</translation> + </message> + <message> + <location filename="Operations/DPCMEncodingOp.cpp" line="63"/> + <source>Prediction image</source> + <translation>Image de prédiction</translation> + </message> <message> <location filename="Operations/DPCMEncodingOp.cpp" line="63"/> <source>Reconstructed image</source> @@ -1690,8 +1700,8 @@ Nombre de classes = %1 </translation> </message> <message> <location filename="Operations/ThresholdDialog.cpp" line="70"/> - <source>Double threshold</source> - <translation>Double seuil</translation> + <source>Double threshold (right clic to move the second threshold)</source> + <translation>Double seuil (clic droit pour déplacer le deuxième seuil)</translation> </message> <message> <location filename="Operations/ThresholdDialog.cpp" line="79"/> diff --git a/lib/detiq-t b/lib/detiq-t index 80da271..69a111e 160000 --- a/lib/detiq-t +++ b/lib/detiq-t @@ -1 +1 @@ -Subproject commit 80da27102f24d1f5d018f819b590b926d34a56f3 +Subproject commit 69a111e904d12520d9c1e301b41a6debcf445711 -- GitLab