QPixmap cropping using a QRect



  • Hi to everyone.
    It's my first post and i've installed qt with opencv libraries recently. I' m trying to crop a part of an area of a video displayed in a QLabel. i've subclassed this QLabel in order to have mousePressEvent and other function.

    When it crops the area enclosed by the rectangle it's not exactly the area contained in this.

    When i chose the point of rect i used

    selectionRect.setTopLeft(e->pos()) and selectionRect.setBottomRight(e->pos());
    Are these points the problem?

    Thanks


  • Qt Champions 2016

    Hi

    • it's not exactly the area contained in this.

    How much is it off?

    I assume e->pos() is from MousePress event and should already converted to client coordinates?

    You should qDebug() << selectionRect; and see what you get of values.

    It seems a bit wrong as it seems that u make a rect with the same 2 points which
    im not sure is correct or just seems so as rest of code is not there.

    selectionRect.setTopLeft(e->pos()) and selectionRect.setBottomRight(e->pos());



  • It works but the crop video in the second label is different from that one selected in the first label

    frmmain.cpp
    ``
    `
    #include "frmmain.h"
    #include "ui_frmmain.h"
    #include<opencv2/highgui/highgui.hpp>

    #include<QtCore>
    #include<QMessageBox>

    using namespace cv;
    using namespace std;

    // constructor ////////////////////////////////////////////////////////////////////////////////////
    frmMain::frmMain(QWidget *parent) : QMainWindow(parent), ui(new Ui::frmMain) {
    ui->setupUi(this);

    capWebcam.open(0);              // associate the capture object to the default webcam
    
    if(capWebcam.isOpened() == false) {                 // if unsuccessful
        QMessageBox::information(this, "", "error: capWebcam not accessed successfully \n\n exiting program\n");        // show error message
        exitProgram();                          // and exit program
        return;                                 //
    }
    
    qtimer = new QTimer(this);                                                      // instantiate timer
    connect(qtimer, SIGNAL(timeout()), this, SLOT(processFrameAndUpdateGUI()));     // associate timer to processFrameAndUpdateGUI
    qtimer->start(100);                  // start timer, set to cycle every 20 msec (50x per sec), it will not actually cycle this often
    

    }

    // destructor
    frmMain::~frmMain() {
    delete ui;
    }

    void frmMain::exitProgram() {
    if(qtimer->isActive()) qtimer->stop(); // if timer is running, stop timer
    QApplication::quit(); // and exit program
    }

    void frmMain::processFrameAndUpdateGUI() {
    cv::Mat imgOriginal; // input image

    bool blnFrameReadSuccessfully = capWebcam.read(imgOriginal);                    // get next frame from the webcam
    
    if (!blnFrameReadSuccessfully || imgOriginal.empty()) {                            // if we did not get a frame
        QMessageBox::information(this, "", "unable to read from webcam \n\n exiting program\n");        // show error via message box
        exitProgram();                                                                              // and exit program
        return;                                                                                     //
    }
    
    
    
    flip(imgOriginal, imgOriginal, 0.5);
    QImage qimgOriginal = convertOpenCVMatToQtQImage(imgOriginal);             // convert from OpenCV Mat to Qt QImage
    

    ui->lblOriginal->setPixmap(QPixmap::fromImage(qimgOriginal)); // show images on form labels
    ui->lblCanny->setPixmap(ui->lblOriginal->getRect(qimgOriginal,qimgOriginal.height(),qimgOriginal.width())); //
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////
    QImage frmMain::convertOpenCVMatToQtQImage(cv::Mat mat) {
    if(mat.channels() == 1) { // if grayscale image
    return QImage((uchar*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_Indexed8); // declare and return a QImage
    } else if(mat.channels() == 3) { // if 3 channel color image
    cv::cvtColor(mat, mat, CV_BGR2RGB); // invert BGR to RGB
    return QImage((uchar*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888); // declare and return a QImage
    } else {
    qDebug() << "in convertOpenCVMatToQtQImage, image was not 1 channel or 3 channel, should never get here";
    }
    return QImage(); // return a blank QImage if the above did not work
    }

    
    my_qlabel.h
    

    #ifndef WIDGET_H
    #define WIDGET_H

    #include <QtGui>
    #include<QtCore>
    #include <QtWidgets>
    #include <QApplication>

    class my_qlabel : public QLabel
    {
    public:
    explicit my_qlabel(QWidget * parent = 0)
    : QLabel(parent)
    , mStartX(0)
    , mStartY(0)
    , mEndX(0)
    , mEndY(0)
    , mFirstClick(true)
    , mPaintFlag(false)

    {
        ;
    }
    

    void setPixmap(const QPixmap &);
    QPixmap getRect(QImage original,int hv,int wv){
    QPoint an,bn;

    an.setX(a.x()*hv/width());
    an.setY(a.y()*wv/height());
    
    bn.setX(b.x()*hv/width());
    bn.setY(b.y()*wv/height());
    
    
    
    QRect selection;
    selection.setRect(an.x(),an.y(),bn.x()-an.x(),bn.y()-an.y());
    
    return  QPixmap::fromImage(original.copy(selection));
    

    }

    protected:
    void mousePressEvent(QMouseEvent * e)
    {
    if(e->button() == Qt::LeftButton)
    {
    //store 1st point
    if(mFirstClick)
    {
    // mFirstClick = false;
    a=(e->pos());
    qWarning() << "a "<< a.x()<< " "<< a.y();
    qWarning() << "a "<< a.x()<< " "<< a.y();
    b=(e->pos());
    selectionRect.setRect(a.x(),a.y(),a.x()-b.x(),a.y()-b.y());
    }

        }
    }
    
    
    void mouseMoveEvent(QMouseEvent *e){
       if  (mFirstClick)
       {
        b=(e->pos());
        qWarning() << "b "<< b.x()<< " "<< b.y();
        selectionRect.setRect(a.x(),a.y(),b.x()-a.x(),b.y()-a.y());
        repaint();
       }
    }
    
    
    void mouseRelaseEvent(QMouseEvent *e){
       mFirstClick=false;
    
    }
    
    void paintEvent(QPaintEvent * e)
    {
        QLabel::paintEvent(e);
    
        if(mFirstClick)
        {
            QPainter painter(this);
            QPen paintpen(Qt::red);
            paintpen.setWidth(4);
    
            QPen linepen(Qt::black);
            painter.setPen(linepen);
            painter.drawRect(selectionRect);
        }
    }
    

    private:
    int mStartX;
    int mStartY;
    int mEndX;
    int mEndY;
    QPoint a,b;
    QRect selectionRect;
    bool mFirstClick;
    bool mPaintFlag;
    };

    #endif // WIDGET_H

    
    my_qlabel.cpp
    

    #include "my_qlabel.h"
    #include <QPainter>
    #include <QMouseEvent>
    #include <QDebug>
    #include <QAction>
    #include <QFileDialog>
    #include <iostream>
    #include <QTextStream>

    using namespace std;

    void my_qlabel::setPixmap(const QPixmap& myPixmap){

    QLabel::setPixmap(myPixmap.scaled(width(),height(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation));

    }


  • Qt Champions 2016

    Ok, but did you check the rect values?
    are they what you expect ?
    U are not very clear on "How it is different" and since you seems to
    scale it also, im not sure what the actual issue is.

    I would start checking the values for the QRect selectio and see if they make sense.



  • This is how i see the 2 label.
    alt text


  • Qt Champions 2016

    HI
    Super with pictures.

    Is this how you set image on label 2?
    void my_qlabel::setPixmap(const QPixmap& myPixmap){
    QLabel::setPixmap(myPixmap.scaled(width(),height(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation));
    }

    if yes, you ask it to scale to width(),height() and that would make it look zoomed as in your case.



  • No, i use this line

    ui->lblCanny->setPixmap(ui->lblOriginal->getRect(qimgOriginal,qimgOriginal.height(),qimgOriginal.width())); 
    

    and this

    QPixmap getRect(QImage original,int hv,int wv){
        QPoint an,bn;
    
        an.setX(a.x()*width()/hv);
        an.setY(a.y()*height()/wv);
    
        bn.setX(b.x()*width()/hv);
        bn.setY(b.y()*height()/wv);
    
    //    an.setX(a.x());
    //    an.setY(a.y());
    
    //    bn.setX(b.x());
    //    bn.setY(b.y());
    
        qWarning() << "an "<< an.x()<< " "<< an.y();
        qWarning() << "b "<< bn.x()<< " "<< bn.y();
    
        QRect selection;
        selection.setRect(an.x(),an.y(),bn.x()-an.x(),bn.y()-an.y());
    
        return  QPixmap::fromImage(original.copy(selection));
    
    
    }
    
    
    

    so the getRect() method return only a QPixmap


  • Qt Champions 2016

    ok. Not the scaling then.
    Code seems fine.
    Did you tried with fix area. like (0,0,100,100)
    and then use debugger to follow through code ?

    Should be easy to spot where it goes wrong rect wise.



  • i've solved. The image in the second label was not at the top left but centered, so part of the image was lost .Thank you


  • Qt Champions 2016

    @FED27
    ah, sneaky :)
    Good found.


Log in to reply
 

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