cvResizeWindow() flicker reaction - opencv

I have an OpenCV window that I would like to resize to fill my screen, but when I use the resize function the window flickers. The output is my webcam and I guess the flicker is because my camera does not have those dimensions. Is there any other way to make the output from the camera larger?
cvNamedWindow("video", CV_WINDOW_AUTOSIZE);
IplImage *frame=0;
frame=cvQueryFrame(capture);
cvShowImage("video", frame);
cvResizeWindow("video", 1920,1080);

Give you an example of using cvResize() to resize the image or frame.
IplImage *frame;
CvCapture *capture = cvCaptureFromCAM(0);
cvNamedWindow("capture", CV_WINDOW_AUTOSIZE);
while(1) {
frame = cvQueryFrame(capture);
IplImage *frame_resize = cvCreateImage(cvSize(1366, 768), frame -> depth, frame -> nChannels);
cvResize(frame, frame_resize, CV_INTER_LINEAR);
cvShowImage("capture", frame);
cvWaitKey(25);
}

One possibility is to use the cvResize() function to change the size of the frame.
However, an easier way is to get rid of the CV_WINDOW_AUTOSIZE flag -- without that the video will be displayed at the size of the window.
Something like this:
cvNamedWindow("video", 0);
cvResizeWindow("video", 1920,1080);
IplImage *frame=0;
while(true)
{
frame=cvQueryFrame(capture);
cvShowImage("video", frame);
int c = waitKey(10);
...
}
I am not sure of the cause of the flickering, as I could not replicate that issue on my system.
Therefore I cannot guarantee that the flickering will disappear for you (but at least the video should be the correct size).

Related

Show opencv video frames in widget QT5 c++

I want to display a video read with OpenCV in a qt widget.I have already read the frames (have function that reads frames) but don't know how to show them. I need to show the video in a little widget in a window.
Please share a code that can help me.
as far as I know, you should play video in a Qlabel. this link might help you about Qlabel: https://doc.qt.io/qt-6/qlabel.html
at first create a label and then can play your video in while(1) loop; dont forgot that input shape of the image in Qlabel is QPixmap but shape of image in openCV is Mat; so you have to convet image shape from Mat to QPixmap.
for this you can convert mat to QImage and then you can convet QPixmap to QImage in Qt.
I hope you will realize it when you read code and its comments.
cv::VideoCapture cap("String Video Address");
if(!cap.isOpened())
QMessageBox::information(this, "", "error: Video not loaded "); // show error message
cv::Mat cvframe;
QImage Qframe;
while(1){
cap >> cvframe;
if (cvframe.empty())
break;
Qframe = convertOpenCVMatToQtQImage(cvframe);
ui->Video_lable->setPixmap(QPixmap::fromImage(Qframe)); // show images on form labels
ui->Video_lable->setScaledContents( true );
ui->Video_lable->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
char c=(char)cv::waitKey(25); // waits to display frame
if(c==27)
break;
}
//The function that convert OpenCVMat To QtQImageQImage
QImage MainWindow::convertOpenCVMatToQtQImage(cv::Mat mat)
{
if(mat.channels() == 1) { // if 1 channel (grayscale or black and white) image
return QImage((uchar*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_Indexed8);// return QImage
}
else if(mat.channels() == 3) { // if 3 channel color image
cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB);// flip colors
return QImage((uchar*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);// return 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
}

How to store image from cam?

I am just started with processing.js.
The goal of my program is adept image filter(opencv) to video frame.
So I thought (However I found out it does not working in this way :<) :
get video steam from Capture object which in processing.video package.
Store current Image(I hope it can store as PImage Object).
adept OpenCV image Filter
call image method with filtered PImage Object.
I found out how to get video stream from cam, but do not know how to store this.
import processing.video.*;
import gab.opencv.*;
Capture cap;
OpenCV opencv;
public void setup(){
//size(800, 600);
size(640, 480);
colorMode(RGB, 255, 255, 255, 100);
cap = new Capture(this, width, height);
opencv = new OpenCV(this, cap);
cap.start();
background(0);
}
public void draw(){
if(cap.available()){
//return void
cap.read();
}
image(cap, 0, 0);
}
this code get video stream and show what it gets. However, I can not store single frame since Capture.read() returns 'void'.
After Store current frame I would like to transform PImage s with OpenCV like :
PImage gray = opencv.getSnapshot();
opencv.threshold(80);
thresh = opencv.getSnapshot();
opencv.loadImage(gray);
opencv.blur(12);
blur = opencv.getSnapshot();
opencv.loadImage(gray);
opencv.adaptiveThreshold(591, 1);
adaptive = opencv.getSnapshot();
Is there any decent way to store and transform current frame? (I think my way - this means show frame after save current image and transform - uses lots of resources depend on frame rate)
Thanks for answer :D
not sure what you want to do, I'm sure you solved it already, but this could be useful for someone anyway...
It seems you can just write the Capture object's name directly and it returns a PImage:
cap = new Capture(this, width, height);
//Code starting and reading capture in here
PImage snapshot = cap;
//Then you can do whatever you wanted to do with the PImage
snapshot.save("snapshot.jpg");
//Actually this seems to work fine too
cap.save("snapshot.jpg");
Use opencv.loadImage(cap). For example:
if (cap.available() == true) {
cap.read();
}
opencv.loadImage(cap);
opencv.blur(15);
image(opencv.getSnapshot(), 0, 0);
Hope this helps!

Real time circle detection using OpenCV

I have written the following program to detect a circle in real time. But it doesn't work.
The compiler doesn't show any error but the problem is that the program doesn't even detect a circle. How can I fix it?
here is my code
using namespace cv;
int main()
{
VideoCapture cap(0);
namedWindow("main",CV_WINDOW_AUTOSIZE);
namedWindow("blur",CV_WINDOW_AUTOSIZE);
Mat img;
Mat img2;
int c;
float radius;
while(1)
{
cap>>img;
imshow("main",img);
cvtColor(img,img2,CV_BGR2GRAY);
GaussianBlur(img2,img2,Size(9,9),2,2);
imshow("blur",img2);
vector <Vec3f> circles;
HoughCircles(img2,circles,CV_HOUGH_GRADIENT,1,img2.rows/8,200,100,0,0);
for(size_t i=0;i<circles.size();i++)
{
Point center(cvRound(circles[i][0]),cvRound(circles[i][1]));
radius = cvRound(circles[i][2]);
circle(img,center,3,Scalar(0,255,0),-1,8,0);
circle(img,center,radius,Scalar(0,0,255),3,8,0);
}
c = waitKey(33);
if(c==27)
break;
}
destroyAllWindows();
return 0;
}
I checked your program, it seems you just forgot to visualize it using imshow() after the detection. You only drew the image before the detection, in this way, you were not able to see the circles (maybe this mistakenly make you think there is no circles detected) even it did detect some circles.
Try to add
imshow("main", img);
right before c = waitKey(33);.
You will see the circles if it does detect some circles.
Edit: to answer your comment for real time circle detection:
Do it in a while loop style will make it work for video frames. However, whether it is real time or not depends on how fast HoughCircles() will work and also other stuff inside the loop despite you setup the proper time for waitKey().

the nchannel() returns always 1 even in the case of color video image

I'm coding an opencv 2.1 program with visual c++ 2008 express. I want to get each pixel color data of each pixel and modify them by pixel.
I understand that the code "frmSource.channels();" returns the color channels of the mat frmSource, but it always returns 1 even if it is absolutely color video image, not 3 or 4.
Am I wrong?
If I'm wrong, please guide me how to get the each color component data of each pixel.
Also, the total frame count by "get(CV_CAP_PROP_FRAME_COUNT)" is much larger than the frame count I expected, so I divide the "get(CV_CAP_PROP_FRAME_COUNT) by get(CV_CAP_PROP_FPS Frame rate.") and I can get the result as I expected.
I understand that the frame is like a cut of a movie, and 30 frames per sec. Is that right?
My coding is as follows:
void fEditMain()
{
VideoCapture vdoCap("C:/Users/Public/Videos/Sample Videos/WildlifeTest.wmv");
// this video file is provided in window7
if( !vdoCap.isOpened() )
{
printf("failed to open!\n");
return;
}
Mat frmSource;
vdoCap >> frmSource;
if(! frmSource.data) return;
VideoWriter vdoRec(vRecFIleName, CV_FOURCC('W','M','V','1'), 30, frmSource.size(), true);
namedWindow("video",1);
// record video
int vFrmCntNo=1;
for(;;)
{
int vDepth = frmSource.depth();
vChannel = frmSource.channels();
// here! vChannel is always 1, i expect 3 or 4 because it is color image
imshow("video", frmSource);// frmSource Show
vdoRec << frmSource;
vdoCap >> frmSource;
if(! frmSource.data)
return;
}
return;
}
I am not sure if this will answer your question but if you use IplImage it will be very easy to get the correct number of channels as well as manipulate the image. Try using:
IplImage *frm = cvQueryFrame(cap);
int numOfChannels = channelfrm->nChannels;
A video is composed of frames and you can know how many frames pass in a second by using get(CV_CAP_PROP_FPS). If you divide the frame count by the FPS you'll get the number of seconds for the clip.

mouse handler in opencv for large images, wrong x,y coordinates?

i am using images that are 2048 x 500 and when I use cvShowImage, I only see half the image. This is not a big deal because the interesting part is on the top half of the image. Now, when I use the mouseHandler to get the x,y coordinates of my clicks, I noticed that the coordinate for y (the dimension that doesnt fit in the screen) is wrong.
It seems OpenCV think this is the whole image and recalibrates the coordinate system although we are only effectively showing half the image.
I would need to know how to do 2 things:
- display a resized image that would fit in the screen
get the proper coordinate.
Did anybody encounter similar problems?
Thanks!
Update: it seems the y coordinate is divided by 2 of what it is supposed to be
code:
EXPORT void click_rect(uchar * the_img, int size_x, int size_y, int * points)
{
CvSize size;
size.height = size_y ;
size.width = size_x;
IplImage * img;
img = cvCreateImageHeader(size, IPL_DEPTH_8U, 1);
img->imageData = (char *)the_img;
img->imageDataOrigin = img->imageData;
img1 = cvCreateImage(cvSize((int)((size.width)) , (int)((size.height)) ),IPL_DEPTH_8U, 1);
cvNamedWindow("mainWin",CV_WINDOW_AUTOSIZE);
cvMoveWindow("mainWin", 100, 100);
cvSetMouseCallback( "mainWin", mouseHandler_rect, NULL );
cvShowImage("mainWin", img1 );
//// wait for a key
cvWaitKey(0);
points[0] = x_1;
points[1] = x_2;
points[2] = y_1;
points[3] = y_2;
//// release the image
cvDestroyWindow("mainWin");
cvReleaseImage(&img1 );
cvReleaseImage(&img);
}
You should create a window with the CV_WINDOW_KEEPRATIO flag instead of the CV_WINDOW_AUTOSIZE flag. This temporarily fixes the problem with your y values being wrong.
I use OpenCV2.1 and visual studio C++ compiler. I fix this problem with another flag CV_WINDOW_NORMAL and work properly and returns correct coordinates, this flag enables you to resize the image window.
cvNamedWindow("Box Example", CV_WINDOW_NORMAL);
I am having the same problem with OpenCV 2.1 using it with Windows and mingw compiler. It took me forever to find out what was wrong. As you describe it, cvSetMouseCallback gets too large y coordinates. This is apparently due to the image and the cvNamedWindow it is shown in being bigger than my screen resolution; thus I cannot see the bottom of the image.
As a solution I resize the images to a fixed size, such that they fit on the screen (in this case with resolution 800x600, which can be any other values:
// g_input_image, g_output_image and g_resized_image are global IplImage* pointers.
int img_w = cvGetSize(g_input_image).width;
int img_h = cvGetSize(g_input_image).height;
// If the height/width ratio is greater than 6/8 resize height to 600.
if (img_h > (img_w*6)/8) {
g_resized_image = cvCreateImage(cvSize((img_w*600)/img_h, 600), 8, 3);
}
// else adjust width to 800.
else {
g_resized_image = cvCreateImage(cvSize(800, (img_h*800)/img_w), 8, 3);
}
cvResize(g_output_image, g_resized_image);
Not a perfect solution, but works for me...
Cheers,
Linus
How are you building the window? You are not passing CV_WINDOW_AUTOSIZE to cvNamedWindow(), are you?
Share some source, #Denis.

Resources