实时视频上的OpenCV Canny Edge

时间:2011-09-08 16:53:40

标签: c++ video opencv

我正在尝试在网络摄像头的实时视频上实现opencv的canny边缘检测。但是,我收到了这个错误:

OpenCV错误:未报告的格式或格式组合<>在未知功能,文件........ \ ocv \ opencv \ src \ cv \ cvcanny.cpp,第66行

我想这是一个格式问题。我可以将3通道8位RGB图像转换为1通道灰度图像帧,然后对结果执行边缘检测。但是,我也无法在图像上实现rgb2grayscale转换; <此转换代码的通道数不正确>

以下是我在VS2008中实现的代码。有关如何解决此错误的任何想法?

#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;
}

3 个答案:

答案 0 :(得分:3)

问题是你每次传递一个3通道图像

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 );

这对我有用:

#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;
}

答案 1 :(得分:2)

你正在使用OpenCV 2.x吗?这里的代码也有效,但在以下几点之前:

  1. 请记住,OpenCV与BGR一起使用,因此在转换时,请使用CV_BGR2GRAY
  2. 小心Canny中的阈值,它们应该是不同的,比例为2或3(推荐)。可能会尝试100-200 ......
  3. 尽量避免在每个循环中打印,这会使代码慢一点
  4. 对于过滤器,尽量不要使用大窗口。最大尺寸3 0r 5通常很好(取决于您的应用)。可能不需要11号。
  5. 好的,这里是代码:

    #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;
    }
    

    顺便说一下,你可以考虑使用cv :: Mat。它比IplImage更灵活,实际上(不再有Release Image ......)

答案 2 :(得分:0)

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;



int main()
{
    Mat img;
    VideoCapture cap(0);

    while (true)
    {
        cap >> img;

        Mat edges;
        cvtColor(img, edges, CV_BGR2GRAY);

        Canny(edges, edges, 30, 60);

        imshow("window label", edges);
        waitKey(1);
    }

    return 0;
}

这是我使用canny功能拍摄的方式。