您的位置:首页 > 运维架构

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

2016-11-17 22:23 357 查看

一、复杂的变换

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 <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\opencv.hpp>
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 <opencv2\opencv.hpp>
#include<stdio.h>
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 <cv.h>
#include <cxcore.h>
#include <highgui.h>
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