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

从零开始 OpenCV (二) —— OpenCV 的基本数据类型和基本函数

2017-12-16 19:51 423 查看

从零开始 OpenCV (二) —— OpenCV 的基本数据类型和基本函数

注: 本系列博客主要针对 OpenCV 的 C 语言库部分。

OpenCV 的基本数据类型及其相关函数

...\opencv\build\include\opencv2\core\types_c.h
文件中定义了一些基本的数据类型。

坐标点类型:
CvPoint

typedef struct CvPoint
{
int x;
int y;
}CvPoint;


针对不同的数值类型,
CvPoint
还有几个变体类型:
CvPoint2D32f
,
CvPoint2D64f
,
CvPoint3D32f
以及
CvPoint3D64f


记录矩形宽高的
CvSize
类型

typedef struct CvSize
{
int width;
int height;
}CvSize;


CvSize
类型也有变体类型:
CvSize2D32f


矩形类型:
CvRect

typedef struct CvRect
{
int x;
int y;
int width;
int height;
}CvRect;


标量(scalar)类型:
CvScalar

typedef struct CvScalar
{
double val[4];
}CvScalar;


以上类型(
CvRect
,
CvScalar
等) 都有一个与之匹配的类似于构造函数的功能的函数(具有与结构类型一样的名字, 只是首字母不大写, 如:
cvRect()
)。

矩阵类型:
CvMat

一. 矩阵结构(
CvMat
)的定义

typedef struct CvMat
{
int type;
int step;

/* for internal use only */
int* refcount;
int hdr_refcount;

union
{
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
} data;

int rows;
int cols;
}CvMat;


其中,
type
指定矩阵中存放的元素类型, 其结构为
CV_<bit_depth>(S|U|F)C<number_of_channels>
, 如:
CV_8UC3
表示该矩阵存放的是无符号的 8 位三元组的整形数据。
data
指向实际存放矩阵的数据体。
step
存储行数据的长度(以字节为单位)。

二.
CvMat
的创建,释放和克隆

(1) 创建
type
类型, 行数为
rows
, 列数为
cols
的矩阵:
cvCreateMat


// Creates a matrix header and allocates the matrix data.
CvMat* cvCreateMat(int rows, int cols, int type);


(2) 矩阵
mat
的释放:
cvReleaseMat


// Deallocates a matrix.
// The function decrements the matrix data reference counter and deallocates matrix header.
// If the data reference counter is 0, it also deallocates the data. :
void cvReleaseMat(CvMat** mat);


(3) 矩阵
mat
的克隆:
cvCloneMat


// Creates an exact copy of the input matrix.
CvMat* cvCloneMat(const cvMat* mat);


三. 矩阵的存取

(1)
CV_MAT_ELEM()
CV_MAT_ELEM_PTR()


#define CV_MAT_ELEM_PTR_FAST( mat, row, col, pix_size )  \
(assert( (unsigned)(row) < (unsigned)(mat).rows &&   \
(unsigned)(col) < (unsigned)(mat).cols ),   \
(mat).data.ptr + (size_t)(mat).step*(row) + (pix_size)*(col))

#define CV_MAT_ELEM_PTR( mat, row, col )                 \
CV_MAT_ELEM_PTR_FAST( mat, row, col, CV_ELEM_SIZE((mat).type) )

#define CV_MAT_ELEM( mat, elemtype, row, col )           \
(*(elemtype*)CV_MAT_ELEM_PTR_FAST( mat, row, col, sizeof(elemtype)))


注:
CvMat
中是将数据存在一个一维数组中,具体存储形式如下图:



关于
CV_MAT_ELEM()
CV_MAT_ELEM_PTR
举个例子:

CvMat* may = cvCreateMat(5, 5, CV_32FC1);
// 读取 (3,3) 处的一元组
float elem_3_3 = CV_MAT_ELEM(*mat, float, 3, 3);
// 将 (3,3) 处的一元组的值改为 33
float* elemPtr_3_3 = (float*)CV_MAT_ELEM_PTR(*mat, 3, 3);
(*elemPtr_3_3) = 33;


(2)
cvGet*D
函数簇和
cvPtr*D
函数簇

cvGet*D
函数簇

// This is the "metatype" used only as a function parameter.
// It denotes that the function accepts arrays of multiple types, such as IplImage*, CvMat* or even CvSeq* sometimes.
// The particular array type is determined at runtime by analyzing the first 4 bytes of the header.
// In C++ interface the role of CvArr is played by InputArray and OutputArray.
typedef void CvArr;

// The functions return a specific array element.
// In the case of a sparse array the functions return 0
// if the requested node does not exist (no new node is created by the functions).
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);


cvPtr*D
函数簇

// Return pointer to a particular array element.
// The functions return a pointer to a specific array element.
// Number of array dimension should match to the number of indices passed to the function
// except for cvPtr1D function that can be used for sequential access to 1D, 2D or nD dense arrays.
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);


(3) 直接对
data
指针进行操作。

IplImage
数据结构

一.
IplImage
数据结构的定义

/*
* The following definitions (until #endif)
* is an extract from IPL headers.
* Copyright (c) 1995 Intel Corporation.
*/

#define IPL_DEPTH_SIGN 0x80000000

#define IPL_DEPTH_1U     1
#define IPL_DEPTH_8U     8
#define IPL_DEPTH_16U   16
#define IPL_DEPTH_32F   32

#define IPL_DEPTH_8S  (IPL_DEPTH_SIGN| 8)
#define IPL_DEPTH_16S (IPL_DEPTH_SIGN|16)
#define IPL_DEPTH_32S (IPL_DEPTH_SIGN|32)

#define IPL_DATA_ORDER_PIXEL  0
#define IPL_DATA_ORDER_PLANE  1

#define IPL_ORIGIN_TL 0
#define IPL_ORIGIN_BL 1

#define IPL_ALIGN_4BYTES   4
#define IPL_ALIGN_8BYTES   8
#define IPL_ALIGN_16BYTES 16
#define IPL_ALIGN_32BYTES 32

#define IPL_ALIGN_DWORD   IPL_ALIGN_4BYTES
#define IPL_ALIGN_QWORD   IPL_ALIGN_8BYTES

#define IPL_BORDER_CONSTANT   0
#define IPL_BORDER_REPLICATE  1
#define IPL_BORDER_REFLECT    2
#define IPL_BORDER_WRAP       3

/** The IplImage is taken from the Intel Image Processing Library, in which the format is native. OpenCV
only supports a subset of possible IplImage formats, as outlined in the parameter list above.

In addition to the above restrictions, OpenCV handles ROIs differently. OpenCV functions require
that the image size or ROI size of all source and destination images match exactly. On the other
hand, the Intel Image Processing Library processes the area of intersection between the source and
destination images (or ROIs), allowing them to vary independently.
*/
typedef struct _IplImage
{
int  nSize;             /**< sizeof(IplImage) */
int  ID;                /**< version (=0)*/
int  nChannels;         /**< Most of OpenCV functions support 1,2,3 or 4 channels */
int  alphaChannel;      /**< Ignored by OpenCV */
int  depth;             /**< Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S,
IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported.  */
char colorModel[4];     /**< Ignored by OpenCV */
char channelSeq[4];     /**< ditto */
int  dataOrder;         /**< 0 - interleaved color channels, 1 - separate color channels.
cvCreateImage can only create interleaved images */
int  origin;            /**< 0 - top-left origin,
1 - bottom-left origin (Windows bitmaps style).  */
int  align;             /**< Alignment of image rows (4 or 8).
OpenCV ignores it and uses widthStep instead.    */
int  width;             /**< Image width in pixels.                           */
int  height;            /**< Image height in pixels.                          */
struct _IplROI *roi;    /**< Image ROI(Region of Interest). If NULL, the whole image is selected. */
struct _IplImage *maskROI;      /**< Must be NULL. */
void  *imageId;                 /**< "           " */
struct _IplTileInfo *tileInfo;  /**< "           " */
int  imageSize;         /**< Image data size in bytes
(==image->height*image->widthStep
in case of interleaved data)*/
char *imageData;        /**< Pointer to aligned image data.         */
int  widthStep;         /**< Size of aligned image row in bytes.    */
int  BorderMode[4];     /**< Ignored by OpenCV.                     */
int  BorderConst[4];    /**< Ditto.                                 */
char *imageDataOrigin;  /**< Pointer to very origin of image data
(not necessarily aligned) -
needed for correct deallocation */
} IplImage;


(1)
origin
取值
IPL_ORIGIN_TL
IPL_ORIGIN_BL
, 分别设置坐标原点的位置为图像的左上角或者左下角

(2)
dataOrder
取值
IPL_DATA_ORDER_PIXEL
IPL_DATA_ORDER_PLANE
, 前者指明数据是将像素点的不同通道的值交错在一起, 后者是把所有像素同通道值排在一起m 形成通道平面, 再把平面排列起来。

(3) ROI(Region of Interest): 一旦设置了 ROI, 通常作用于整幅图像的函数便会只对 ROI 所表示的子图像进行操作。 如果 ROICOI(Channel of Interest) 设置为非 0 值, 则只对该对子图像的指定通道上进行操作。

二. 加载图像:
cvLoadImage


IplImage* cvLoadImage(const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR);


三. 展示图像:
cvShowImage


/* display image within window (highgui windows remember their content) */
void cvShowImage(const char* name, const CvArr* image);


四. 设置和释放 ROI:
cvSetImageROI
cvResetImageROI


// Sets an image Region Of Interest (ROI) for a given rectangle.
// If the original image ROI was NULL and the rect is not the whole image,
//  the ROI structure is allocated.
// image: A pointer to the image header
// rect: The ROI rectangle
void cvSetImageROI(IplImage* image, CvRect rect);

// Resets the image ROI to include the entire image and releases the ROI structure.
void cvResetImageROI(IplImage* image);


五. 举个例子: 将
src
的指定 ROI 的像素点减去指定的
cvScalar


#include "opencv/highgui.h"
#include "opencv/cv.h"

int main()
{
// load image from file
IplImage* src = cvLoadImage("C:\\Users\\yanglion\\Pictures\\Img\\Ali.jpg");

//
// set image's ROI
cvSetImageROI(src, cvRect(216, 123, 100, 70));
// dst(mask) = src(mask) - value = src(mask) + (-value)
cvSubS(src, cvScalar(50,50,100), src);
// Resets the image ROI to include the entire image and releases the ROI structure.
cvResetImageROI(src);

// create window
cvNamedWindow("Ali");
// display image within window (highgui windows remember their content)
cvShowImage("Ali", src);
// wait for key event infinitely (delay<=0) or for "delay" milliseconds
cvWaitKey();

return 0;
}


运行效果:

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