QCamera get resolution and raw frame - c++

I would like to get the resolution of the selected camera and also get the raw frame in the videocapture but I have not found clearly at all how to do it. Could you help me!? Thanks in advance.
// Open camera for reading
cameraQt = new QCamera(cameras.at(cameraIdSelected));
if(!cameraQt->isAvailable())
ui->statusBar->showMessage(tr("Impossible to open camera...."));
cameraQt->setViewfinder(ui->centralWidget);
like : cameraQt->getResolution ?
Thanks.

I think you 1) Should load the cam 2) get imageCapture (raw) from the loaded cam. There is no direct simple type of a resolution, because camera will have a list of supported resolutions, you can set your device to one of those.
Try this to get the list of resolutions for a device:
QList<QByteArray> cameraDevices = QCamera::availableDevices();
QByteArray cameraDevice = cameraDevices[0];
QCamera *camera = new QCamera(cameraDevice);
camera->load();
qDebug() << "Camera status: " << camera->status();
QCameraImageCapture *imageCapture = new QCameraImageCapture(camera);
QList<QSize> resolutions = imageCapture->supportedResolutions();
QListIterator<QSize> it(resolutions);
while (it.hasNext()) {
qDebug() << "Resoution: " << it.next();
}

Related

Problems Displaying Mat Image in Windows Forms C++ Visual Studio 2019

I am new to C++ gui design and I am not too familiar with using pointers. Recently I have run into a few problems when trying to get an OpenCV Mat Image to display in a PictureBox in a constructed gui. I have searching online and even found a very similar post to my question but when trying to implement the guidance I ran into an exception when trying to operate the gui.
A very similar post
Displaying webcam feed in cv::Mat format in a picturebox
Code I grabbed from this post to save you a click:
void DrawCVImage(System::Windows::Forms::Control^ control, cv::Mat& colorImage)
{
System::Drawing::Graphics^ graphics = control->CreateGraphics();
System::IntPtr ptr(colorImage.ptr());
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(colorImage.cols,colorImage.rows,colorImage.step,System::Drawing::Imaging::PixelFormat::Format24bppRgb,ptr);
System::Drawing::RectangleF rect(0,0,control->Width,control->Height);
graphics->DrawImage(b,rect);
delete graphics;
}
Now I am trying to display a "video" feed (really an array of cv::Mat Objects) but I am having a
"Source Not Available"/System.ArgumentException: 'Parameter is not valid.'
screen come up when I attempt to call the function that houses that playback. I also know specific line of code that throws the issue is the line
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(colorImage.cols,colorImage.rows,colorImage.step,System::Drawing::Imaging::PixelFormat::Format24bppRgb,ptr);
Now for specifics, the form has an event (currently the click on the picture box, but I want to move to a "play" button in the future) and on this event, the code:
private: System::Void leftEyeImage_Click(System::Object^ sender, System::EventArgs^ e) {
std::cout << "Click Received" << std::endl;
cv::Mat& frame = cv::imread("Desktop/testcapture.png");
std::cout << "Import successful" << std::endl;
drawLeftEye(this, frame);
}
This code does get execute on click and starts the function drawLeftEye. The function is a modified version of the code from the other post and is below:
This is on the ShowResults.cpp file
namespace DevProject {
void ShowResults::drawLeftEye(System::Windows::Forms::Control^ control, cv::Mat& framebmp) {
System::Drawing::Graphics^ graphics = control->CreateGraphics();
std::cout << "Now Here" << std::endl;
System::IntPtr ptr(framebmp.data);
// Issue line
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(framebmp.cols, framebmp.rows, framebmp.step, System::Drawing::Imaging::PixelFormat::Format32bppRgb, ptr);
std::cout << "Converted successfully" << std::endl;
System::Drawing::RectangleF rect(0, 0, control->Width, control->Height); //No issue
graphics->DrawImage(b, rect);
std::cout << "Now Here before delete" << std::endl;
delete graphics;
//delete b;
}
}
I know based on my cout statements that I do make it into my function and I know my code compiles and runs through the function if I comment out the line:
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(framebmp.cols, framebmp.rows, framebmp.step, System::Drawing::Imaging::PixelFormat::Format32bppRgb, ptr);
//As well as (but only because b is defined in the line above^
graphics->DrawImage(b, rect);
I am not quite sure how to fix this, my friend mentioned this could be a memory issue but I don't know how I would go about fixing it. It is also very possible I have made a simple mistake in the design of this or where my pointers are going and I am just not competent enough to know the error.
By the way the pointer for "this" that is called in the function is linked to the Windows Autogenerated code (from gui construction) of:
this->leftEyeImage->Anchor = System::Windows::Forms::AnchorStyles::None;
this->leftEyeImage->BorderStyle = System::Windows::Forms::BorderStyle::FixedSingle;
this->leftEyeImage->Location = System::Drawing::Point(11, 836);
this->leftEyeImage->Name = L"leftEyeImage";
this->leftEyeImage->Size = System::Drawing::Size(991, 646);
this->leftEyeImage->TabIndex = 4;
this->leftEyeImage->TabStop = false;
this->leftEyeImage->Click += gcnew System::EventHandler(this, &ShowResults::leftEyeImage_Click);
Any and all advice or tests would be very appreciated as I am both interested in the answer and the reasoning. Thanks in advance!

Is there a way to effectively update CAN data in QML?

Currently I am receiving CAN data in real time using socketcan API in main.cpp file.
I am constantly updating the data frame of CAN in one variable in main.cpp.
I want to express the gauge in real time by passing the variable containing the CAN data frame in main.cpp to the QML animation gauge.
I need to detect the change of the variable containing CAN data in QML in real time. I wonder if there is an effective way.
I tried to share data with QML using emit.
However, the function written by emit inside device-> connect (device, & QCanBusDevice :: framesReceived, [device] () {...} does not work.
When using it, I get the error
'this' cannot be implicitly captured in this context.
I looked up the error, but did not find the answer.
if (QCanBus::instance()->plugins().contains(QStringLiteral("socketcan"))) {
qWarning() << "plugin available";
}
QString errorString;
QCanBusDevice *device = QCanBus::instance()->createDevice(
QStringLiteral("socketcan"), QStringLiteral("vcan0"), &errorString);
if (!device) {
qWarning() << errorString;
} else {
device->connectDevice();
std::cout << "connected vcan0" << std::endl;
device->connect(device, &QCanBusDevice::framesReceived, [device]() {
QCanBusFrame frame = device->readFrame();
QString testV = frame.toString();
QString qvSpeed = frame.payload();
std::string text = testV.toUtf8().constData();
std::string vSpeed = qvSpeed.toUtf8().constData();
//At that point the vVal values ​​are being updated in real time.
//I want to pass the updated vVal to qml gui in real time.
int vVal = static_cast<int>(frame.payload()[0]);
//emit sendMessage(vVal); // 'this' cannot be implicitly captured in this context error.
std::cout << text << std::endl;
});
}
As of now, main.cpp can't send the data and QML can't solve the error.
Inside device-> connect, emit sendMessage (vVal); will cause "'this' cannot be implicitly captured in this context" error.
I'm wondering if there is a good way to implement animation by expressing QML GUI data in real time.
Your capture clause only captures device. You need to also explicitly capture this:
device->connect(device, &QCanBusDevice::framesReceived, [this,device]{ /*...*/ });
BTW, note that there's no need to specify the () for a no-args lambda expression.

Qt double buffering behaviour

I am converting some code from using QWidget to QOpenGLWidget, I want to use double buffering to render the widget, so far:
void clsElevStrip::initializeGL() {
qDebug() << "clsElevStrip::initializeGL()";
initializeOpenGLFunctions();
//Get the openGL context
mpobjContext = context();
if ( mpobjContext != NULL ) {
//Setup surface
mobjFormat.setDepthBufferSize(24);
mobjFormat.setSamples(4);
mobjFormat.setVersion(3, 0);
mobjFormat.setProfile(QSurfaceFormat::NoProfile);
mobjFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
int intSB = (int)mobjFormat.swapBehavior();
qDebug() << "swapBehavour as set-up in format: " << QString::number(intSB);
mpobjContext->setFormat(mobjFormat);
intSB = (int)mpobjContext->format().swapBehavior();
qDebug() << "swapBehavour as set-up in context: " << QString::number(intSB);
}
}
I can see in the debugger that intSB is 2 when checking swap behaviour from the format, but when I check intSB as set in the context it is 0, not 2?
As a result of this anything I render to the context is visible.
Resolved:
I modified the code, adding
mpobjContext->create();
After:
mpobjContext->setFormat(mobjFormat);
Now it works!

Released app does not work as the original

I have a file with hundreds and hundreds of pictures (photographs) that I need to show in preview to some people. This preview should be a purchase order (rapidly, nothing "pro") and I would give them so that the people can put a cross in the case they want a picture and which size (as simple as that).
I tried to auto-generate the purchase order, there would be two per page (A4) on a PDF.
I use Qt/C++ and three objects :
QPdfWriter
QPainter
QImage
Here's the beginning of the pdf-generation class :
int order = 1;
qDebug() << "pdf creation";
QString logoName = QFileDialog::getOpenFileName(0, "Sélectionner le logo", QString(), "Images (*.png *.bmp *.jpg)");
QString fileName = QFileDialog::getSaveFileName(0, "Export PDF",
QString(), "*.pdf");
QString dir = QFileDialog::getExistingDirectory(0, "Sélectionner le dossier de photos");
QFont titleFont("Arial", 24);
titleFont.setUnderline(true);
QFont textFont("Times new roman", 12);
QDirIterator it(dir);
if (!fileName.isEmpty()) {
if (QFileInfo(fileName).suffix().isEmpty())
fileName.append(".pdf");
QPdfWriter writer(fileName);
QPainter painter(&writer);
painter.setRenderHint(QPainter::Antialiasing);
int height = painter.device()->height();
int semi = height/2;
int width = painter.device()->width();
int digits = 1;
qDebug() << "height : " << height << " width : " << width;
QImage logo(logoName);
QImage finalLogo = logo.scaled(3750, 1250, Qt::KeepAspectRatio);
while(it.hasNext()){
it.next();
digits = countDigits(order);
if(it.fileInfo().isFile()){
if(order%2!=0){
painter.drawImage(300,100,finalLogo);
QImage currentPreview(it.filePath());
QImage finalPreview = currentPreview.scaled(3250,4000, Qt::KeepAspectRatio);
painter.drawImage(650,1500,finalPreview);
The rest is just the drawing of the text/borders.
I tried it in debug : works fine
I compiled in release, put all the .dll in the file (including platform) and ran it without Qt : works fine
Then I put the files on a usb stick, I put it on the other computer that I use for the pictures, that computer does NOT have Qt.
I launched the .exe and the app showed exactly as on my dev-pc
But when I called the PDF creation I filled the FileDialogs with my data, it runs for around 30 secs (a lot of pictures in the file) and generates the PDF.
I opened it and ... not a single picture on the PDF.
All the lines and texts are in place without any problem, it generates the right amount of purchase order but not a single picture on it ... Neither the logo (QImage finalLogo) nor the preview (QImage finalPreview).
It's like QPainter::drawText()/drawLine() does work, but not QPainter::drawImage.
It's disturbing since it works on a computer but not on another ... Did I do something wrong when compiling/releasing ?
(Answered in the comments - converted to a community wiki.)
The OP wrote:
Ok ! I figured it out. The dll to handle the jpeg was not in the right directory, I moved it to the right one and it worked.

"Unable to read font " ImageMagick++

i try this little bit a of code :
try {
InitializeMagick(*argv);
//create a base image
Image image("400x100",font_color);
//construct a drawing list
std::list<Magick::Drawable> drawList;
//add tracing elements
drawList.push_back(DrawableRectangle(0,0,400,100)); // Draw a rectangle ( the sign)
drawList.push_back(DrawableStrokeColor("black")); // Outline Color
drawList.push_back(DrawableFillColor(font_color)); // Fill color
drawList.push_back(DrawableStrokeWidth(5));
drawList.push_back(DrawablePointSize(50));
drawList.push_back(DrawableFont("#Arial"));
drawList.push_back(DrawableStrokeColor(police_color));
drawList.push_back(DrawableText(10,70,ville));
drawList.push_back(DrawableText(300,70,distance));
image.draw(drawList);
image.write(filedest);
}
catch(exception & error_)
{
cout<<"Caught exception : " << error_.what() << endl;
}
but i get this error when i start the program :
proto.exe:unable to read font `#Arial' # error/annotate.c/RenderFreetype/1126
Just drop the # sign in the font name. It's not needed for the Magick::DrawableFont method.
drawList.push_back(DrawableFont("Arial"));
You can verify the fonts available by running the identify utility.
identify -list font | more