I'm using OpenCV 3.2.0 compiled with Qt support and function cv::addText to put text on image. Here's the simplest code that reproduces the error
#include <opencv/cv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
if (argc != 2)
{
cout << " Usage: display_image ImageToLoadAndDisplay" << endl;
return -1;
}
Mat image, resized;
image = imread(argv[1], IMREAD_COLOR); // Read the file
namedWindow("test", 1);
addText(image, "SomeText", Point(5, 27), fontQt("Times"));
namedWindow("Display window", WINDOW_AUTOSIZE); // Create a window for display.
imshow("Display window", image); // Show our image inside it.
waitKey(0); // Wait for a keystroke in the window
return 0;
}
I get the following error
/home/vitaly/CLionProjects/opencvTest/cmake-build-debug/opencvTest
/home/vitaly/Pictures/img.jpg OpenCV Error: Null pointer (NULL
guiReceiver (please create a window)) in cvAddText, file
/home/vitaly/Documents/opencv/opencv/modules/highgui/src/window_QT.cpp,
line 114 terminate called after throwing an instance of
'cv::Exception' what():
/home/vitaly/Documents/opencv/opencv/modules/highgui/src/window_QT.cpp:114:
error: (-27) NULL guiReceiver (please create a window) in function
cvAddText
which goes away if I add
namedWindow("test", WINDOW_AUTOSIZE);
before addText.
However, I cannot understand why would qt or opencv need an opened window for that ? I don't need to display the image, I'm only using it to put text on image and then save it, I don't want to create any windows.
So here's my questions
Why window is required for that ?
Is there a way around it ? (To not create windows)
As you can see in the source code:
CV_IMPL void cvAddText(const CvArr* img, const char* text, CvPoint org, CvFont* font)
{
if (!guiMainThread)
CV_Error( CV_StsNullPtr, "NULL guiReceiver (please create a window)" );
QMetaObject::invokeMethod(guiMainThread,
"putText",
autoBlockingConnection(),
Q_ARG(void*, (void*) img),
Q_ARG(QString,QString::fromUtf8(text)),
Q_ARG(QPoint, QPoint(org.x,org.y)),
Q_ARG(void*,(void*) font));
}
addText requires a gui thread. as the actual drawing happens in that thread. No thread, no function, no drawing...
Why is it like that? Well because it made sense to somebody I guess.
It's open source, feel free to code your own workaround. Otherwise use OpenCV's putText.
puttext should work fine as already suggested.
If you're looking for more powerful gui formatting options, you can use the CanvasCV library which blends into the OpenCV main loop.
Here is a tutorial about using its Text widget.
Here is another one about auto centering text with layouts.
Related
I want to show a live stream of the camera connected to raspberry in qt application (OS Linux). After googling it, I found out I must display the video inside QLabel. When displaying an image there's no problem and everything works fine, but when I want to display the live stream inside QLabel, the live stream window opens separately (not inside QLabel). would you tell me how to solve this problem? here's my code :
void Dialog::on_Preview_clicked()
{
command = "raspistill";
args<<"-o"<<"/home/pi/Pictures/Preview/"+Date1.currentDateTime().toString()+".jpg"<<"-t"<<QString::number(20000);
Pic.start(command,args,QIODevice::ReadOnly);
QPixmap pix("//home//pi//Pictures//Preview//test.jpg");
ui->label_2->setPixmap(pix);
ui->label_2->setScaledContents(true);
}
This code opens video capturing screen and captures an image after 20 seconds. the only problem is that the capture screen (which could be used as a live stream). isn't being displayed inside the "Lable_2". Is there anyway to do this without using OpenCV library? If not, tell me how to do it using OpenCV.
Thanks
It is pretty simple in opencv
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat edges;
namedWindow("edges",1);
for(;;)
{
Mat frame;
cap >> frame; // get a new frame from camera
imshow("edges", frame);
if(waitKey(30) >= 0) break;
}
return 0;
}
Stream the camera using OpenCV, and show it in QLabel is possible.
When QCamera not working, and also use OpenCV in the project, could use VideoCapture to stream the video instead of QCamera.
The problem can be decomposed into several steps. Basically, We need:
Create a QThread for streaming(Don't let the GUI thread blocked).
In the sub-thread, using cv::VideoCapture to capture the frame into a cv::Mat.
Convert the cv::Mat to QImage(how to convert an opencv cv::Mat to qimage).
Pass QImage frame from sub-thread to the main GUI thread.
Paint the QImage on the QLabel.
I put the complete demo code in Github. it could paint the frame on the QLabel and QML VideoOutput.
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
int isSquare(String fileName);
int main() {
String imgName = "C:/A.jpg";
isSquare(imgName);
}
int isSquare(String fileName) {
Mat img;
img = cv::imread(fileName, IMREAD_COLOR);
if (img.empty()) {
cout << "Could not open or find the image" << endl;
return -1;
}
//namedWindow("display", WINDOW_AUTOSIZE);
imshow("display", img);
waitKey(0);
cout << "hi";
destroyWindow("display");
return 0;
}
Hi, I'm currently messing around with openCV 3.30, C++. Now I'm trying to open an image, but the display window just kept disappear when I execute above code. I commented namedWindow("display", WINDOW_AUTOSIZE); because openCV document says cv:imshow() will automatically create one, and if I un-comment that line I got one gray window, one image window like this.
I don't want to got that gray window, and key input for waitKey(0) works only when I focus on gray window, not on image window.
So I made that line as a comment. but if I do that, when I execute that code the image window disappears instantly as if I don't have waitKey(0) code. Clearly waitKey(0) is not working because cout<<"hi"; after waitKey(0) was executed.
Am I missing something? Is the document wrong and using namedWindow necessary? All I wanted was to get rid of that gray window... any words of wisdom is appreciated, thanks.
I use opencv2.4.9 whith visual studio 2010
when I have to show an image program display the empty window and not show image
and its my code:
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\core\core.hpp>
#include<opencv\cv.h>
int main(int argc,char**argv[]) {
IplImage* img1=cvLoadImage("C:\opencv\sources\samples\cpp\board.jpg");
cvNamedWindow("img1",CV_WINDOW_AUTOSIZE);
cvShowImage("img1",img1);
cvWaitKey(0);
cvReleaseImage(&img1);
}
The problem is in the way you wrote the path of the image. you should not use the escape character alone. You can solve it by one of these:
IplImage* img1=cvLoadImage("C:\\opencv\\sources\\samples\\cpp\\board.jpg");
Or:
IplImage* img1=cvLoadImage("C:/opencv/sources/samples/cpp/board.jpg");
Or:
IplImage* img1=cvLoadImage(R"(C:\opencv\sources\samples\cpp\board.jpg)");
BTW, you are using C interface which is really too out of data. If you do not have a REAL reason to use it, please do not. The equivalent code that use C++ is:
int main(int argc,char**argv[]) {
cv::Mat img1=cv::imread("C:\\opencv\\sources\\samples\\cpp\\board.jpg");
cv::namedWindow("img1",CV_WINDOW_AUTOSIZE);
cv::imshow("img1",img1);
cv::waitKey(0);
//No need to release manually
}
if you use Mat then you can use:
if (frame1.empty())
{
std::cout << "no image";
break;
}
then if the image not empty you should use more delay to display the images.
for example you can use:
waitKey(100);
I have a VS console application that is built using opencv library. I am displaying image using the opencv imshow function. The thing is that all the imshow windows overlap over each other and it is difficult to toggle between them. How can I prevent the overlap and display them separately and toggle between them
The way to go about this programatically, is to call resizeWindow() to define each windows' size and moveWindow() to place them at specific locations in your screen.
void cv::resizeWindow(const string& winname, int width, int height)
void cv::moveWindow(const string& winname, int x, int y)
Although this is a late reply, you may find it useful to call moveWindow() after each imshow() call. A language independent solution is given here.
Example steps :-
call imshow("first image", img1)
call moveWindow("first image", img1, 0, 0) //Default position of window is at col,row == 0,0. So, this line is optional.
call imshow("second image", img2)
set firstImageWidth = width of img1
set mySpacing = 40 //vary this to increase/decrease the gap between the image windows.
call moveWindow("first image", firstImageWidth + mySpacing , 0)
Then, add these lines to prevent output windows from being forever active.
set myTime = 7000 //in milliseconds. Here, 7000 ms == 7 secs to show our image windows.
call waitKey(myTime)
call waitKey(1) //this is a trick. Otherwise, the windows are opened indefinitely.
At the moment, I am using Java SE8 with OpenCV 4.2. The above method works for me.
[Screenshot of the above example in action.][1]
[1]: https://i.stack.imgur.com/JaTI0.png
Here is a Java+OpenCV code snippet for the display part:
...
//display image. Using OpenCV HighGui class methods.
String inputWindowName = "This window shows input image";
String outputWindowName = "This window shows output image";
HighGui displayWindow = new HighGui();
displayWindow.imshow(inputWindowName, img1);
displayWindow.imshow(outputWindowName, img2);
displayWindow.moveWindow(outputWindowName, img1.cols()+40, 0);
displayWindow.waitKey(7000);
displayWindow.waitKey(1);
Good day everyone! So currently I'm working on a project with video processing, so I decided to give a try to OpenCV. As I'm new to it, I decided to find few sample codes and test them out. First one, is C OpenCV and looks like this:
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <stdio.h>
int main( void ) {
CvCapture* capture = 0;
IplImage *frame = 0;
if (!(capture = cvCaptureFromCAM(0)))
printf("Cannot initialize camera\n");
cvNamedWindow("Capture", CV_WINDOW_AUTOSIZE);
while (1) {
frame = cvQueryFrame(capture);
if (!frame)
break;
IplImage *temp = cvCreateImage(cvSize(frame->width/2, frame->height/2), frame->depth, frame->nChannels); // A new Image half size
cvResize(frame, temp, CV_INTER_CUBIC); // Resize
cvSaveImage("test.jpg", temp, 0); // Save this image
cvShowImage("Capture", frame); // Display the frame
cvReleaseImage(&temp);
if (cvWaitKey(5000) == 27) // Escape key and wait, 5 sec per capture
break;
}
cvReleaseImage(&frame);
cvReleaseCapture(&capture);
return 0;
}
So, this one works perfectly well and stores image to hard drive nicely. But problems begin with next sample, which uses C++ OpenCV:
#include "opencv2/opencv.hpp"
#include <string>
using namespace cv;
int main(int, char**)
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat edges;
//namedWindow("edges",1);
for(;;)
{
Mat frame;
cap >> frame; // get a new frame from camera
cvtColor(frame, edges, CV_RGB2XYZ);
imshow("edges", edges);
//imshow("edges2", frame);
//imwrite("test1.jpg", frame);
if(waitKey(1000) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
So, yeah, generally, in terms of showing video (image frames) there is practically no changes, but when it comes to using im** functions, some problems arise.
Using cvSaveImage() works out nicely, but the moment I try to use imwrite(), unhandled exception arises in regards of 'access violation reading location'. Same goes for imread(), when I'm trying to load image.
So, the thing I wanted to ask, is it possible to use most of the functionality with C OpenCV? Or is it necessary to use C++ OpenCV. If yes, is there any solution for the problem I described earlier.
Also as stated here, images initially are in BGR-format, so conversion needed. But doing BGR2XYZ conversion seems to invert colors, while RGB2XYZ preserve them. Examples:
images
Or is it necessary to use C++ OpenCV?
No, there is no necessity whatsoever. You can use any interface you like and you think you are good with it (OpenCV offers C, C++, Python interfaces).
For your problem about imwrite() and imread() :
For color images the order channel is normally Blue, Green, Red , this
is what imshow() , imread() and imwrite() expect
Quoted from there