【OpenCV】3rd-Canny边缘检测、打开摄像头

一、复杂的变换

1、Canny边缘检测将输出写入一个单通道(灰度级)图像(p29)

#include "cv.h"
#include "highgui.h"

IplImage* doCanny(
    IplImage* in,
    double    lowThresh,
    double    highThresh,
    double    aperture)
{
    if (in->nChannels != 1)
        return(0); // Canny only handles gray scale images
    IplImage* out = cvCreateImage( 
        cvGetSize( in ),
        in->depth, //IPL_DEPTH_8U,    
        1);
    cvCanny( in, out, lowThresh, highThresh, aperture );
    return( out );
};

int main( int argc, char** argv )
{
  IplImage* img_rgb = cvLoadImage( argv[1] );
  IplImage* img_gry = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
  cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
  cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
  cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
  cvShowImage("Example Gray", img_gry );
  IplImage* img_cny = doCanny( img_gry, 10, 100, 3 );
  cvShowImage("Example Canny", img_cny );
  cvWaitKey(0);
  cvReleaseImage( &img_rgb);
  cvReleaseImage( &img_gry);
  cvReleaseImage( &img_cny);
  cvDestroyWindow("Example Gray");
  cvDestroyWindow("Example Canny");
}

前面的实现使更加容易进行一些连续的变换
IplImage* doCanny(
IplImage* in,
double lowThresh,
double highThresh,
double aperture)
{
if (in->nChannels != 1)
return(0); // Canny only handles gray scale images
IplImage* out = cvCreateImage(
cvGetSize( in ),
in->depth, //IPL_DEPTH_8U,
1);
cvCanny( in, out, lowThresh, highThresh, aperture );
return( out );
};
··
如下例,可以简单地操作组合。


2、进行两次缩放处理与边缘检测(p29)

IplImage* img_pyr = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
IplImage* img_pyr2 = doPyrDown( img_pyr, IPL_GAUSSIAN_5x5 );
IplImage* img_cny = doCanny( img_pyr2, 10, 100, 3 );
...
cvReleaseImage( &img_pyr);
cvReleaseImage( &img_pyr2);
cvReleaseImage( &img_cny);

以下是完整程序:

#include "cv.h"
#include "highgui.h"

IplImage* doCanny(
    IplImage* in,
    double    lowThresh,
    double    highThresh,
    double    aperture)
{
    IplImage* out = cvCreateImage( 
        cvGetSize( in ),
        in->depth, //IPL_DEPTH_8U,    
        1);
    cvCanny( in, out, lowThresh, highThresh, aperture );
    return( out );
};

IplImage* doPyrDown(
  IplImage* in,
  int       filter = IPL_GAUSSIAN_5x5)
{

    // Best to make sure input image is divisible by two.
    //
    assert( in->width%2 == 0 && in->height%2 == 0 );

    IplImage* out = cvCreateImage( 
        cvSize( in->width/2, in->height/2 ),
        in->depth,
        in->nChannels
    );
    cvPyrDown( in, out );
    return( out );
};

int main( int argc, char** argv )
{
  IplImage* img_rgb  = cvLoadImage( argv[1] );
  IplImage* img_gry  = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
  cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
  IplImage* img_pyr  = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
  IplImage* img_pyr2 = doPyrDown( img_pyr, IPL_GAUSSIAN_5x5 );
  IplImage* img_cny  = doCanny( img_pyr2, 10, 100, 3 );

  cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
  cvNamedWindow("Example Pyr", CV_WINDOW_AUTOSIZE );
  cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
  cvShowImage("Example Gray", img_gry );
  cvShowImage("Example Pyr", img_pyr2 );
  cvShowImage("Example Canny", img_cny );
  cvWaitKey(0);
  cvReleaseImage( &img_rgb);
  cvReleaseImage( &img_gry);
  cvReleaseImage( &img_pyr);
  cvReleaseImage( &img_pyr2);
  cvReleaseImage( &img_cny);
  cvDestroyWindow("Example Gray");
  cvDestroyWindow("Example Pyr");
  cvDestroyWindow("Example Canny");
}

3、自清理模式(p30)

通过每个独立阶段释放内存来简化上例中图像处理流程:
out = doPyrDown( out );
out = doPyrDown( out );
out = doCanny( out, 10, 100, 3 );
...
cvReleaseImage( &out);

以下是完整程序:

#include "cv.h"
#include "highgui.h"

IplImage* doCanny(
    IplImage* in,
    double    lowThresh,
    double    highThresh,
    double    aperture)
{
    IplImage* out = cvCreateImage( 
        cvGetSize( in ),
        in->depth, //IPL_DEPTH_8U,    
        1);
    cvCanny( in, out, lowThresh, highThresh, aperture );
    return( out );
};

IplImage* doPyrDown(
  IplImage* in,
  int       filter = IPL_GAUSSIAN_5x5)
{

    // Best to make sure input image is divisible by two.
    //
    assert( in->width%2 == 0 && in->height%2 == 0 );

    IplImage* out = cvCreateImage( 
        cvSize( in->width/2, in->height/2 ),
        in->depth,
        in->nChannels
    );
    cvPyrDown( in, out );
    return( out );
};

int main( int argc, char** argv )
{
  cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
  cvNamedWindow("Example Pyr", CV_WINDOW_AUTOSIZE );
  cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
  IplImage* img_rgb = cvLoadImage( argv[1] );
  IplImage* out;

  out = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
  cvCvtColor(img_rgb, out ,CV_BGR2GRAY);
  cvShowImage("Example Gray", out );
  out = doPyrDown( out );
  out = doPyrDown( out );
  cvShowImage("Example Pyr", out );
  out = doCanny( out, 10, 100, 3 );
  cvShowImage("Example Canny", out );

  cvWaitKey(0);
  cvReleaseImage( &out);
  cvDestroyWindow("Example Gray");
  cvDestroyWindow("Example Pyr");
  cvDestroyWindow("Example Canny");
}

二、打开摄像头

【问题】:用opencv3.0运行打开摄像头的程序时,只显示灰色。并且运行几次后要求选择摄像头,随后闪退。
【原因】:
这里写图片描述
以下是网络版,2.4.9,3.0运行成功:

#include 
#include 
#include 
using namespace cv;//命名空间
int main()
{
    VideoCapture capture(0);//创建VideoCapture对象
    if (!capture.isOpened())//判断是否打开摄像头,打开isOpened返回ture
        return 1;
    bool stop(false);//定义一个用来停止循环的变量
    Mat frame;//用来存放读取的视频序列,承载每一帧的图像 ,Mat类是用于保存图像以及其他矩阵数据的数据结构

    namedWindow("Camera");//创建一个窗口,显示每一帧的窗口
    while (!stop)
    {
        if (!capture.read(frame))//如果没有读取到就中断
        {
            break;
        }
        imshow("Camera", frame);//正常显示,把获取的视频填充到窗口中

        char c = cvWaitKey(33);
        if (c == 32)break; //使用空格键来停止ASCII 为32
    }
    capture.release();//释放
}

以下是书p30的版本,出现闪退情况,待解决:

#include "cv.h"
#include "highgui.h"

int main(int argc, char** argv) {
    cvNamedWindow("Example2_9", CV_WINDOW_AUTOSIZE);
    CvCapture* capture;
    if (argc == 1) {
        capture = cvCreateCameraCapture(0);
    }
    else {
        capture = cvCreateFileCapture(argv[1]);
    }
    assert(capture != NULL);

    IplImage* frame;
    while (1) {
        frame = cvQueryFrame(capture);
        if (!frame) break;
        cvShowImage("Example2_9", frame);
        char c = cvWaitKey(10);
        if (c == 27) break;
    }
    cvReleaseCapture(&capture);
    cvDestroyWindow("Example2_9");
}

网上的测试程序,3.0无法打开,2.4.9可以:

#include 
#include
using namespace std;
int main(int argc, char** argv)
{
    //声明IplImage指针
    IplImage* pFrame = NULL;

    //获取摄像头
    CvCapture* pCapture = cvCaptureFromCAM(0);// cvCreateCameraCapture(0);
    cvWaitKey(200);
    //创建窗口
    cvNamedWindow("Video", 1);

    //显示视屏
    while (1)
    {
        pFrame = cvQueryFrame(pCapture);
        if (!pFrame)break;
        cvShowImage("Video", pFrame);
        char c = cvWaitKey(33);
        if (c == 27)break;
    }
    cvReleaseCapture(&pCapture);
    cvDestroyWindow("Video");

    return 0;

}

【问题】:不能显示图像。
【原因】:命令参数里有别的变量忘记删了。


网上的测试程序,显示灰色:

//#include "stdafx.h"
#include 
#include 
#include 
int main(int argc, char** argv)
{
    //声明IplImage 指针
    IplImage* pFrame = NULL;
    //获取摄像头
    CvCapture* pCapture = cvCreateCameraCapture(-1);
    //创建窗口
    cvNamedWindow("video", 1);
    //显示视屏
    while (1)
    {
        pFrame = cvQueryFrame(pCapture);
        if (!pFrame)break;
        cvShowImage("video", pFrame);
        char c = cvWaitKey(33);
        if (c == 27)break;
    }
    cvReleaseCapture(&pCapture);
    cvDestroyWindow("video");
}

【问题】:#include "stdafx.h"没有这个文件。若注释掉则出现选择摄像机的界面且闪退。
【解决】:注释掉#include "stdafx.h"
CvCapture* pCapture = cvCreateCameraCapture(-1);不可用
【原因】:

所谓头文件预编译,就是把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、Afxwin.H)预先编译,以后该工程编译时,不再编译这部分头文件,仅仅使用预编译的结果。这样可以加快编译速度,节省时间。
预编译头文件通过编译stdafx.cpp生成,以工程名命名,由于预编译的头文件的后缀是“pch”,所以编译结果文件是projectname.pch。
编译器通过一个头文件stdafx.h来使用预编译头文件。stdafx.h这个头文件名是可以在project的编译设置里指定的。编译器认为,所有在指令#include “stdafx.h”前的代码都是预编译的,它跳过#include “stdafx. h”指令,使用projectname.pch编译这条指令之后的所有代码。
因此,所有的MFC实现文件第一条语句都是:#include “stdafx.h”。


小结:摄像头打不开,有版本问题,命令参数问题,(可能是stdafx.h问题)。

ps:对于闪退问题,从网上查到的解决方法是:在return语句前面加上system(“pause”);,另外加上头文件include

你可能感兴趣的:(OpenCV)