OpenCV Canny Edge on Live Video

11,582

Solution 1

The Problem is that you are passing a 3 channel image everywere

IplImage* out = cvCreateImage( cvGetSize(frame), IPL_DEPTH_8U, 3 );

Create other two images of single channel and use those:

IplImage* gray_out = cvCreateImage( cvGetSize(frame), IPL_DEPTH_8U, 1 );
IplImage* canny_out = cvCreateImage( cvGetSize(frame), IPL_DEPTH_8U, 1 );

and use it in:

cvSmooth( frame, out, CV_GAUSSIAN, 11, 11 );
cvCvtColor(out , gray_out, CV_RGB2GRAY);
cvCanny( gray_out, canny_out, 10, 10, 3 );

if( !frame ) break;
cvShowImage( "Edge", canny_out );

This works for me:

#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <cv.h>
#include <cvaux.h>
#include <cxcore.h>
#include <highgui.h>
#include <math.h>
#include <string.h>


using namespace std;
using namespace cv;

int main(int, char**)
{

    cvNamedWindow("Edges", CV_WINDOW_AUTOSIZE); 
CvCapture* capture = cvCaptureFromCAM(0);

IplImage* frame;
    while(1) {
        frame = cvQueryFrame( capture );

        int depth_img =frame->depth;
        int height_img =frame->height;
        int width_img =frame->width;
        int size_img =frame->imageSize;
        int nchan_img =frame->nChannels;
        int nsize_img =frame->nSize;

        cout << setw(15) << "depth" <<  depth_img << endl;
        cout << setw(15) << "height" <<  height_img << endl;
        cout << setw(15) << "width" <<  width_img << endl;
        cout << setw(15) << "size" <<  size_img << endl;
        cout << setw(15) << "nchan" <<  nchan_img << endl;
        cout << setw(15) << "nsize" <<  nsize_img << endl;


        IplImage* out = cvCreateImage( cvGetSize(frame), IPL_DEPTH_8U, 3 );
        IplImage* gray_out = cvCreateImage( cvGetSize(frame), IPL_DEPTH_8U, 1 );
        IplImage* canny_out = cvCreateImage( cvGetSize(frame), IPL_DEPTH_8U, 1 );
        cvSmooth( frame, out, CV_GAUSSIAN, 11, 11 );
        cvCvtColor(out , gray_out, CV_RGB2GRAY);
        cvCanny( gray_out, canny_out, 10, 10, 3 );

        if( !frame ) break;
        cvShowImage( "Edge", canny_out );
        char c = cvWaitKey(33);
        if( c == 27 ) break;
    }
    cvReleaseCapture( &capture );
    cvDestroyWindow( "Edge" );
    return 0;
}

Solution 2

are you using OpenCV 2.x? Here is code that also works, but before a few things:

  1. Remember that OpenCV works with BGR, so when you convert, use the CV_BGR2GRAY
  2. Be careful with the threshold in Canny, they should be different and with a ratio of 2 or 3( recommended). Might try 100-200...
  3. Try to avoid printing in every loop, that slows down a little bit your code
  4. For filters, try not to use a big window. A size 3 0r 5 at most is usually fine (Depending on your application). A size 11 is probably not required.

Okay, here the code:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;
using namespace cv;

int main(int, char**)
{
    namedWindow( "Edges", CV_WINDOW_NORMAL ); 
    CvCapture* capture = cvCaptureFromCAM(-1);

    cv::Mat frame; cv::Mat out; cv::Mat out2;

    while(1) {
        frame = cvQueryFrame( capture );

        GaussianBlur( frame, out, Size(5, 5), 0, 0 );
        cvtColor( out ,out2, CV_BGR2GRAY ); // produces out2, a one-channel image (CV_8UC1)
       Canny( out2, out2, 100, 200, 3 ); // the result goes to out2 again,but since it is still one channel it is fine

        if( !frame.data ) break;
        imshow( "Edges", out2 );

        char c = cvWaitKey(33);
        if( c == 'c' ) break;
    }
    return 0;
}

By the way, you might consider using cv::Mat. It is far more flexible than IplImage and in fact ( no more Release Image...)

Share:
11,582
mystique
Author by

mystique

engineer, programmer, thinker, dreamer, creator

Updated on June 29, 2022

Comments

  • mystique
    mystique almost 2 years

    i am trying to implement opencv's canny edge detection on live video from webcam. However, I am getting this error:

    OpenCV Error: Unsuported format or combination of formats <> in unknown function, file ........\ocv\opencv\src\cv\cvcanny.cpp, line 66

    I guess this is a format issue. I can convert the 3-channel 8-bit RGB image into a 1-channel grayscale imageframe and then perform edge detection on the result. However, I am unable to implement rgb2grayscale conversion on the image as well; < Incorrect number of channels for this conversion code>

    Below is the code that I implemented In VS2008. Any thoughts on how to resolve this error?

    #pragma once
    
    #include <stdio.h>
    #include <tchar.h>
    #include <iostream>
    #include <conio.h>
    #include <iomanip>
    #include <cv.h>
    #include <cvaux.h>
    #include <cxcore.h>
    #include <highgui.h>
    #include <math.h>
    #include <string.h>
    #include <cxtypes.h>
    
    
    using namespace std;
    using namespace cv;
    
    int main(int, char**)
    {
    
        cvNamedWindow("Edges", CV_WINDOW_AUTOSIZE); 
    CvCapture* capture = cvCaptureFromCAM(0);
    
    IplImage* frame;
        while(1) {
            frame = cvQueryFrame( capture );
    
    
            int depth_img =frame->depth;
            int height_img =frame->height;
            int width_img =frame->width;
            int size_img =frame->imageSize;
            int nchan_img =frame->nChannels;
            int nsize_img =frame->nSize;
    
            cout << setw(15) << "depth" <<  depth_img << endl;
            cout << setw(15) << "height" <<  height_img << endl;
            cout << setw(15) << "width" <<  width_img << endl;
            cout << setw(15) << "size" <<  size_img << endl;
            cout << setw(15) << "nchan" <<  nchan_img << endl;
            cout << setw(15) << "nsize" <<  nsize_img << endl;
    
    
            IplImage* out = cvCreateImage( cvGetSize(frame), IPL_DEPTH_8U, 3 );
            cvSmooth( frame, out, CV_GAUSSIAN, 11, 11 );
            cvCvtColor(out ,out, CV_RGB2GRAY);
            cvCanny( out, out, 10, 10, 3 );
    
            if( !frame ) break;
            cvShowImage( "Edge", out );
            char c = cvWaitKey(33);
            if( c == 27 ) break;
        }
        cvReleaseCapture( &capture );
        cvDestroyWindow( "Edge" );
        return 0;
    }