How to use zoom in/out with Qt Camera? - c++

I'm very new to Qt, I have to create an image capture via webcam and print it, in Qt. I have managed to carry out most of the
required tasks but there is one problem that I have when I see the webcam image I would like to zoom in/out to capture an image, How can I do this ? I
have searched the net without any joy. What I have so far
ui->setupUi(this);
vCam = new QCamera(this);
vCamViewfinder = new QCameraViewfinder(this);
vCamImageCapture = new QCameraImageCapture(vCam, this);
vLayout = new QVBoxLayout;
vMenu = new QMenu("Options",this);
vStart = new QAction("Start", this);
vEnd = new QAction("End",this);
vCapture = new QAction("Capture",this);
vMenu->addActions({ vStart, vEnd, vCapture });
ui->pushButton_camAction->setMenu(vMenu);
vCam->setViewfinder(vCamViewfinder);
vLayout->addWidget(vCamViewfinder);
vLayout->setMargin(0);
ui->graphicsView->setLayout(vLayout);
connect(vStart, &QAction::triggered, [&](){
vCam->start();
});
connect(vEnd, &QAction::triggered, [&](){
vCam->stop();
});
connect(vCapture, &QAction::triggered, [&](){
on_pushButton_camAction_clicked();
});
void VisitorSignIn::on_pushButton_camAction_clicked()
{
QString vImage = "C:/Qt/VisitorsImages/1.jpg";
vCamImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToFile);
QImageEncoderSettings imgEncSet;
imgEncSet.setCodec("image/jpeg");
imgEncSet.setResolution(640, 480);
vCamImageCapture->setEncodingSettings(imgEncSet);
vCam->setCaptureMode(QCamera::CaptureStillImage);
vCam->start();
vCam->searchAndLock();
vCamImageCapture->capture(vImage);
vCam->unlock();
}

Have a look on http://doc.qt.io/qt-5/qcamerafocus.html These Methods allow optical and digital zoom.

Related

How to flip image from QCamera?

In QT Creator how we can filp the images from camera. I googled a lot but I didn't get a proper solution.
Following is my code.
mCamera = new QCamera;
mViewfinder = new QCameraViewfinder;
mLayout = new QVBoxLayout(ui->graphicsView);
mLayout->addWidget(mViewfinder);
mCamera->setViewfinder(mViewfinder);
mViewfinder->show();
mCamera->start();
I tried QCamera::FrontFace and QCamera::BackFace in constructor argument in QCamera like below
mCamera = new QCamera(QCamera::FrontFace);
and
mCamera = new QCamera(QCamera::BackFace );
But both have no difference.
In Python
video=cv2.flip(self.frame,1)
will solve the problem,
Any idea how to solve this ..
I am using Windows 10
QCamera::FrontFace and QCamera::BackFace are just positions of the camera. To achieve what you want, you should flip every image.
Create QCameraImageCapture and connect to its imageCaptured() signal.
auto imageCapture = new QCameraImageCapture( mCamera );
connect(imageCapture, &QCameraImageCapture::imageCaptured, [&](int id, const QImage &preview){
QImage flipped = preview.mirrored();
// do what you want with flipped image
})
Documentation says that mirrored(bool horizontal = false, bool vertical = true)
Returns a mirror of the image, mirrored in the horizontal and/or the vertical direction depending on whether horizontal and vertical are set to true or false.
UPDATE:
I found the camera and tested the code and realized that I forgot one important thing. You need to use a timer by which QCameraImageCapture will capture the image.
Create QTimer and connect to QTimer::timeout() signal:
connect (&timer, &QTimer::timeout, [&](){
camera->searchAndLock();
imageCapture->capture();
camera->unlock();
});
And after that start the timer. To show flipped image you can use just QLabel class with label->setPixmap(QPixmap::fromImage(flipped)) method.
Hai I changed my code as per the answer of #Allocse and its work for me
My full code will be
mCamera = new QCamera;
mCamera->start();
imageCapture = new QCameraImageCapture( mCamera );
connect (&timer, &QTimer::timeout, [&](){
mCamera->searchAndLock();
imageCapture->capture();
mCamera->unlock();
});
connect(imageCapture, &QCameraImageCapture::imageCaptured, [&](int id, const QImage &preview){
QImage flipped = preview.mirrored(true,false);
ui->videoFrame->setPixmap(QPixmap::fromImage(flipped));
});
timer.start();
Note :-mCamera and imageCapture should be declared in class decleration

Zooming in / out on images - QT c++

I am currently using QT to load images into a graphicsview scene. Essentially, I am looking for a way to be able to zoom in and out on the loaded image using a slider. The image loads successfully into the pane, but whatever I try to implement to zoom in / out, the image would disappear.
This is how it looks:
This is my implemented function, but the image disappears:
void MainWindow::on_horizontalSlider_valueChanged(int value)
{
float pool ;
if(value==0 )
pool=0.1;
else
pool = value*0.01;
scene->update();
ui->graphicsView->transform();
ui->graphicsView->scale(pool,pool);
}
This is how I'm loading the images:
void MainWindow::on_BrowseImages_clicked()
{
QString imagePath = QFileDialog::getOpenFileName(
this,
tr("Open File"),
"",
tr("Images (*.jpg *.jpeg *.png)" )
);
imageObject = new QImage();
imageObject->load(imagePath);
image = QPixmap::fromImage(*imageObject);
scene = new QGraphicsScene(this);
scene->addPixmap(image);
scene->setSceneRect(image.rect());
ui->graphicsView->setScene(scene);
//ui->graphicsView->fitInView(scene->sceneRect(),Qt::KeepAspectRatio);
}
When scaling is applied to transformation it always scales around origin.
Scaling with a certain center (that is not the origin) means that the center has been translated to the origin before scaling.
This could be
v' = translateO→C(scale(translateC→O(v)))
or with matrix operations
v' = MtranslateO→C • Mscale • MtranslateC→O • v
However, the Grahics View Framework provides something where combining transformations is actually built-in by default:
Every item provides its own local transformation.
The transformation of a group item is applied to the child items as well forming something which can be imagined as a local coordinate system.
This in mind, I came up with the following MCVE where
- translation to center is applied to the pixmap item
- scaling is applied to a group item which becomes parent of the pixmap item.
testQGraphicsViewScaleItem.cc:
// Qt header:
#include <QtWidgets>
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup data
QGraphicsScene qGScene;
QGraphicsItemGroup qGItemGrp;
QImage qImgCat("cat.jpg");
QGraphicsPixmapItem qGItemImg(QPixmap::fromImage(qImgCat));
qGItemImg.setTransform(
QTransform().translate(-0.5 * qImgCat.width(), -0.5 * qImgCat.height()));
qGItemGrp.addToGroup(&qGItemImg);
qGScene.addItem(&qGItemGrp);
// setup GUI
QWidget qWinMain;
qWinMain.setWindowTitle("QGraphicsView - Scale Image");
QVBoxLayout qVBox;
QGraphicsView qGView;
qGView.setScene(&qGScene);
qVBox.addWidget(&qGView, 1);
QSlider qSlider(Qt::Horizontal);
qSlider.setRange(-100, 100);
qVBox.addWidget(&qSlider);
qWinMain.setLayout(&qVBox);
qWinMain.show();
// install signal handlers
auto scaleImg = [&](int value) {
const double exp = value * 0.01;
const double scl = pow(10.0, exp);
qGItemGrp.setTransform(QTransform().scale(scl, scl));
};
QObject::connect(&qSlider, &QSlider::valueChanged,
scaleImg);
// runtime loop
return app.exec();
}
and a qmake project file testQGraphicsViewScaleItem.pro:
SOURCES = testQGraphicsViewScaleItem.cc
QT += widgets
Output:

Using QCamera with multiple cameras

I am trying to show the one camera output on two QLabel widget. However I am not able to do so. I encounter following error.
Graph failed to connect filters -2147024809
However I can see it on one screen not on another. If this is a wrong approach or is it not possible at all?
cM = new QCamera(this);
cM2 = new QCamera(this);
cV = new QCameraViewfinder(this);
cV2 = new QCameraViewfinder(this);
mMenu = new QMenu("Options",this);
cA = new QAction("one camera", this);
cA2 = new QAction("both camera", this);
mMenu->addActions({cA, cA2});
ui->pushButton->setMenu(mMenu);
cM->setViewfinder(cV);
cM2->setViewfinder(cV2);
cBox1 = new QVBoxLayout();
cBox2 = new QVBoxLayout();
cBox1->addWidget(cV);
cBox2->addWidget(cV2);
ui->label->setLayout(cBox1);
ui->label_2->setLayout(cBox2);
connect(cA, &QAction::triggered, [&](){
cM->start();
cM2->start();
You need to construct yoru cameras with cameraInfo, otherwise it's not bound to real hardware. https://doc.qt.io/qt-5/qcamera.html
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
foreach (const QCameraInfo &cameraInfo, cameras)
{
if (cameraInfo.deviceName() == "mycamera")
camera = new QCamera(cameraInfo, this);
}

Qt State Machine Transition in a Layout

Well, I am developing a Qt application and I want use the Qt State Framework to make some animations.
First:
How I can animate a group of buttons contained in a horizontal layout, into another vertical layout, by using state a transition?
Second:
How I can show a widget when in a state? For example a menu: When the user clicks a button in the menu, the widget (that previously has been hidden with widget->hide()) is shown...???
This is a code example:
boxInsert = new BoxInsert(this);
boxInsert->hide ();
btn1 = new QPushButton("Introducir", this);
btn2 = new QPushButton("Informe", this);
btn3 = new QPushButton("Salir", this);
QStateMachine *machine = new QStateMachine(this);
QState *st1 = new QState(machine);
st1->setObjectName ("menuMode");
st1->assignProperty (btn1, "pos", QPointF(center - btn1->width () / 2, 20));
st1->assignProperty (btn2, "pos", QPointF(center - btn1->width () / 2, 40));
st1->assignProperty (btn3, "pos", QPointF(center - btn1->width () / 2, 60));
st1->assignProperty (boxInsert, "visible", QVariant(false));
QState *st2 = new QState(machine);
st2->setObjectName ("barMode");
st2->assignProperty (btn1, "pos", QPointF(40, 0));
st2->assignProperty (btn2, "pos", QPointF(40, 0));
st2->assignProperty (btn3, "pos", QPointF(40, 0));
st1->assignProperty (boxInsert, "visible", QVariant(true));
machine->setInitialState (st1);
QAbstractTransition *t1 = st1->addTransition (btn1, SIGNAL(clicked()), st2);
//QSequentialAnimationGroup *sq1 = new QSequentialAnimationGroup;
//sq1->addPause (250);
t1->addAnimation (new QPropertyAnimation(btn1, "pos"));
t1->addAnimation (new QPropertyAnimation(btn2, "pos"));
t1->addAnimation (new QPropertyAnimation(btn3, "pos"));
t1->addAnimation (new QPropertyAnimation(boxInsert, "visible"));
machine->start ();
It is something like when you will start machine it will change color of a button that may indicate this is clicked then perform something that is linked with your signal so its linked slot will be executed.
s0->addTransition(s1);
s1->assignProperty(ui->pushButton,"styleSheet","background-color:rgb(255,0,0);");
s1->addTransition(s2);
s2->addTransition(ui->pushButton,SIGNAL(clicked()),s0);
QStateMachine m;
m.addState(s0);
m.addState(s1);
m.addState(s2);
m.setInitialState(s0);
To make visible a widget add an state transition like this:
s1->assignProperty(MyWid,"visible", true);
and add transition in s0 for state s1.
First: Move widgets from horizontal layout to vertical using stateMachine? Don't know how to do it, really.
Second: You can implement widget with your own transparency property, that works with QGraphicsEffect:
class myWidget
{
//your methods
Q_PROPERTY(double alpha READ alpha WRITE setAlpha)
double mAlpha;
double alpha() {return mAlpha;}
void setAlpha(double a);
QGraphicsOpacityEffect* eff;
}
make QGraphicsEffect working in setAlpha() method:
void myWidget::setAlpha(double a)
{
mAlpha = a;
if(mAlpha < 0.0)
mAlpha = 0.0;
if(mAlpha > 1.0)
mAlpha = 1.0;
if(mAlpha == 0)
{
this->hide();
}
else
{
this->show();
eff->setOpacity(mAlpha);
}
this->update();
}
And, of course, set QGraphicsOpacityEffect to your widget in constructor:
eff = new QGraphicsOpacityEffect(this);
eff->setOpacity(mAlpha);
this->setGraphicsEffect(eff);
Then you can work with your alpha property in QState:
QState* s1 = new QState(mainState);
s1->assignProperty(mywidget, "alpha", 1.0);
//and so on...

Qt Scroll Area does not add in scroll bars

Hi guys I have to dynamically create push buttons depending on user inputs, therefore if user gives a large input number the widget containing the push buttons has to have the ability to scroll up and down. For this reason I am using QScrollArea. I generate the template in Qt designer and the UIC generates the code for me after which I add in my part which should handle dynamic creation of push buttons. However, I can not seem to get the vertical scroll bars to appear. Here is the relevant part of the code.
verticalWidget = new QWidget(FWHMWorkflowDialog);
verticalWidget->setObjectName(QString::fromUtf8("verticalWidget"));
verticalWidget->setMinimumSize(QSize(150, 0));
verticalWidget->setMaximumSize(QSize(150, 16777215));
verticalLayout_5 = new QVBoxLayout(verticalWidget);
verticalLayout_5->setObjectName(QString::fromUtf8("verticalLayout_5"));
scrollArea = new QScrollArea(verticalWidget);
scrollArea->setObjectName(QString::fromUtf8("scrollArea"));
scrollArea->setMaximumSize(QSize(150, 16777215));
scrollArea->setWidgetResizable(true);
scrollAreaWidgetContents = new QWidget();
scrollAreaWidgetContents->setObjectName(QString::fromUtf8("scrollAreaWidgetContents"));
scrollAreaWidgetContents->setGeometry(QRect(0, 0, 130, 432));
numberOfSlices = numberSlices;
for (int i = 0; i < numberOfSlices; i++)
{
QWidget *horizontalWidget = new QWidget(scrollAreaWidgetContents);
horizontalWidget->setMaximumSize(150,40);
horizontalWidget->setGeometry(QRect(0, i*40, 150, 40));
hWidgetList.push_back(horizontalWidget);
QHBoxLayout *hLayout = new QHBoxLayout(horizontalWidget);
hLayoutList.push_back(hLayout);
hLayout->setSizeConstraint(QLayout::SetMinimumSize);
hLayout->setContentsMargins(-1, 1, -1, 1);
QPushButton *pushButton = new QPushButton(horizontalWidget);
pushButtonList.push_back(pushButton);
QString temp = QString("m_sliceButton").arg(i);
pushButtonList[i]->setObjectName(temp);
pushButtonList[i]->setGeometry(QRect(10, 20+i*40, 98, 27));
hLayout->addWidget(pushButton);
QCheckBox *checkBox = new QCheckBox(horizontalWidget);
checkBoxList.push_back(checkBox);
temp = QString("m_checkBox").arg(i);
checkBoxList[i]->setObjectName(temp);
checkBoxList[i]->setEnabled(true);
checkBoxList[i]->setGeometry(QRect(110, 20+i*40, 21, 22));
hLayout->addWidget(checkBox);
}
scrollArea->setWidget(scrollAreaWidgetContents);
//scrollArea->setWidgetResizable(true);
verticalLayout_5->addWidget(scrollArea);
The output window always looks like the following.
In this example the input by the user is 25 however you can see that the 21st button is cut off and 4 other buttons are not visible.
The size window problem occurring after scroll functionality started working.
You need to add your horizontalWidget to a vertical widget like so:
QVBoxLayout* vLayout = new QVBoxLayout();
for (int i = 0; i < numberOfSlices; i++)
{
QWidget *horizontalWidget = new QWidget();
vLayout->addWidget(horizontalWidget);
....
}
scrollAreaWidgetContents->setLayout(vLayout);
You second problem looks like it comes from this line:
scrollArea = new QScrollArea(verticalWidget);
You're adding scrollArea directly to verticalWidget, but to get it to lay out the way you want you need to put it in a layout. Try the following instead:
QVBoxLayout* l = new QVBoxLayout();
l->addWidget(sliceLabel); // or whatever you call it
l->addWidget(scrollArea);
l->addWidget(clearButton); // again, your name here
verticalWidget->setLayout(l);
Try playing around with the QScrollBarPolicy.
http://doc.qt.digia.com/qt/qabstractscrollarea.html#horizontalScrollBarPolicy-prop
I'm guessing that the default behavior isn't working because there is something strange going on with layouts.