Are 2 simultaneous webcam windows possible with openCV? - c

I am applying common image transforms to my live webcam capture. I want to display the original webcam in one window and the image with the transforms applied to in another window. However, I am getting same image (filtered) on both windows, I am wondering if I am limited by the OpenCV API or if I am missing something? My code snippet looks like -
/* allocate resources */
cvNamedWindow("Original", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Filtered", CV_WINDOW_AUTOSIZE);
CvCapture* capture = cvCaptureFromCAM(0);
do {
IplImage* img = cvQueryFrame(capture);
cvShowImage("Original", img);
Filters* filters = new Filters(img);
IplImage* dst = filters->doSobel();
cvShowImage("Filtered", dst);
cvWaitKey(10);
} while (1);
/* deallocate resources */
cvDestroyWindow("Original");
cvDestroyWindow("Filtered");
cvReleaseCapture(&capture);

Its possible! Try copying img to another IplImage before sending it to processing and see if that works first.
Yes, I know what you're going to say. But just try that first and see if it does what you want. The code below is just to illustrate what you should do, I don't know if it will work:
/* allocate resources */
cvNamedWindow("Original", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Filtered", CV_WINDOW_AUTOSIZE);
CvCapture* capture = cvCaptureFromCAM(0);
do {
IplImage* img = cvQueryFrame(capture);
cvShowImage("Original", img);
IplImage* img_cpy = cvCreateImage(cvGetSize(img), 8, 3);
img_cpy = cvCloneImage(img);
Filters* filters = new Filters(img_cpy);
IplImage* dst = filters->doSobel();
cvShowImage("Filtered", dst);
/* Be aware that if you release img_cpy here it might not display
* the data on the window. On the other hand, not doing it now will
* cause a memory leak.
*/
//cvReleaseImage( &img_cpy );
cvWaitKey(10);
} while (1);
/* deallocate resources */
cvDestroyWindow("Original");
cvDestroyWindow("Filtered");
cvReleaseCapture(&capture);

Related

OpenCV canny; output image is pure gray

I am learning opencv and reading a book and following examples. The book introduced the canny filter. However there is some problem with my output. As an input image I have given a 512x512 gray scale image but the filter output is pure gray image. Here is the image:
This is the input image.
And this is the output image.
And here is the snippets:
#include <opencv\cv.h>
#include <opencv2\highgui\highgui.hpp>
#include "Resources.h"
IplImage* doCanny(
IplImage* in,
double lowThresh,
double highThresh,
double aperture
) {
if (in->nChannels != 1)
{
return 0; // Canny only handle gray scale images.
}
IplImage* out = cvCreateImage(
CvSize(cvGetSize(in)),
IPL_DEPTH_8U,
1
);
cvCanny(in, out, lowThresh, highThresh, aperture);
return out;
}
int main(int argc, char** argv)
{
IplImage* image = cvLoadImage(IMAGE_FRUIT);
IplImage* output = doCanny(image, 200, 201, 1);
cvNamedWindow("Canny", CV_WINDOW_AUTOSIZE);
cvShowImage("Canny", output);
cvWaitKey(0);
cvReleaseImage(&output);
cvDestroyWindow("Canny");
return 0;
}
Visual Studio 2015, OpenCV version 2.4.13
I think if you step through your code, you will realize the cvCanny function never gets triggered, the returned output from doCanny is a null pointer.
OpenCV's Canny edge detection algorithm only accepts gray scale image, which is why the original code has the "if (in->nChannels != 1)" check, so you need to convert your input image into a grayscale image first.
// Convert to grayscale first
IplImage* gray_image = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
cvCvtColor(image, gray_image, CV_BGR2GRAY);
// Perform Canny
IplImage* output = doCanny(gray_image, 200, 201, 3);
Additional, I think your "aperture" parameter for cvCanny is also invalid, try to use the default value 3 (or 5, 7), and you should be able to see the result.
I would also recommend using the C++ interface instead of the deprecated C interface.

Very Slow Processing of my Opencv Application

I am building an OpenCV application which captures a video from camera and overlays it on another video after removing the background.
I am not able to achieve a reasonable speed as it is playing the output at about 1 fps, whereas my background removal is working at 3fps.
Is there a way to display the background video at its normal speed and overlay the processed video at 3fps ?
I tried commenting out my code and I realized that the problem lies majorly with the Rendering part itself. I tried displaying the video along with my web cam feed and I noticed that there is a drop in the actual fps and the fps of video when displayed with openCV.
here is the sample code:
void main()
{
CvCapture* capture, *Vcap;
capture = cvCaptureFromCAM(0);
if(!capture)
{
printf("Video Load Error");
}
Vcap = cvCaptureFromAVI("bgDemo.mp4");
//printf("\nEntered BGR");
if(!Vcap)
{
printf("Video Load Error");
}
while(1)
{
IplImage* src = cvQueryFrame(Vcap);
if(!src)
{
Vcap = cvCaptureFromAVI("bgDemo.mp4");
continue;
}
IplImage* bck1 = cvCreateImage(cvGetSize(src),8,3);
cvResize(src,bck1,CV_INTER_LINEAR);
cvShowImage("BCK",bck1);
cvWaitKey(1);
}
}
The main problem is that you are allocating a new image at every iteration of the loop without releasing it at the end of the loop. In other words, you have a beautiful memory leak.
A better approach is to simply grab a frame of the video before the loop starts. This will let you create bck1 with the right size just once.
There are other problems with your code, I'm sharing a fixed version below, make sure you pay attention to every line of code to see what changed. I haven't had time to test it, but I'm sure you'll figure it out:
int main()
{
// I know what you are doing, just one capture interface is enough
CvCapture* capture = NULL;
capture = cvCaptureFromCAM(0);
if(!capture)
{
printf("Ooops! Camera Error");
}
capture = cvCaptureFromAVI("bgDemo.mp4");
if(!capture)
{
printf("Ooops! Video Error");
// if it failed here, it means both methods for loading a video stream failed.
// It makes no sense to let the application continue, so we return.
return -1;
}
// Retrieve a single frame from the camera
IplImage* src = cvQueryFrame(capture);
if(!src)
{
printf("Ooops! #1 cvQueryFrame Error");
return -1;
}
// Now we can create our backup image with the right dimensions.
IplImage* bck1 = cvCreateImage(cvGetSize(src),src->depth, src->nChannels);
if(!bck1)
{
printf("Ooops! cvCreateImage Error");
return -1;
}
while(1)
{
src = cvQueryFrame(capture);
if(!src)
{
printf("Ooops! #2 cvQueryFrame Error");
break;
}
cvResize(src, bck1, CV_INTER_LINEAR);
cvShowImage("BCK",bck1);
cvWaitKey(10);
}
cvReleaseImage( &bck1 ); // free manually allocated resource
return 0;
}
These fixes should speed up your application considerably.

Return type as Array of IPlImage

I spend the whole morning today searching for a way to save an array of images in IplImage type in openCV and failed.
This is what I am trying to do :
IplImage* GetThresholdedImage(IplImage* img) {
IplImage* imageTest[2];
IplImage* imgHSV = cvCreateImage(cvGetSize(img), 8, 3); // hold the resulted HSV image
cvCvtColor(img, imgHSV, CV_BGR2HSV); // convert the coming image from the camera from RGB format to HSV (Hue, Saturation, Value)
imageTest[0] = cvCreateImage(cvGetSize(img), 8, 1); //hold the thresholded image of the yellow color
imageTest[1] = cvCreateImage(cvGetSize(img), 8, 1); //hold the thresholded image of the red color
cvSmooth(imgHSV, imgHSV, CV_GAUSSIAN, 11, 11); //smooth the image to remove the noise from the image
cvInRangeS(imgHSV, cvScalar(24, 100, 150), cvScalar(34, 255, 255),
imageTest[0]); //this function filter out the colors in this range (This is a yellow color)
cvInRangeS(imgHSV, cvScalar(172, 100, 150), cvScalar(179, 255, 255),
imageTest[1]); //this function filter out the colors in this range (This is a red color)
cvReleaseImage(&imgHSV);
return *imageTest;
}
Now when I try to return the array in the main in order to process it -->
IplImage *thresholdedImage;// = cvCreateImage(cvGetSize(frame), 8, 1); // to store the thresholded image
IplImage *yellow = cvCreateImage(cvGetSize(frame), 8, 1);
IplImage *red = cvCreateImage(cvGetSize(frame), 8, 1);
//===========================================
// start creating three windows to show the video after being thresholded, after it passes the contour function and the final video
cvNamedWindow("display", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Threshold", CV_WINDOW_AUTOSIZE);
cvNamedWindow("contoured", CV_WINDOW_AUTOSIZE);
while (key != 'q') { // grab the video unless the user press q button
frame = cvQueryFrame(capture);
if (!frame) {
break;
}
//start the actual video processing on real-time frames
//first output of the threshold method
thresholdedImage = GetThresholdedImage(frame);
yellow = *thresholdedImage;
red = *thresholdedImage++;
//insert the resulted frame from the above function into the find contour function
cvFindContours(yellow, storage, &contours, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
cvFindContours(red, storage, &contours, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
however it gives me error !!!
any help is appreciated , thank you
An array of pointers to IplImage would be IplImage**. Also note, that you have to provide the buffer from the outside, as you can't return a pointer to local (non-static) data.
void GetImages(IplImage** images, unsigned int num) {
// assign pointers here
images[0] = ...
images[1] = ...
}
IplImage *images[2];
GetImage(images, 2);
As an alternative, you could as well create the array within your function using new or malloc and return the pointer to it. Just ensure you delete/free it later on.
IplImage **CreateImages(unsigned int num) {
IplImage **images = new IplImage*[num];
// assign again
images[0] = ...
return images;
}
Also ensure you free the images, once you're done with them. So you shouldn't use the approach you used above (increasing the pointer). Instead simply use array syntax to access n-th element.
Your code fails due to returning only a single pointer to the first image instead of the actual array.

OpenCV cvCanny memory exception

I am trying to do the examples in the OpenCV book and I got to the part regarding cvCanny. I am trying to use it, but I keep getting a memory exception error of
Unhandled exception at 0x75d8b760 in Image_Transform.exe: Microsoft C++ exception: cv::Exception at memory location 0x0011e7a4..
I have also looked at another post that was similar to this question, but it did not help for me as I got the same error each time. Any help is greatly appreciated and the source code for the function is located below.
void example2_4(IplImage* img)
{
// Create windows to show input and ouput images
cvNamedWindow("Example 2-4 IN", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Example 2-4 OUT", CV_WINDOW_AUTOSIZE);
// Display out input image
cvShowImage("Example 2-4 IN", img);
// Create an image to hold our modified input image
IplImage* out = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
// Do some smoothing
//cvSmooth(img, out, CV_GAUSSIAN, 3, 3);
// Do some Edge detection
cvCanny(img, out, 10, 20, 3);
// Show the results
cvShowImage("Example 2-4 OUT", out);
// Release the memory used by the transformed image
cvReleaseImage(&out);
// Wait for user to hit a key then clean up the windows
cvWaitKey(0);
cvDestroyWindow("Example 2-4 IN");
cvDestroyWindow("Example 2-4 OUT");
}
int main()
{
// Load in an image
IplImage* img = cvLoadImage("images/00000038.jpg");
// Run the transform
example2_4(img);
// clean the image from memory
cvReleaseImage(&img);
return 0;
}
You forgot to say if you are able to see the original image being displayed on the screen.
I never get tired of telling people that checking the return of functions is a must!
Consider IplImage* img = cvLoadImage("images/00000038.jpg"); , how can you tell if this function succeeded or not? As far as I can tell, the error you are having might be from a function failing prior to cvCanny() being called.
Anyway, I recently posted a code that uses cvCanny to improve circle detection. You can check that code and see what you are doing differently.
EDIT:
Your problem in this case is that you are passing to cvCanny input and output as a 3 channel image, when it takes only a single channel image. Check the docs:
void cvCanny(const CvArr* image, CvArr* edges, double threshold1, double threshold2, int aperture_size=3)
Implements the Canny algorithm for edge detection.
Parameters:
* image – Single-channel input image
* edges – Single-channel image to store the edges found by the function
* threshold1 – The first threshold
* threshold2 – The second threshold
* aperture_size – Aperture parameter for the Sobel operator (see Sobel)
So, change your code to:
// Create an image to hold our modified input image
IplImage* out = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
// Do some smoothing
//cvSmooth(img, out, CV_GAUSSIAN, 3, 3);
IplImage* gray = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
cvCvtColor(img, gray, CV_BGR2GRAY);
// Do some Edge detection
cvCanny(gray, out, 10, 20, 3);

OpenCV show both incoming video and modified video in separate windows

This should be easy. I have a video stream coming in from my webcam. I'm just playing with image transformation etc. I'd like to be able to view the original images (video input) in one window and the transformed video in another. Problem is, as soon as I start capturing video instead of just single images, the original video window displays transformed video. I don't understand why.
cvNamedWindow("in", CV_WINDOW_AUTOSIZE);
cvNamedWindow("out", CV_WINDOW_AUTOSIZE);
CvCapture *fc = cvCaptureFromCAM(0);
IplImage* frame = cvQueryFrame(fc);
if (!frame) {
return 0;
}
IplImage* greyscale = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
IplImage* output = cvCreateImage(cvGetSize(frame),IPL_DEPTH_32F , 1);
while(1){
frame= cvQueryFrame(fc);
cvShowImage("in", frame);
// manually convert to greyscale
for (int y = 0; y < frame->height; y++) {
uchar* p = (uchar*) frame->imageData + y* frame->widthStep; // pointer to row
uchar* gp = (uchar*) greyscale->imageData + y*greyscale->widthStep;
for(int x = 0; x < frame->width; x++){
gp[x] = (p[3*x] + p[3*x+1] + p[3*x+2])/3; // average RGB values
}
}
cvShowImage("out", greyscale);
char c = cvWaitKey(33);
if (c == 27) {
return 0;
}
}
In this simple example, both video streams end up appearing greyscale... The pointer values and imagedata for frame and greyscale are totally different. If I stop showing greyscale in the "out" window, then frame will appear in color.
Also, if I continue and apply a Sobel operation on the greyscale image and display the result in "out", both "in" and "out" windows will show the Sobel image!
Any ideas?
Hmm This was weird, but it seems using CV_WINDOW_AUTOSIZE was the problem? Perhaps it's not supported in OpenCV 2.1 (which I'm pretty sure is what I'm running). Anyways, using 0 instead of CV_WINDOW_AUTOSIZE when creating the windows works fine.
I have tried your code with openCV 2.0 under mandriva 2010 and it is working fine either with CV_WINDOW_AUTOSIZE or 0.
You may try to convert to grayscale with cvCvtColor(frame,grayscale,CV_RGB2GRAY) and see if the problem persist.

Resources