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

opencv简单视频与图像操作

2016-02-20 23:26 483 查看
//学习OPENCV,第2章
#include<cv.h>
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <cxcore.h>
#include<assert.h>

//全局变量,用于视频波形滚条控制(帧之间的跳跃);
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边缘检测

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opencv