Visualizzare un'immagine e copiarne una porzione



  • Salve, come da titolo il mio obiettivo è quello di visualizzare un'immagine (io l'ho messa in un QLabel), dare la possibilità all'utente di selezionarne una parte ( disegnando un rettangolo) e visualizzare la porzione selezionata in un altro QLabel.
    Il problema è che quando vado a visualizzare la selezione non ottengo la porzione di immagine selezionata, ma un altro pezzo di immagine. Ecco il mio codice:
    CPP:

    void Button1_nyq::on_selectimage_nyq_Hom_clicked() 
    {
    
            Imagename = QFileDialog::getOpenFileName(this,tr("Open Image for Nyquist Test"), "", tr("Images (*.jpg)"));  //apro l'immagine
            //mostro l'immagine
            QPixmap image(Imagename);
            ui->ImageDisplay->setPixmap(image);  //ImageDisplay è il nome del QLabel
        }
    int count_selection=0; //quando è diverso da 0 faccio sparire vuol dire che l'utente vuole disegnare un altro rettangolo, quindi nascondo il precedente
    
    void Button1_nyq::mousePressEvent(QMouseEvent *e)
    {
            if(count_selection!=0)
                    rubberBand->hide();
            point1 = e->pos();
            rubberBand = new QRubberBand(QRubberBand::Rectangle,this );
    }
    
    void Button1_nyq::mouseMoveEvent(QMouseEvent *e)
    {
            rubberBand->show();
            rubberBand->setGeometry(QRect(point1,e->pos()));
    }
    
    void Button1_nyq::mouseReleaseEvent(QMouseEvent *e)
    {
            count_selection++;
            QRect rect; //selection rectangle
            rect.setTopLeft(point1);
            rect.setBottomRight(e->pos());
            QPixmap image(Imagename);
            QPixmap a = image.copy(rect); //copio l'immagine selezionata in a
            ui->label_image_selected->setPixmap(a); //mostro l'immagine nel secondo QLabel
        }
    }
    

    .h

    #ifndef BUTTON1_NYQ_H
    #define BUTTON1_NYQ_H
    
    #include <QDialog>
    #include <qrubberband.h>
    
    namespace Ui {
    class Button1_nyq;
    }
    
    class Button1_nyq : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit Button1_nyq(QWidget *parent = 0);
        ~Button1_nyq();
    
    private slots:
        void on_selectimage_nyq_Hom_clicked();
    
        void on_SAVE_clicked();
    
        void mousePressEvent(QMouseEvent *e);
    
        void mouseReleaseEvent(QMouseEvent *e);
    
        void mouseMoveEvent(QMouseEvent *e);
    
    private:
        Ui::Button1_nyq *ui;
        QRubberBand *rubberBand;
    };
    
    #endif // BUTTON1_NYQ_H
    
    

    Eglish version: https://forum.qt.io/topic/76667/visualize-an-image-and-copy-a-portion
    cosa sto sbagliando? :O



  • il problema e' in e->pos() quella e' relativa a Button1_nyq non alla label

    usa e->globalPos() e usa QLabel::mapFromGloabal per convertirli in coordinate dell'immagine



  • @VRonin Grazie per la risposta, ma non sono riuscito a trovare info in rete, quindi ho improvvisato e ho ancora dei problemi, ho modificato cosi:

    void Button1_nyq::on_selectimage_nyq_Hom_clicked() 
    {
    
            Imagename = QFileDialog::getOpenFileName(this,tr("Open Image for Nyquist Test"), "", tr("Images (*.jpg)"));  //apro l'immagine
            //mostro l'immagine
            QPixmap image(Imagename);
            QPoint zero(0,0);
            ui->ImageDisplay->mapFromGlobal(zero); //mapFromGlobal mi chiede un QPoint come parametro, è giusto cosi?
            ui->ImageDisplay->setPixmap(image);  //ImageDisplay è il nome del QLabel
        }
    int count_selection=0; //quando è diverso da 0 faccio sparire vuol dire che l'utente vuole disegnare un altro rettangolo, quindi nascondo il precedente
    
    void Button1_nyq::mousePressEvent(QMouseEvent *e)
    {
            if(count_selection!=0)
                    rubberBand->hide();
            point1 = e->globalPos();
            rubberBand = new QRubberBand(QRubberBand::Rectangle,this );
    }
    
    void Button1_nyq::mouseMoveEvent(QMouseEvent *e)
    {
            rubberBand->show();
            rubberBand->setGeometry(QRect(point1,e->globalPos()));
    }
    
    void Button1_nyq::mouseReleaseEvent(QMouseEvent *e)
    {
            count_selection++;
            QRect rect; //selection rectangle
            rect.setTopLeft(point1);
            rect.setBottomRight(e->globalPos());
            QPixmap image(Imagename);
            QPixmap a = image.copy(rect); //copio l'immagine selezionata in a
            ui->label_image_selected->setPixmap(a); //mostro l'immagine nel secondo QLabel
    

    il fatto è che ora il rettangolo di selezione non viene disegnato dal punto del primo click ma altrove



  • QPoint zero(0,0);
    ui->ImageDisplay->mapFromGlobal(zero); //mapFromGlobal mi chiede un QPoint come parametro, è giusto cosi?

    no, mapFromGlobal deve essere usato nel rect, non qui

    QRect rect; //selection rectangle
            rect.setTopLeft(ui->ImageDisplay->mapFromGlobal(point1));
            rect.setBottomRight(ui->ImageDisplay->mapFromGlobal(e->globalPos()));
    


  • @VRonin ok quindi riscrivendo il codice cosi:

    void Button1_nyq::on_selectimage_nyq_Hom_clicked() 
    {
    
            Imagename = QFileDialog::getOpenFileName(this,tr("Open Image for Nyquist Test"), "", tr("Images (*.jpg)"));  //apro l'immagine
            //mostro l'immagine
            QPixmap image(Imagename);
            ui->ImageDisplay->setPixmap(image);  //ImageDisplay è il nome del QLabel
        }
    int count_selection=0; //quando è diverso da 0 faccio sparire vuol dire che l'utente vuole disegnare un altro rettangolo, quindi nascondo il precedente
    
    void Button1_nyq::mousePressEvent(QMouseEvent *e)
    {
            if(count_selection!=0)
                    rubberBand->hide();
            point1 = e->globalPos();
            rubberBand = new QRubberBand(QRubberBand::Rectangle,this );
    }
    
    void Button1_nyq::mouseMoveEvent(QMouseEvent *e)
    {
            rubberBand->show();
            rubberBand->setGeometry(QRect(point1,e->globalPos()));
    }
    
    void Button1_nyq::mouseReleaseEvent(QMouseEvent *e)
    {
            count_selection++;
            QRect rect; //selection rectangle
            rect.setTopLeft(ui->ImageDisplay->mapFromGlobal(point1));
            rect.setBottomRight(ui->ImageDisplay->mapFromGlobal(e->globalPos()));
            QPixmap image(Imagename);
            QPixmap a = image.copy(rect); //copio l'immagine selezionata in a
            ui->label_image_selected->setPixmap(a); //mostro l'immagine nel secondo QLabel
    

    il risultato non cambia, il rettangolo viene ancora disegnato in un punto iniziale che non è quello di click



  • prova a sostituire QPixmap a = image.copy(rect); con ui->ImageDisplay->render(&a,QPoint(0,0),QRegion(rect));



  • @VRonin said in Visualizzare un'immagine e copiarne una porzione:

    ui->ImageDisplay->render(&a,QPoint(0,0),QRegion(rect));

    se ho scritto giusto

    QPixmap a = ui->ImageDisplay->render(&a,QPoint(0,0),QRegion(rect));
    

    ho il seguente errore

    ...\gui\button1_nyq.cpp:224: error: conversion from 'void' to non-scalar type 'QPixmap' requested
             QPixmap a = ui->ImageDisplay->render(&a,QPoint(0,0),QRegion(rect));//copy the selected image in a
                                                                              ^
    


  • togli QPixmap a =

     QPixmap image(rect.size());
            ui->ImageDisplay->render(&a,QPoint(0,0),QRegion(rect)); //copio l'immagine selezionata in a
            ui->label_image_selected->setPixmap(a); //mostro l'immagine nel secondo QLabel
    


  • @VRonin

    ui->ImageDisplay->render(&a,QPoint(0,0),QRegion(rect));
    ui->label_image_selected->setPixmap(a); //show the image selected
    

    cosi mi dice

    ...\gui\button1_nyq.cpp:224: error: no matching function for call to 'QLabel::render(int*, QPoint, QRegion)'
             ui->ImageDisplay->render(&a,QPoint(0,0),QRegion(rect));//copy the selected image in a
                                                                  ^                                      ^
    

    e per la seconda riga

    ...\gui\button1_nyq.cpp:227: error: no matching function for call to 'QLabel::setPixmap(int&)'
             ui->label_image_selected->setPixmap(a); //show the image selected
                                                  
    


  • @VRonin ok scusa colpa mia, cambiando quella riga mi sono dimenticato che a era un intero usato da un'altra parte
    quindi:

    QPixmap image(rect.size());
            ui->ImageDisplay->render(&k,QPoint(0,0),QRegion(rect)); //copio l'immagine selezionata in a
            ui->label_image_selected->setPixmap(k); //mostro l'immagine nel secondo QLabel
    

    ora però mi da giustamente errore su k, dicendo che non è dichiarato

    edit:
    provando a dichiarare k come un QPixmap: il rettangolo è sempre disegnato in posizione diversa da quella del primo click, non viene visualizzato nulla nel secondo label



  • Che casino che abbiamo fatto. ok,

    QPixmap image(rect.size());
            ui->ImageDisplay->render(&image,QPoint(0,0),QRegion(rect)); //copio l'immagine selezionata in image
            ui->label_image_selected->setPixmap(image); //mostro l'immagine nel secondo QLabel
    


  • @VRonin
    ok allora il codice che ho ora è

    void Button1_nyq::on_selectimage_nyq_Hom_clicked() 
    {
    
            Imagename = QFileDialog::getOpenFileName(this,tr("Open Image for Nyquist Test"), "", tr("Images (*.jpg)"));  //apro l'immagine
            //mostro l'immagine
            QPixmap image(Imagename);
            ui->ImageDisplay->setPixmap(image);  //ImageDisplay è il nome del QLabel
        }
    int count_selection=0; //quando è diverso da 0 faccio sparire vuol dire che l'utente vuole disegnare un altro rettangolo, quindi nascondo il precedente
    
    void Button1_nyq::mousePressEvent(QMouseEvent *e)
    {
            if(count_selection!=0)
                    rubberBand->hide();
            point1 = e->pos();
            rubberBand = new QRubberBand(QRubberBand::Rectangle,this );
    }
    
    void Button1_nyq::mouseMoveEvent(QMouseEvent *e)
    {
            rubberBand->show();
            rubberBand->setGeometry(QRect(point1,e->pos()));
    }
    
    void Button1_nyq::mouseReleaseEvent(QMouseEvent *e)
    {
            count_selection++;
            QRect rect; //selection rectangle
            rect.setTopLeft(point1);
            rect.setBottomRight(e->pos()));
           QPixmap image(rect.size());
            ui->ImageDisplay->render(&image,QPoint(0,0),QRegion(rect)); //copio l'immagine selezionata in image
            ui->label_image_selected->setPixmap(image); //mostro l'immagine nel secondo QLabel
    
    

    cosi,usando pos, al posto di globalpos il rettangolo viene visualizzato correttamente e l'immagine copiata è più precisa rispetto a prima, nel senso che prima veniva traslata su 2 dimesioni, ora invece viene visualizzata un'immagine di poco traslata solo sull'asse x. Hai idee per questo?
    usando globalpos non sono riuscito a disegnare il rettangolo correttamente

    Questo è il risultato che ottengo ora:
    Real image
    http://imgur.com/9f6e0D3
    Selected image
    http://imgur.com/lysvM0q
    Result
    http://imgur.com/s0FydTc



  • Ho risolto il problema, questa è la mia soluzione per chi dovvesse avere lo stesso inconveniente

    void Button1_nyq::on_selectimage_nyq_Hom_clicked() 
    {
     
            Imagename = QFileDialog::getOpenFileName(this,tr("Open Image for Nyquist Test"), "", tr("Images (*.jpg)"));  //apro l'immagine
            //visualize the image in the first Label
            QPixmap image(Imagename);
            ui->ImageDisplay->setPixmap(image);  //ImageDisplay is the name of QLabel
        }
     
    void Button1_nyq::mousePressEvent(QMouseEvent *e)
    {
     
            point1 = e->pos();
            rubberBand = new QRubberBand(QRubberBand::Rectangle,this );
    }
     
    void Button1_nyq::mouseMoveEvent(QMouseEvent *e)
    {
            rubberBand->show();
            rubberBand->setGeometry(QRect(point1,e->pos()));
    }
     
    void Button1_nyq::mouseReleaseEvent(QMouseEvent *e)
    {
            rubberband->hide();
            QRect rect; //selection rectangle
            rect.setTopLeft(point1);
            rect.setBottomRight(e->pos()));
     
           QPixmap image(rect.size());
           image = grab(rubberband->geometry()); //copy the selected part
            ui->label_image_selected->setPixmap(image); //show "image" in the second QLabel
    


  • La via giusta comunque sarebbe usare il framework QGraphicView o la moderna alternativa in Qt Quick. QLabel e' progettata per essere un display di scritte o immagini, non per iteragirvi



  • @VRonin
    Non sono ancora così esperto, quindi grazie per avermi dato questi spunti ;)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.