//学习OPENCV,第2章
#include
#include
#include
#include
#include
#include
//全局变量,用于视频波形滚条控制(帧之间的跳跃);
int g_slider_position = 0; //设置滚条位置
CvCapture* g_capture = NULL; //回调函数对象
//定义回调函数,使其在滚动条被拖动时调用。滚条位置为pos
void onTrackbarSlide(int pos)
{
//设置视频属性,对应获取视频属性为cvGetCaptureProperty
//g_capture:对应视频结构体
//CV_CAP_PROP_POS_FRAME:单位为帧数的位置(只对视频文件有效)
//pos:视频位置value
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
}
IplImage* docanny(IplImage* Image_in,double lowThresh,double highThresh,double aperture);
IplImage* doPyrDown(IplImage* Image_in,int filter = IPL_GAUSSIAN_5x5);
int main(int argc,char** argv)
{
/**显示图像**/
printf("1.简单图像显示\n");
IplImage* img = cvLoadImage("D:\\AI_Proj\\OPENCV\\dog.jpg");//读取图像,自动分配内存
cvNamedWindow("example",CV_WINDOW_AUTOSIZE);
cvShowImage("example",img);
cvWaitKey(0);
cvReleaseImage(&img);
cvDestroyWindow("example");
/**简单AVI视频读取与显示**/
printf("2.简单AVI视频读取与显示\n");
cvNamedWindow("cv_vedio",CV_WINDOW_AUTOSIZE);
//读入的AVI文件,CvCapture结构包括所有AVI文件信息,包括状态信息等。
CvCapture* capture = cvCreateFileCapture("D:\\AI_Proj\\OPENCV\\shipin.avi");
IplImage* frame;
//循环读入AVI文件
while(1)
{
//将下一帧视频载入内存
//cvLoadImage为图像分配内存,需要通过cvReleaseImage()进行内存释放
//cvQueryFrame使用已经在CvCapture中分配好的内存,只需要释放CvCapture指针即可
frame = cvQueryFrame(capture);
if(!frame)
break;
cvShowImage("cv_vedio",frame);
//实际应用中通过从CvCapture结构体中获取实际帧率更好(CV_CAP_PROP_FPS)
//如果期间用户触发按键,c设置为对应按键的ASIC码
char c = cvWaitKey(33);//wait for 33ms
if(c == 27) //对应ESC按键
break;
}
cvWaitKey(0);
cvReleaseCapture(&capture);
cvDestroyWindow("cv_vedio");
/**创建滚动条,通过设置参数确定滚动条所属窗口**/
//通过添加全局变量来表示滚动条位置,并添加一个回调函数更新变量以及设置视频读入位置。
printf("3.视频滚动条\n");
cvNamedWindow("cv_vedio_control",CV_WINDOW_AUTOSIZE);
g_capture = cvCreateFileCapture("D:\\AI_Proj\\OPENCV\\shipin.avi");
//cvGetCaptureProperty从cvCapture中查询数据
//CV_CAP_PROP_FRAME_COUNT:将被下一步解压/获取的帧索引
//以帧数来设置读入位置
int frames = (int)cvGetCaptureProperty(g_capture,CV_CAP_PROP_FRAME_COUNT);
if(frames != 0)
{ //frame为0时不会创建,因为对于有些编码方式,总的帧数获取不到。这时看不到滚动条
//创建滚动条
cvCreateTrackbar("Position", //滚动条名称
"cv_vedio_control",//所属窗口
&g_slider_position,//pos位置以0为起点
frames,//将全局变量绑定到滚动条表示滚动条的最大值
onTrackbarSlide);//回调函数,当滚动条被拖动时被触发
}
IplImage* frame1;
while(1)
{
frame1 = cvQueryFrame(g_capture);//参数为CvCapture指针,将下一帧视频载入内存
//cvLoadImage为图像分配内存,cvQueryFrame使用已经在CvCapture中分配好的内存
//前者需要通过cvReleaseImage()进行内存释放,后者只需要释放CvCapture指针即可
if(!frame1)
break;
cvShowImage("cv_vedio_control",frame1);
char c = cvWaitKey(33);
if(c == 27)
break;
}
cvWaitKey(0);
cvReleaseCapture(&g_capture);
cvDestroyWindow("cv_vedio_control");
/**平滑滤波**/
printf("4.平滑滤波\n");
IplImage* Image = cvLoadImage("D:\\AI_Proj\\OPENCV\\dog.jpg");
cvNamedWindow("Image-in",CV_WINDOW_AUTOSIZE);
cvNamedWindow("Image-out",CV_WINDOW_AUTOSIZE);
cvShowImage("Image-in",Image);
//创建图像,参数:图像大小,像素数据类型,通道数
IplImage* Image_o = cvCreateImage(cvGetSize(Image),IPL_DEPTH_8U,3);
cvSmooth(Image,Image_o,CV_GAUSSIAN,3,3);
cvShowImage("Image-out",Image_o);
cvWaitKey(0);
cvReleaseImage(&Image_o);
cvReleaseImage(&Image);
cvDestroyWindow("Image-in");
cvDestroyWindow("Image-out");
/**图像变换**/
//图像变换前后大小、深度、通道数不同
printf("5.简单图像变换\n");
IplImage* Image_in = cvLoadImage("D:\\AI_Proj\\OPENCV\\stuff.jpg");//640x480
//高度与宽度为源图像的一半
IplImage* Image_out = doPyrDown(Image_in,IPL_GAUSSIAN_5x5);
cvNamedWindow("Image_in",CV_WINDOW_AUTOSIZE);
cvShowImage("Image_in",Image_in);
cvNamedWindow("Image_out",CV_WINDOW_AUTOSIZE);
cvShowImage("Image_out",Image_out);
cvWaitKey(0);
cvReleaseImage(&Image_in);
cvReleaseImage(&Image_out);
cvDestroyWindow("Image_in");
cvDestroyWindow("Image_out");
/**对图像进行2次缩放以及canny检测**/
printf("6.对图像进行2次缩放以及canny检测\n");
IplImage* Image_in1 = cvLoadImage("D:\\AI_Proj\\OPENCV\\stuff.jpg",0);//0-强制转为灰度图;1-彩色图;-1-源通道数
IplImage* image1 = doPyrDown(Image_in1,IPL_GAUSSIAN_5x5);
IplImage* image2 = doPyrDown(image1,IPL_GAUSSIAN_5x5);
IplImage* image3 = docanny(image2,10,100,3);
cvNamedWindow("Image_in");
cvShowImage("Image_in",Image_in1);
cvNamedWindow("image1");
cvShowImage("image1",image1);
cvNamedWindow("image2");
cvShowImage("image2",image2);
cvNamedWindow("image3");
cvShowImage("image3",image3);
cvWaitKey(0);
cvReleaseImage(&Image_in1);
cvDestroyWindow("Image_in");
cvReleaseImage(&image1);
cvDestroyWindow("image1");
cvReleaseImage(&image2);
cvDestroyWindow("image2");
cvReleaseImage(&image3);
cvDestroyWindow("image3");
/**写入视频**/
//(1)读入视频文件、获取视频帧
printf("7.写入视频\n");
CvCapture* capture1 = cvCreateFileCapture("D:\\AI_Proj\\OPENCV\\shipin.avi");
if(!capture1)
return -1;
IplImage* brg_frame = cvQueryFrame(capture1);
//(2)获取视频流的各项属性
double fps = cvGetCaptureProperty(capture1,CV_CAP_PROP_FPS);//获取帧率
CvSize size = cvSize((int)cvGetCaptureProperty(capture1,CV_CAP_PROP_FRAME_WIDTH),
(int)cvGetCaptureProperty(capture1,CV_CAP_PROP_FRAME_HEIGHT));
//(3)创建视频文件写入器结构
//CV_FOURCC为四个字符用来表示压缩帧的codec,motion-jpeg(MJPEG)
CvVideoWriter* writer = cvCreateVideoWriter("D:\\AI_Proj\\OPENCV\\new.avi",CV_FOURCC('M','J','P','G'),fps,size);
//(4)将图像帧转换为对数极坐标格式,并逐帧写入视频文件
IplImage* logpolar_frame = cvCreateImage(size,IPL_DEPTH_8U,3);
while(brg_frame != NULL)
{
//Log-polar转换表示从笛卡尔坐标到极坐标。
//模仿视网膜中央凹视力,对于目标跟踪等可用于快速尺度和旋转变换不变模板匹配。
cvLogPolar(brg_frame,
logpolar_frame,
cvPoint2D32f(brg_frame->width/2,brg_frame->height/2),//创建一个二维坐标下的点(浮点)
40,
CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS);
cvWriteFrame(writer,logpolar_frame);
cvNamedWindow("mainwin",CV_WINDOW_AUTOSIZE);
cvShowImage("mainwin", logpolar_frame);
char c = cvWaitKey(33);
if(c == 27)
break;
}
printf("well done");
cvReleaseVideoWriter(&writer);
cvReleaseImage(&logpolar_frame);
cvReleaseCapture(&capture1);
return 0;
}
//doPyrDown,图像缩放与滤波(高斯金字塔)
IplImage* doPyrDown(IplImage* Image_in,int filter)
{
assert(Image_in->width%2==0 && Image_in->height%2==0);
IplImage* Image_out = cvCreateImage(cvSize(Image_in->width/2,Image_in->height/2),
Image_in->depth,
Image_in->nChannels);
//filter仅支持 CV_GAUSSIAN_5x5
//cvPyrDown使用Gaussian金字塔分解对输入图像向下采样。
//先进行卷积,后通过拒绝偶数的行与列来下采样图像。
cvPyrDown(Image_in,Image_out); //对图像进行缩放
return(Image_out);
}
//docanny
IplImage* docanny(IplImage* Image_in,double lowThresh,double highThresh,double aperture)
{
if(Image_in->nChannels != 1) //通道必须为1
{
printf("it's not a 1-channel image-in\n");
return 0;
}
IplImage* Image_out = cvCreateImage(cvGetSize(Image_in),IPL_DEPTH_8U,1);
//输入图像必须为单通道灰度图。输出边缘图像也为单通道黑白图
//小阈值控制边缘连接
//大阈值控制强边缘的初始分割,才保留,否则删除
//aperture为Sobel算子,默认为3即表示一个3*3的矩阵
cvCanny(Image_in,Image_out,lowThresh,highThresh,aperture);
return Image_out;
}
效果图:
简单图像显示
平滑滤波
通道不变,简单缩放
对灰度图构建图像金字塔,并执行canny边缘检测