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
-
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 imagebool 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));
}
-
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.
-
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
-
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.