半个月前开始学习opencv 觉得计算机视觉真是个大坑啊 没做好准备千万别往里踏 否则像我一样摔得粉身碎骨。
学习的过程中写了一些笔记,主要是根据于仕琪的 学习opencv 上一步步来的 感觉做识别和机器学习挺有意思,与诸君共勉吧 路途漫漫 还得加把劲呐。
//2013.7.12
一.函数声明及参数含义
Mat 图片数据类型的申明
cvNamedWindow("example") --- 创建一个叫做example的窗口
cvCreateImage(CvSize size,int depth,int channels)
size 图像的宽和高
depth 图像的位深度 IPL_DEPTH_8U
channels 每个元素的通道数 通常是1 2 3 4
imread(filename) -- 读入一张图片
cvWaitKey(0); --- 一个等待用户输入的函数,可以用于定格输出画面
IplImage* --- 图片指针,指向图片的数据类型
cvLoadImage(filename,flag) -- flag:1 将读入图像强制转换为三通道彩色图像
0 将读入图像强制转换为单通道灰度图像
-1 读入与写入图像通道数想通
cvShowImage(filename,image) filename是窗口名 image是被显示的图像
cvReleaseImage(&image) 对image变量的一个引用,用于释放image占用的内存资源
cvDestroyWindow("exmaple")-- 销毁窗口
PS:要先释放资源,再销毁窗口 否则容易内存泄露导致系统崩溃
cvShowImage("filename",IplIamge* image) -- 在创建的窗口中显示image指向的图片
二.实例函数用途
1.对图像进行模糊处理
cvSmooth(image1,image2,CV_GAUSSIAN,int,int)
-- 使图像平滑 image1是输入图像 image2是输出图像 cv_gaussian用高斯滤波(一种平滑方法)
2.边缘检测
cvCreateTrackbar(const char* trackbar_name, const char* window_name, int* value, int count, CvTrackbarCallback on_change);
trackbar_name 被创建的trackbar名字。
window_name 窗口名字,这个窗口将为被创建trackbar的父对象。
value 整数指针,它的值将反映滑块的位置。这个变量指定创建时的滑块位置。
count 滑块位置的最大值。最小值一直是0。
on_change 每次滑块位置被改变的时候,被调用函数的指针。这个函数应该被声明为void Foo(int); 如果没有回调函数,这个值可以设为NULL。
//2013.7.15更新
3.轮廓检测
cvGetSize(const CvArr* arr); 得到二位数组的尺寸以结构体 CvSize返回
CvSize是基本的数据类型之一 表示矩阵框的大小
typedef struct CvSize{
int width; //矩形宽
int height;//矩形高
}CvSize
4.运动物体的检测
cvNamedWindow("name",int) --- 创建窗口
cvMoveWindow("name",int,int) --- 移动窗口,使创口排列有序
cvCaptureFromCAM(-1) --- 打开摄像头
//pCapture = cvCaptureFromCAM(-1) 摄像头指针
cvCaptureFromFile(argv[1]) --- 打开视频文件
//pCapture = cvCaptureFromFile(argv[1])
//打开视频文件或者检测运动物体的时候都是通过循环的一帧一帧的处理图像
所以会用到函数cvQueryFrame()---从摄像头或者视频文件中抓取并返回一帧
函数定义
ipIimage* cvQueryFrame(CvCapture* capture);
cvCreateMat(int rows,int cols,int type);
type为矩阵元素类型 CV_<比特数>(S|U|F)C<通道数>
//opencv里的颜色空间转换函数 可以实现RGB,HSV,HSI或者灰度图像的转换
void cvCvtColor(const CvArr* src,CvArr* dst,int code);
src 输入的8-bit,16-bit,32-bit单精度浮点数影像
dst 输出的8-bit,16-bit,32-bit单精度浮点数影像
code 色彩空间转换模式
CV_BGR2GRAY --灰度图 dst需要时单通道图片
CV_BGR2HSV --从RGB到HSV
cvConvert()函数用于图像和矩阵之间的相互转换
void cvConvert(CvMat*,IpIimage)
将IpIimage格式转换为CvMat
因为前者的图像数据是unsigned char类型 精度范围只有0-255
后者却可以存放任意通道数任意格式的数据
//对灰度图像进行阀值操作得到二值图像
void CVThreshold(const CvArr* dst,double threshold,double max_value,int threshold_type);
max_value:使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值。
threshold_type:阈值类型 threshold_type=CV_THRESH_BINARY
//计算两个数组差的绝对值的函数
void cvAbsDiff(const CvArr* src1,CvArr*src2,CvArr* dst);
src1-原数组 src2-第二个原数组 dst-输出数组
dst(i) = abs(src1(i) - src2(i))
//对于区域图像的处理
允许对图像的某一小部分进行操作 使用ROI(region of interest)
使用函数
cvSetImageROI(src,cvRect(x,y,width,height));
cvResetImageROI(src)取消操作
x y width height分别是图片中的ROI区域起始点x值 y值 区域宽度及高度
//矩阵的操作
矩阵创建的一般方法
CvMat *mat = cvCreateMat(int row,int col,int* type);
对于矩阵的读写操作需要用到指针
例如在求矩阵和的时候
for(int row = 0;row < matrix->rows;row++)
{
float s = 0.0;
float* ptr = (float *)(matrix->data.ptr + row * matrix->step);
for(int col = 0;col < matrix->cols;col++)
s += *ptr++;
}
会用到matrix中的step来对每一行进行定位。
//7.16日更新
关于LK稀疏光流算法的讨论
1.这个算法用于计算光流---既用于判断两帧之间的易于跟踪的特征点
适用条件:
第一 亮度恒定,目标的像素在帧间运动时外观保持不变。灰度图的亮度不变。
第二 时间连续且运动变化缓慢。时间变化相对图像中的运动比例要足够小
第三 空间一致
2.cvLine(IplImage*,CvPoint,CvPoint,Cv_RGB(a,b,c),2);
此函数用于在图像中画出易于跟踪点的光流路径,Cv_RGB(a,b,c)函数用于调节所画线段中红绿蓝三通道的比率
a,b,c均为无符号字符取值范围[0,255]
3.void cvCalcOpticalFlowPyrLK(const CvArr* imgA,const CvArr* imgB,CvArr* PyrA,CvArr* PyrB, CvPoint2D32f* featuresA,CvPoint2D32f* featuresB,int count,char* winSize,int level,char* status,
float* track_error,cvTermCriteria criteria,int flags);
前两个参数代表初始图像和最终图像,都是八位单通道图像。
第三四个参数是申请放入两幅输入图像金字塔的缓存 大小至少为 (img.width+8)*img.height/3
featuresA和featuresB分别用于存放需找运动的点和点的新位置
count是featuresA里点的个数
level是图像金字塔的栈的层数
track_error用于删除外观小区域随点运动变化剧烈的点
criteria是迭代的终止条件 CV_TERMCRIT_EPS|CV_TERMCRIT_ITER
//2013.7.19更新
在CK算法中遇到的问题
内存泄露或溢出
编译器报错cv::Exception at memory location
在重写了代码之后发现,这个算法的计算量很大,是递归的算法,所以只能支持灰度图
并且两个图的分辨率必须想同,这对本算法的实用性有很大的限制