Using QCamera with multiple cameras - c++

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

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

Qt 3D: How to draw a cube with different textures on each face?

I'm new to Qt 3D (C++), and while I'm training with my first 3D app, I couldn't achieve the following:
Creating a cube with 6 different textures on each face... Until now, this is what I've tried:
// Cuboid shape data
Qt3DExtras::QCuboidMesh *cuboid = new Qt3DExtras::QCuboidMesh();
// CuboidMesh Transform
Qt3DCore::QTransform *cuboidTransform = new Qt3DCore::QTransform();
cuboidTransform->setScale(2.0f);
Qt3DExtras::QTextureMaterial *textureMaterial = new Qt3DExtras::QTextureMaterial();
Qt3DRender::QTextureCubeMap *cubMap = new Qt3DRender::QTextureCubeMap();
Qt3DRender::QTextureImage *f1 = new Qt3DRender::QTextureImage();
Qt3DRender::QTextureImage *f2 = new Qt3DRender::QTextureImage();
Qt3DRender::QTextureImage *f3 = new Qt3DRender::QTextureImage();
Qt3DRender::QTextureImage *f4 = new Qt3DRender::QTextureImage();
Qt3DRender::QTextureImage *f5 = new Qt3DRender::QTextureImage();
Qt3DRender::QTextureImage *f6 = new Qt3DRender::QTextureImage();
f1->setSource(QUrl("qrc:/rc/images/cubemap1.png"));
f1->setFace(Qt3DRender::QAbstractTexture::CubeMapNegativeX);
f2->setSource(QUrl("qrc:/rc/images/cubemap2.png"));
f2->setFace(Qt3DRender::QAbstractTexture::CubeMapPositiveX);
f3->setSource(QUrl("qrc:/rc/images/cubemap3.png"));
f3->setFace(Qt3DRender::QAbstractTexture::CubeMapNegativeY);
f4->setSource(QUrl("qrc:/rc/images/cubemap4.png"));
f4->setFace(Qt3DRender::QAbstractTexture::CubeMapPositiveY);
f5->setSource(QUrl("qrc:/rc/images/cubemap5.png"));
f5->setFace(Qt3DRender::QAbstractTexture::CubeMapNegativeZ);
f6->setSource(QUrl("qrc:/rc/images/cubemap6.png"));
f6->setFace(Qt3DRender::QAbstractTexture::CubeMapPositiveZ);
cubMap->addTextureImage(f1);
cubMap->addTextureImage(f2);
cubMap->addTextureImage(f3);
cubMap->addTextureImage(f4);
cubMap->addTextureImage(f5);
cubMap->addTextureImage(f6);
textureMaterial->setTexture(cubMap);
//Cuboid
m_cuboidEntity = new Qt3DCore::QEntity(m_rootEntity);
m_cuboidEntity->addComponent(cuboid);
m_cuboidEntity->addComponent(textureMaterial);
m_cuboidEntity->addComponent(cuboidTransform);
But it gives me a black cube.
I've googled for an example, but all I find is written in OpenGl, which I'm not familiar with. I believe it's possible using Qt C++ Classes only.
I would appreciate your help.
This could be related to back face culling.
could you set the following in your renderer?
activeFrameGraph: ForwardRenderer {
...
frustumCulling: false
}
When using Skybox (which is basically a CuboidMesh with different images on it), this is mandatory. Could be needed here too.
Try using f1->setSource(QUrl::fromLocalFile("...")); instead f1->setSource(QUrl("..."));, etc.
And remember about Status

How to use zoom in/out with Qt Camera?

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.

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.