opencv二值化函数cvThreshold
OpenCV 2009-03-26 16:00:07 阅读4570 评论5   字号:大中小 订阅
对图像二值化函数cvThreshold的理解
Threshold
对数组元素进行固定阈值操作
void cvThreshold( const CvArr* src, CvArr* dst, double threshold, double max_value, int threshold_type );
src
原始数组 (单通道 , 8-bit of 32-bit 浮点数).
dst
输出数组,必须与 src 的类型一致,或者为 8-bit.
threshold
阈值
max_value
使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值.
threshold_type
阈值类型 (见讨论)
函数 cvThreshold 对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像。(cvCmpS 也可以达到此目的) 或者是去掉噪声,例如过滤很小或很大象素值的图像点。本函数支持的对图像取阈值的方法由 threshold_type 确定:
threshold_type=CV_THRESH_BINARY:
dst(x,y) = max_value, if src(x,y)>threshold 0, otherwise.
threshold_type=CV_THRESH_BINARY_INV:
dst(x,y) = 0, if src(x,y)>threshold; dst(x,y) = max_value, otherwise.
threshold_type=CV_THRESH_TRUNC:
dst(x,y) = threshold, if src(x,y)>threshold;   dst(x,y) = src(x,y), otherwise.
threshold_type=CV_THRESH_TOZERO:
dst(x,y) = src(x,y), if (x,y)>threshold ;  dst(x,y) = 0, otherwise.
threshold_type=CV_THRESH_TOZERO_INV:
dst(x,y) = 0, if src(x,y)>threshold ;  dst(x,y) = src(x,y), otherwise.
左面是图形化的阈值描述:
 
 
 
OpenCV中矩阵数据的访问(一)(Learning OpenCV第三章2)
keystonexu » 2008-11-26 20:28
在OpenCV中有三种方式访问矩阵中的数据元素:容易的方式,困难的方式,以及正确的方式。以下先讲容易的方式和困难的方式。

容易的方式

最容易的方式是使用宏CV_MAT_ELEM( matrix, elemtype, row, col ),输入参数是矩阵的指针,矩阵元素类型,行,列,返回值是相应行,列的矩阵元素,例如:
CvMat* mat = cvCreateMat(5,5,CV_32FC1);
float element = CV_MAT_ELEM(*mat,float,3,2);

以下是一个例子:

#pragma comment( lib, "cxcore.lib" )
#include "cv.h"
#include <stdio.h>
void main()
{
CvMat* mat = cvCreateMat(3,3,CV_32FC1);
cvZero(mat);//将矩阵置0
//为矩阵元素赋值
CV_MAT_ELEM( *mat, float, 0, 0 ) = 1.f;
CV_MAT_ELEM( *mat, float, 0, 1 ) = 2.f;
CV_MAT_ELEM( *mat, float, 0, 2 ) = 3.f;
CV_MAT_ELEM( *mat, float, 1, 0 ) = 4.f;
CV_MAT_ELEM( *mat, float, 1, 1 ) = 5.f;
CV_MAT_ELEM( *mat, float, 1, 2 ) = 6.f;
CV_MAT_ELEM( *mat, float, 2, 0 ) = 7.f;
CV_MAT_ELEM( *mat, float, 2, 1 ) = 8.f;
CV_MAT_ELEM( *mat, float, 2, 2 ) = 9.f;
//获得矩阵元素的值
float element = CV_MAT_ELEM(*mat,float,2,2);
printf("%f\n",element);
}




CV_MAT_ELEM宏实际上会调用CV_MAT_ELEM_PTR(matrix,row,col)宏来完成任务。CV_MAT_ELEM_PTR()宏的参数是矩阵的指针,行,列。
CV_MAT_ELEM()宏和CV_MAT_ELEM_PTR()宏的区别是,在调用CV_MAT_ELEM时,指向矩阵元素的指针的数据类型已经依据输入参数中的元素类型而
做了强制转换。,以下是使用CV_MAT_ELEM_PTR()来设置元素的值:


#pragma comment( lib, "cxcore.lib" )
#include "cv.h"
#include <stdio.h>
void main()
{
CvMat* mat = cvCreateMat(3,3,CV_32FC1);
cvZero(mat);//将矩阵置0
float element_0_2 = 7.7f;
*((float*)CV_MAT_ELEM_PTR( *mat, 0, 2 ) ) = element_0_2;

//获得矩阵元素的值
float element = CV_MAT_ELEM(*mat,float,0,2);
printf("%f\n",element);
}

以上使用矩阵中元素的方式很方便,但不幸的是,该宏在每次调用时,都会重新计算指针的
位置。这意味着,先查矩阵数据区中第0个元素的位置,然后,根据参数中的行和列,计算所需要的元素的地址偏移量,然后将地址偏移量与第0个元素的地址相加,获得所需要的元素的地址。
所以,以上的方式虽然很容易使用,但是却不是获得矩阵元素的最好方式。特别是当你要顺序遍历整个矩阵中所有元素时,这种每次对地址的重复计算就更加显得不合理。

困难的方式

以上两个宏只适合获得一维或二维的矩阵(数组)元素,OpenCV提供了处理多维矩阵(数组)的方式。实际上你可以不受限制地使用N维。
当访问这样一种N维矩阵中元素时,你需要使用一个系列的函数,叫做cvPtr*D,*代表1,2,,例如,cvPtr1D(),cvPtr2D(),cvPtr3D(),以及cvPtrND().以下为此系列函数的定义:

cvPtr*D函数用于返回指向某数组元素的指针

uchar* cvPtr1D( const CvArr* arr, int idx0, int* type=NULL );
uchar* cvPtr2D( const CvArr* arr, int idx0, int idx1, int* type=NULL );
uchar* cvPtr3D( const CvArr* arr, int idx0, int idx1, int idx2, int* type=NULL );
uchar* cvPtrND( const CvArr* arr, int* idx, int* type=NULL, int create_node=1, unsigned* precalc_hashval=NULL );

arr
输入数组(矩阵).
idx0
元素下标的第一个以0为基准的成员
idx1
元素下标的第二个以0为基准的成员
idx2
元素下标的第三个以0为基准的成员
idx
数组元素下标
type
可选的,表示输出参数的数据类型
create_node
可选的,为稀疏矩阵输入的参数。如果这个参数非零就意味着被需要的元素如果不存在就会被创建。
precalc_hashval
可选的,为稀疏矩阵设置的输入参数。如果这个指针非NULL,函数不会重新计算节点的HASH值,而是从指定位置获取。这种方法有利于提高智能组合数据的操作
函数cvPtr*D 返回指向特殊数组元素的指针。数组维数应该与传递给函数的下标数相匹配,它可以被用于顺序存取的1D,2D或nD密集数组
函数也可以用于稀疏数组,并且如果被需要的节点不存在函数可以创建这个节点并设置为0
就像其它获取数组元素的函数 (cvGet[Real]*D, cvSet[Real]*D)如果元素的下标超出了范围就会产生错误



很明显,如果是一维数组(矩阵),那就可以使用cvPtr1D,用参数idx0来指向要获得的第idx0个元素,返回值为指向该元素的指针,如果是二维数组(矩阵),就可以使用cvPtr2D,用idx0,idx1来指向相应的元素。
如果是N维数组,则int* idx参数指向对N维数组中某元素定位用的下标序列。
#pragma comment( lib, "cxcore.lib" )
#include "cv.h"
#include <stdio.h>
void main()
{
CvMat* mat = cvCreateMat(3,3,CV_32FC1);
cvZero(mat);//将矩阵置0
//为矩阵元素赋值
CV_MAT_ELEM( *mat, float, 0, 0 ) = 1.f;
CV_MAT_ELEM( *mat, float, 0, 1 ) = 2.f;
CV_MAT_ELEM( *mat, float, 0, 2 ) = 3.f;
CV_MAT_ELEM( *mat, float, 1, 0 ) = 4.f;
CV_MAT_ELEM( *mat, float, 1, 1 ) = 5.f;
CV_MAT_ELEM( *mat, float, 1, 2 ) = 6.f;
CV_MAT_ELEM( *mat, float, 2, 0 ) = 7.f;
CV_MAT_ELEM( *mat, float, 2, 1 ) = 8.f;
CV_MAT_ELEM( *mat, float, 2, 2 ) = 9.f;
//获得矩阵元素(0,2)的值
float *p = (float*)cvPtr2D(mat, 0, 2);
printf("%f\n",*p);
}


我们使用cvPtr*D()函数的一个理由是,通过此函数,我们可以用指针指向矩阵中的某元素,并使用指针运算符,来设置该元素的值,或者,用指针运算来移动指针,指向从起始位置开
始的矩阵中的其他元素。例如,我们可以用以下方式遍历矩阵中的元素:
#pragma comment( lib, "cxcore.lib" )
#include "cv.h"
#include <stdio.h>
void main()
{
CvMat* mat = cvCreateMat(3,3,CV_32FC1);
cvZero(mat);//将矩阵置0

//获得矩阵元素(0,0)的指针
float *p = (float*)cvPtr2D(mat, 0, 0);
//为矩阵赋值
for(int i = 0; i < 9; i++)
{
*p = (float)i;
p++;
}

//打印矩阵的值
p = (float*)cvPtr2D(mat, 0, 0);

for(i = 0; i < 9; i++)
{
printf("%f\t",*p);
p++;
if((i+1) % 3 == 0)
printf("\n");
}

}


但 是要注意,以上为矩阵中元素的通道数为1时,可以用p++来访问下一个矩阵中元素,但是如果通道数不为1,例如一个三通道的二维矩阵,矩阵中每个元素的值 为RGB值,则矩阵中数据按以下方式存储:,因此,使用指针指向下一个元素时,就需要加上相应的通道数。

举例如下:



#pragma comment( lib, "cxcore.lib" )
#include "cv.h"
#include <stdio.h>
void main()
{
/
/矩阵元素为三通道浮点数
CvMat* mat = cvCreateMat(3,3,CV_32FC3);
cvZero(mat);//将矩阵置0
//为矩阵元素赋值

//获得矩阵元素(0,0)的指针
float *p = (float*)cvPtr2D(mat, 0, 0);
//为矩阵赋值
for(int i = 0; i < 9; i++)
{
//为每个通道赋值
*p = (float)i*10;
p++;
*p = (float)i*10+1;
p++;
*p = (float)i*10+2;
p++;
}

//打印矩阵的值
p = (float*)cvPtr2D(mat, 0, 0);

for(i = 0; i < 9; i++)
{
printf("%2.1f,%2.1f,%2.1f\t",*p,*(p+1),*(p+2));
p+=3;
if((i+1) % 3 == 0)
printf("\n");
}
}


如果你不想使用指向数据的指针,而只是想获得矩阵中的数据,你还可以使用cvGet*D函数系列。如下所示,该函数系列以返回值类型划分有两种,一种返回double类型数据,另一种返回CvScalar类型数据。

Get*D

返回特殊的数组元素

CvScalar cvGet1D( const CvArr* arr, int idx0 );
CvScalar cvGet2D( const CvArr* arr, int idx0, int idx1 );
CvScalar cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 );
CvScalar cvGetND( const CvArr* arr, int* idx );

arr
输入数组.
idx0
元素下标第一个以0为基准的成员
idx1
元素下标第二个以0为基准的成员
idx2
元素下标第三个以0为基准的成员
idx
元素下标数组

函数cvGet*D 返回指定的数组元素。对于稀疏数组如果需要的节点不存在函数返回0 (不会创建新的节点)



GetReal*D

返回单通道数组的指定元素

double cvGetReal1D( const CvArr* arr, int idx0 );
double cvGetReal2D( const CvArr* arr, int idx0, int idx1 );
double cvGetReal3D( const CvArr* arr, int idx0, int idx1, int idx2 );
double cvGetRealND( const CvArr* arr, int* idx );

arr
输入数组,必须是单通道.
idx0
元素下标的第一个成员,以0为基准
idx1
元素下标的第二个成员,以0为基准
idx2
元素下标的第三个成员,以0为基准
idx
元素下标数组

函 数cvGetReal*D 返回单通道数组的指定元素,如果数组是多通道的,就会产生运行时错误,而 cvGet*D 函数可以安全的被用于单通道和多通道数组,注意,该方法返回值类型是double类型的,这意味着,矩阵中如果保存的是int类型数据,不能用此系列方 法。


#pragma comment(lib,"cxcore.lib")
#include"cv.h"
#include<stdio.h>
void main()
{
/
/矩阵元素为1通道浮点型数据
CvMat*mat=cvCreateMat(3,3,CV_32FC1 );
cvZero(mat);//将矩阵置0
//为矩阵元素赋值

//获得矩阵元素(0,0)的指针
float *p=(float*)cvPtr2D(mat,0,0);
//为矩阵赋值
for(int i=0;i<9;i++)
{
//为每个通道赋值
*p=(float)i*10;
p++;
}

for(i=0;i<3;i++)
for(int j=0;j<3;j++)
{
printf("%lf\t",cvGetReal2D(mat,i,j));

}

}

另外,我们还有类似于cvGet*D()的方法为矩阵元素赋值:cvSetReal*D()和cvSet*D()。

Set*D

修改指定的数组

void cvSet1D( CvArr* arr, int idx0, CvScalar value );
void cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value );
void cvSet3D( CvArr* arr, int idx0, int idx1, int idx2, CvScalar value );
void cvSetND( CvArr* arr, int* idx, CvScalar value );

arr
输入数组
idx0
元素下标的第一个成员,以0为基点
idx1
元素下标的第二个成员,以0为基点
idx2
元素下标的第三个成员,以0为基点
idx
元素下标数组
value
指派的值

函数 cvSet*D 指定新的值给指定的数组元素。对于稀疏矩阵如果指定节点不存在函数创建新的节点



SetReal*D

修改指定数组元素值

void cvSetReal1D( CvArr* arr, int idx0, double value );
void cvSetReal2D( CvArr* arr, int idx0, int idx1, double value );
void cvSetReal3D( CvArr* arr, int idx0, int idx1, int idx2, double value );
void cvSetRealND( CvArr* arr, int* idx, double value );

arr
输入数组.
idx0
元素下标的第一个成员,以0为基点
idx1
元素下标的第二个成员,以0为基点
idx2
元素下标的第三个成员,以0为基点
idx
元素下标数组
value
指派的值

函数 cvSetReal*D 分配新的值给单通道数组的指定元素,如果数组是多通道就会产生运行时错误。然而cvSet*D 可以安全的被用于多通道和单通道数组。
对于稀疏数组如果指定的节点不存在函数会创建该节点。

以下是一个例子:

#pragma comment(lib,"cxcore.lib")
#include"cv.h"
#include<stdio.h>
void main()
{
//矩阵元素为三通道8位浮点数
CvMat *mat=cvCreateMat(3,3,CV_32FC3 );
cvZero(mat);//将矩阵置0
//为矩阵元素赋值


for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
cvSet2D( mat, i, j, cvScalar(i*10,j*10,i*j*10) );

for(i=0;i<3;i++)
for(int j=0;j<3;j++)
{
printf("%lf,%lf,%lf\t",cvGet2D( mat, i, j ).val[0],cvGet2D( mat, i, j ).val[1],cvGet2D( mat, i, j ).val[2]);

}

}



为了方便起见,OpenCV还定义了两个函数:cvmSet()和cvmGet(),这两个函数用于单通道浮点型元素矩阵的存取。
例如,cvmSet(mat,2,2,0.5);就类似于cvSetReal2D(mat,2,2,0.5);

返回单通道浮点矩阵指定元素
double cvmGet( const CvMat* mat, int row, int col );
为单通道浮点矩阵的指定元素赋值。
void cvmSet( CvMat* mat, int row, int col, double value );
Cxcore基礎結構
Wikipedia,自由的百科全书
目錄
[隱藏]
1 CvPoint
2 CvPoint2D32f
3 CvPoint3D32f
4 CvSize
5 CvSize2D32f
6 CvRect
7 CvScalar
8 CvTermCriteria
9 CvMat
10 CvMatND
11 CvSparseMat
12 IplImage
13 CvArr
[編輯]
CvPoint
二維坐標系下的點,類型為整型
typedef struct CvPoint
{
  int x; /* X坐標, 通常以0為基點 */
  int y; /* y坐標, 通常以0為基點 */
}
CvPoint;
/* 構造函數 */
inline CvPoint cvPoint( int x, int y );
/* 從 CvPoint2D32f類型轉換得來 */
inline CvPoint cvPointFrom32f( CvPoint2D32f point )
ddd
[編輯]
CvPoint2D32f
二維坐標下的點,類型為浮點
typedef struct CvPoint2D32f
{
  float x; /* X坐標, 通常以0為基點*/
  float y; /* Y坐標, 通常以0為基點*/
}
CvPoint2D32f;
/* 構造函數 */
inline CvPoint2D32f cvPoint2D32f( double x, double y );
/* 從CvPoint轉換來 */
inline CvPoint2D32f cvPointTo32f( CvPoint point );
[編輯]
CvPoint3D32f
三維坐標下的點,類型為浮點
typedef struct CvPoint3D32f
{
  float x; /* x-坐標, 通常基於0 */
  float y; /* y-坐標, 通常基於0 */
  float z; /* z-坐標, 通常基於0 */
}
CvPoint3D32f;
/* 構造函數 */
inline CvPoint3D32f cvPoint3D32f( double x, double y, double z );
[編輯]
CvSize
矩形框大小,以像素為精度
typedef struct CvSize
{
  int width;  /* 矩形寬 */
  int height; /* 矩形高 */
}
CvSize;
/* 構造函數 */
inline CvSize cvSize( int width, int height );
註意:構造函數的cv是小寫!
[編輯]
CvSize2D32f
以亞像素精度標量矩形框大小
typedef struct CvSize2D32f
{
  float width;  /* 矩形寬 */
  float height; /* 矩形高 */
}
CvSize2D32f;
/* 構造函數*/
inline CvSize2D32f cvSize2D32f( double width, double height );
{
    CvSize2D32f s;
    s.width = (float)width;
    s.height = (float)height;
    return s;
}
[編輯]
CvRect
矩形框的偏移和大小
typedef struct CvRect
{
  int x; /* 方形的最左角的x-坐標  */
  int y; /* 方形的最上或者最下角的y-坐標 */
  int width; /* 寬 */
  int height; /* 高 */
}
CvRect;
/* 構造函數*/
inline CvRect cvRect( int x, int y, int width, int height );
  { CvRect os;
     
      os.x = x;
      os.y = y;
      os.width = width;
      os.height = heigth;
     
      reture os;}
[編輯]
CvScalar
可存放在1-,2-,3-,4-TUPLE類型的捆綁數據的容器
typedef struct CvScalar
{
  double val[4]
}
CvScalar;
/* 構造函數:用val0初始化val[0]用val1初始化val[1], 以此類推*/
inline CvScalar cvScalar( double val0, double val1,
                          double val2, double val3);
{  CvScalar  arr;
   
    arr.val[4] = {val0,val1,val2,val3};
  printf函数返回值
    reture arr;}
/* 構造函數:用val0123初始化所有val[0]...val[3] */
inline CvScalar cvScalarAll( double val0123 );
  { CvScalar arr;
    arr.val[4] = {val0123,val0123,val0123,val0123,};
    reture arr;}
/* 構造函數:用val0初始化val[0],用0初始化val[1],val[2],val[3] */
inline CvScalar cvRealScalar( double val0 );
    { CvScalar arr;
     
      arr.val[4] = {val0};
 
      reture arr;}
dns.jp/opencv/classes/OpenCV/CvScalar.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。