0%

Opencv学习2

前言

Opencv学习-学习笔记2

HSV和RGB的内容

两种格式比较重要,当然还有灰度图GRAY,这里就不做什么解释了。

两者的意思

在进行图像图像处理的时候需要对图像格式进行转换。
将RGB格式的图像转换成HSV格式。
  RGB:三原色光模式(RGB color model),又称RGB颜色模型或红绿蓝颜色模型,是一种加色模型,将红(Red)、绿(Green)、蓝(Blue)三原色的色光以不同的比例相加,以产生多种多样的色光。(且三原色的红绿蓝不可能用其他单色光合成)

  • void cvCvtColor(const CvArr* src, CvArr* dst, int code): 按code指定的模式将src指向的帧转换后写入dst指向的地址。

  • void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, SparseMat& hist, int dims, const int* histSize, const float** ranges, bool uniform, bool accumulate): 为image指向的帧计算直方图,保存在 hist 中。

  • void normalize(const SparseMat& src, SparseMat& dst, double alpha, int normType): 按指定模式将src正常化并写入dst中。

  • double compareHist(const SparseMat& H1, const SparseMat& H2, int method):按method指定的方式比较两个直方图的相似程度。

  • int cvWriteFrame(CvVideoWriter* writer, const IplImage* image): 向视频写入流写入一帧。成功返回 1,否则返回 0。

直方图处理的样例代码

1
2
3
4
5
6
7
8
9
// set background
if (backGroundFlag){
//把frame(当前帧)的内容从BGR格式转换到HSV格式放在HSV中
cvtColor(frame, HSV, CV_BGR2HSV);
//绘制直方图,把HSV的内容
calcHist(&HSV, 1, channels, Mat(), base, 2, histSize, ranges, true, false);
normalize(base, base, 0, 1, NORM_MINMAX, -1, Mat());
backGroundFlag = false;
}

重要基本数据结构

CvPoint

使用(CvPoint*)cvGetSeqElem(lines,i)的到对应的指针.
4检测直线.cpp中的画线方法

1
2
3
4
5
6
7
8
9
for( i = 0; i < lines->total; i++ )
{
CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
cvLine( color_dst, line[0], line[1], CV_RGB(255,0,0), 3, CV_AA, 0 );
//color_dst图像类型,line[0],line[1]线段的两个端点CvPoint类型,
//CV_RGB(255,0,0)线段的颜色,彩图有效.3(thickness)线的粗细程度
//line_type线段类型,CV_AA为线段,8为(8邻接)连接线,4同理.
//0坐标点的小数点位数
}

cvSet2D()&&cvSetReal2D()

对某个坐标点进行颜色的设置,在学习调试的过程中可以非常方便地通过这个方法来查看点的位置.
cvSet2D()是对多通道的彩色图进行设置,cvSetReal2D()是对单通道图设置

使用样例:

1
2
cvSetReal2D(contoursImage, pt->y, pt->x, 255.0);
cvSet2D(imgColor, pt->y, pt->x, cvScalar(0, 255, 0, 0));

通过三个点的坐标计算角度

已知A(x1,y1),B(x2,y2),C(x3,y3),计算∠BAC.

1
2
3
4
向量AB=(x2-x1,y2-y1),向量AC=(x3-x1,y3-y1)
AB*AC=|AB||AC|cos∠BAC
=(x2-x1)(x3-x1)+(y2-y1)(y3-y1)
于是,cos∠BAC=(AB*AC)/[|AB|*|AC|]

计算得到的是余弦值,然后通过公式进行换算:
角度=180/π*acos(∠BAC)
第一阶段完成.cpp中使用的转换余弦值的公式代码为:

1
2
double ang=angle(temp[0],&up,&mid); //mid为要求角度的点
ang=180/PI*acos(ang); //进行余弦值转化角度值

cvContourArea 计算轮廓面积

就是求的轮廓所占的面积.看这个就懂了.—>解释

函数定义:
double cvContourArea( const CvArr* contour, CvSlice slice=CV_WHOLE_SEQ );

  • contour:轮廓(顶点的序列或数组)。
  • slice:感兴趣区轮廓部分的起点和终点,默认计算整个轮廓的面积。

使用方法:

1
2
if(fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000)
//那么执行...

cvArcLength 计算轮廓周长

函数定义:
double cvArcLength( const void* curve, CvSlice slice=CV_WHOLE_SEQ, int is_closed=-1 );

  • curve
    曲线点集序列或数组
  • slice
    曲线的起始点,缺省是计算整个曲线的长度
  • is_closed
    表示曲线是否闭合,有三种情况:
    • is_closed=0 - 假设曲线不闭合
    • is_closed>0 - 假设曲线闭合
    • is_closed<0 - 若曲线是序列,检查 ((CvSeq*)curve)->flags 中的标识 CV_SEQ_FLAG_CLOSED 来确定曲线是否闭合。否则 (曲线由点集的数组 (CvMat*) 表示) 假设曲线不闭合。

cvStartReadSeq函数

函数 cvStartReadSeq 初始化读取部分的状态。
函数定义
void cvStartReadSeq( const CvSeq* seq, CvSeqReader* reader, int reverse=0 )
函数参数

  • seq 序列
  • reader 读取部分的状态; 由该函数初始化
  • reverse 决定遍历序列的方向。如果 reverse 为0,则读取顺序被定位从序列头部元素开始,否则从尾部开始读取

顺序读取可通过调用宏 CV_READ_SEQ_ELEM( read_elem, reader ),逆序读取可通过调用宏CV_REV_READ_SEQ_ELEM( read_elem, reader )。这两个宏都将序列元素读进read_elem中, 并将指针移到下一个元素。下面代码显示了如何去使用reader 和 writer.


ApproxPoly函数

用指定精度逼近多边形曲线
函数定义
CvSeq* cvApproxPoly( const void* src_seq, int header_size, CvMemStorage* storage,int method, double parameter, int parameter2=0 );
函数参数

  • src_seq 点集数组序列
  • header_size 逼近曲线的头尺寸
  • storage 逼近轮廓的容器。如果为 NULL, 则使用输入的序列
  • method 逼近方法。目前仅支持 CV_POLY_APPROX_DP, 对应 Douglas-Peucker 算法.
  • parameter 方法相关参数。对 CV_POLY_APPROX_DP它是指定的逼近精度
  • parameter2 如果 src_seq 是序列,它表示要么逼近单个序列,要么在 src_seq 的同一个或低级层次上逼近所有序列 (参考 cvFindContours 中对轮廓继承结构的描述). 如果 src_seq 是点集的数组 (CvMat*) , 参数指定曲线是闭合 (parameter2!=0) 还是非闭合 (parameter2=0).

函数cvApproxPoly逼近一个或多个曲线,并返回逼近结果。对多个曲线的逼近,生成的树将与输入的具有同样的结构。(1:1 的对应关系).
使用实例
第一阶段完成.cpp中检测矩形轮廓的时候

1
2
3
//在
result = cvApproxPoly( contours, sizeof(CvContour), mem_storage,
CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );

cvFitEllipse2函数

二维点集的椭圆拟合
函数定义
CvBox2D cvFitEllipse2( const CvArr* points );
函数参数

  • points 点集的序列或数组

函数 cvFitEllipse 对给定的一组二维点集作椭圆的最佳拟合(最小二乘意义上的)。返回的结构与 cvEllipse 中的意义类似,除了 size表示椭圆轴的整个长度,而不是一半长度。


cvBoundingRect函数

计算点集的最外面(up-right)矩形边界
函数定义
CvRect cvBoundingRect( CvArr* points, int update=0 );
函数参数

  • points ,二维点集,点的序列或向量 (CvMat)
  • update ,更新标识。下面是轮廓类型和标识的一些可能组合:
    • update=0, contour ~ CvContour*: 不计算矩形边界,但直接由轮廓头的 rect 域得到。
    • update=1, contour ~ CvContour*: 计算矩形边界,而且将结果写入到轮廓头的 rect 域中 header.
    • update=0, contour ~ CvSeq* or CvMat*: 计算并返回边界矩形
    • update=1, contour ~ CvSeq* or CvMat*: 产生运行错误 (runtime error is raised)

函数 cvBoundingRect 返回二维点集的最外面 (up-right)矩形边界


cvMinAreaRect2函数

寻找最小面积的包围矩形
函数定义
CvBox2D cvMinAreaRect2( const CvArr* points, CvMemStorage* storage=NULL );
函数参数

  • points ,点序列或点集数组
  • storage ,可选的临时存储仓

函数 cvMinAreaRect2 通过建立凸外形并且旋转外形以寻找给定 2D 点集的最小面积的包围矩形。其中返回的2D盒子定义如下: (CvBox2D可参考–>说明

1
2
3
4
5
6
7
typedef struct CvBox2D 
{
CvPoint2D32f center; /* 盒子的中心 */
CvSize2D32f size; /* 盒子的长和宽 */
float angle; /* 水平轴与第一个边的夹角,用弧度表示*/

}CvBox2D;

cvMinEnclosingCircle函数

寻找最小包围的圆
函数定义
int cvMinEnclosingCircle(const CvArr * points,CvPoint2D32f * center,float * radius )
函数参数

  • points ,输入的轮廓序列
  • center ,返回的中心点坐标
  • radius ,放回的半径

FitLine函数

2D 或 3D 点集的直线拟合
函数定义
void cvFitLine( const CvArr* points, int dist_type,double param,double reps, double aeps, float* line );
函数参数

  • points ,2D 或 3D 点集,32-比特整数或浮点数坐标
  • dist_type ,拟合的距离类型 (见讨论).
  • param ,对某些距离的数字参数,如果是 0, 则选择某些最优值
  • reps, aeps ,半径 (坐标原点到直线的距离) 和角度的精度,一般设为0.01。
  • line ,输出的直线参数。2D 拟合情况下,它是包含 4 个浮点数的数组 (vx, vy, x0, y0),其中 (vx, vy) 是线的单位向量而 (x0, y0) 是线上的某个点. 对 3D 拟合,它是包含 6 个浮点数的数组 (vx, vy, vz, x0, y0, z0), 其中 (vx, vy, vz) 是线的单位向量,而 (x0, y0, z0)是线上某点。

函数 cvFitLine 通过求 sumiρ(ri) 的最小值方法,用 2D 或 3D 点集拟合直线,其中 ri是第 i 个点到直线的距离, ρ(r) 是下面的距离函数之一

听说好看的人都关注了我的公众号《泫言》