自己实现的矩阵类QQ::Mat

来源:互联网 发布:网络刷手兼职合法的吗 编辑:程序博客网 时间:2024/04/29 10:45

为什么想写这个矩阵类Mat

用OpenCV两年半的时间了,期间也看过OpenCV的一些源码,比如Mat的实现,对OpenCV还是有一定的了解的,自己现在也在cv这个领域工作,觉得图像处理是非常有意思的一个领域,自己一直都有一一个梦想:建立自己的图像处理库,实现常用的图像处理算法,而建立图像处理库的一个基础就是需要有一个高效的矩阵类,这会大大提高图像处理算法的开发效率,最近实现了一下矩阵类,后期还会对他进行优化,大家有什么建议的,欢迎留言,不胜感激!


主要思想

这个矩阵类主要用到了下面的一些思想:
1. 模板,兼容多种类型的矩阵
2. 通过引用计数自动释放内存
3. 内存地址对齐,便于图像处理算法的指令集优化

注:
QQ::Mat除了命名规则与cv::Mat不同(QQ::Mat中的函数名使用帕斯卡命名规则),提供的接口基本与OpenCV提供的接口一致,所以,基于cv::Mat写的程序很容易改写为QQ::Mat的版本。
前面写过的几篇博客
图像旋转的原理,实现和优化
直方图均衡化算法原理与实现
Canny边缘检测算法的实现
虽然都是基于cv::Mat写的,但都非常容易改写成QQ::Mat的版本,有兴趣的读者可以自己实现一下,后面的博客中的图像处理算法都会使用QQ::Mat实现(对于需要兼容OpenCV的还是使用cv::Mat实现)。


实现

Mat.h

//////////////////////////////////////////////////////////////////////////// 矩阵类 Mat.h // 2016-12-24,by QQ//// Please contact me if you find any bugs, or have any suggestions.// Contact://      Telephone:15366105857//      Email:654393155@qq.com//      Blog: http://blog.csdn.net/qianqing13579//////////////////////////////////////////////////////////////////////////#ifndef __MAT_H__#define __MAT_H__#include "CommonDefinition.h"#include"Alloc.h"namespace QQ{template <typename T>class  DLL_EXPORTS Mat{public:    //构造函数    Mat();    Mat(int _rows, int _cols, int _numberOfChannels);    Mat(int _rows, int _cols, int _numberOfChannels, Scalar scalar);     Mat(int _rows, int _cols, int _numberOfChannels, void *_data, bool needCopyData = false);// 外部数据_data需要外部释放    //析构函数    virtual ~Mat();//调用Release()    void Release();//引用计数减1    void Deallocate();//释放数据    //自动分配内存    void Create(int _rows, int _cols, int _numberOfChannels);    void Create(Size _size, int _numberOfChannels);    //重载赋值操作符    inline Mat& operator = (const Mat &dstMat);//共享数据    void SetTo(const Scalar &scalar);    // 获取指定位置的元素    template<typename _Tp>    inline _Tp& At(int y, int x)    {        return ((_Tp*)(data + step*y))[x];    }protected:    void InitEmpty();public:    int rows;    int cols;    int numberOfChannels;//通道数    int step;// 步长(每行字节数)    uchar *data;        //引用计数    int *refCount;};// Mat//////////////////////////////Mat的实现////////////////////////////////////////////template <typename T>inline Mat<T>::Mat(){    InitEmpty();}template <typename T>inline void Mat<T>::InitEmpty(){    rows = cols = numberOfChannels = 0;    data = 0;    refCount = 0;}template <typename T>inline Mat<T>::Mat(int _rows, int _cols, int _numberOfChannels){    InitEmpty();    Create(_rows, _cols, _numberOfChannels);}template <typename T>inline Mat<T>::Mat(int _cols, int _rows, int _numberOfChannels, Scalar scalar){    InitEmpty();    Create(_cols, _rows, _numberOfChannels);    SetTo(scalar);}//BYTE->Image,IplImage->Image//默认不拷贝数据,外部数据_data需要外部释放template <typename T>inline Mat<T>::Mat(int _rows, int _cols, int _numberOfChannels, void *_data, bool needCopyData){    rows = _rows;    cols = _cols;    numberOfChannels = _numberOfChannels;    step = cols*numberOfChannels*sizeof(T);    if (needCopyData == false)    {        data=(uchar *)_data;        refCount = 0;    }    else    {        data = (uchar *)AlignedMalloc((step*rows + (int)sizeof(int)), 16);        refCount = (int*)(data + step*rows);        *refCount = 1;        memcpy(data, _data, step*rows);//拷贝    }}template <typename T>Mat<T>::~Mat(){    Release();//释放}// 引用计数减1,如果引用计数为0了,调用Deallocate()template <typename T>void Mat<T>::Release(){    //引用计数减1,如果引用计数为0,说明没有引用,释放数据    if (refCount && (*refCount)-- == 1)    {        Deallocate();    }    InitEmpty();}//释放数据template <typename T>void Mat<T>::Deallocate(){    AlignedFree(data);}template <typename T>void Mat<T>::Create(int _rows, int _cols, int _numberOfChannels){    if (rows == _rows&&cols == _cols&&numberOfChannels == _numberOfChannels)    {        return;    }    else    {        //如果不一致,引用计数减1,此时引用计数为0,释放数据和引用计数        Release();        rows = _rows;        cols = _cols;        numberOfChannels = _numberOfChannels;        step = cols*numberOfChannels*sizeof(T);        // 内存地址16字节对齐(指令集优化)        data = (uchar *)AlignedMalloc((step*rows + (int)sizeof(int)), 16);        refCount = (int*)(data + step*rows);        *refCount = 1;    }}template <typename T>inline void Mat<T>::Create(Size _size, int _numberOfChannels){    int _rows = _size.height;    int _cols = _size.width;    Create(_rows, _cols, _numberOfChannels);}//重载操作符// 注意返回值为Image&(如果返回void,A=(B=C),那么A就没有值了)template <typename T>inline Mat<T>& Mat<T>::operator = (const Mat<T> &dstMat){    if (this != &dstMat)    {        // 调用this的release        Release();        rows = dstMat.rows;        cols = dstMat.cols;        numberOfChannels = dstMat.numberOfChannels;        step = dstMat.step;        data = dstMat.data;        //引用计数        refCount = dstMat.refCount;        (*refCount)++;    }    return *this;}template <typename T>void Mat<T>::SetTo(const Scalar &scalar){    T *dataOfSrc = (T *)data;    int numberOfElement = rows*cols;    for (int i = 0; i <= numberOfElement - 1; ++i, dataOfSrc += numberOfChannels)    {        for (int k = 0; k <= numberOfChannels - 1; ++k)            dataOfSrc[k] = scalar.val[k];    }}}// namespace QQ#endif

其中AlignedMalloc()函数和AlignedFree()函数见博客: 实现任意字节对齐的内存分配和释放

CommonDefinition.h

//////////////////////////////////////////////////////////////////////////// 通用定义 CommonDefinition.h// 2014-11-13,by QQ//// Please contact me if you find any bugs, or have any suggestions.// Contact://      Telephone:15366105857//      Email:654393155@qq.com//      Blog: http://blog.csdn.net/qianqing13579//////////////////////////////////////////////////////////////////////////#ifndef __COMMON_DEFINITION_H__#define __COMMON_DEFINITION_H__#include<assert.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>//////////////////////////////Common macros//////////////////////////////////////////////WIN32,_WIN32:判断是否 Windows平台//DLLAPI_EXPORTS:条件宏//DLL_EXPORTS:DLL导出符号#if (defined WIN32 || defined _WIN32 || defined WINCE) && defined DLLAPI_EXPORTS#define DLL_EXPORTS __declspec(dllexport)#else#define DLL_EXPORTS#endif#ifndef MAX#define MAX(a,b)  ((a) > (b) ? (a) : (b))#endif#ifndef MIN#define MIN(a,b)  ((a) > (b) ? (b) : (a))#endif#define PI   3.1415926535897932384626433832795#define LOG2 0.69314718055994530941723212145818//角度转换#define DEGREE2RADIAN(x) (x*PI/180)//角度转弧度#define RADIAN2DEGREE(x) (x*180/PI)//弧度转角度#define  DESCALE(x,n)  (((x)+(1 << ((n)-1))) >> (n))//#define  DESCALE(x,n)  ((x) >> (n)) // 饱和运算#define  saturate(x)   (uchar)(((x) & ~255) == 0 ? (x) : ~((x)>>31))// memory deallocation#define SAFE_DELETE(p)  { if ((p)) { delete (p); (p) = NULL; } }#define SAFE_DELETE_ARRAY(p)  { if ((p)) { delete[] (p); (p) = NULL; } }///////////////////////////////Common type definitions///////////////////////////////////////////////typedef unsigned char uchar;typedef unsigned short ushort; // 2 ucharstypedef unsigned int uint;  // 4 uchars//Resize:interpolation methods差值方式enum{    NEAREST   =0,//最近邻差值    LINEAR    =1,//双线性插值,图像缩小时候,容易出现波纹    AREA      =2//像素关系重采样};////////////////////////////namespace QQ//////////////////////////////////////////////namespace QQ{/////////////////////////////Scalar/////////////////////////////////////////////// 表示像素值class Scalar{public:    //成员函数    //构造函数    Scalar(double val0=0, double val1=0,double val2=0, double val3=0);//默认都为0    Scalar(const Scalar &scalar);    //成员变量    double val[4];};inline Scalar::Scalar(double val0, double val1,double val2, double val3){    val[0]=val0;    val[1]=val1;    val[2]=val2;    val[3]=val3;}inline Scalar::Scalar(const Scalar &scalar){    val[0]=scalar.val[0];    val[1]=scalar.val[1];    val[2]=scalar.val[2];    val[3]=scalar.val[3];}///////////////////////////Size///////////////////////////////////////////////class Size{public:    //成员函数    //构造函数    Size();    Size(int _width,int _height);    Size(const Size &size);    //成员变量    int width;    int height;};inline Size::Size():width(0),height(0){}inline Size::Size(int _width,int _height):width(_width),height(_height){}inline Size::Size(const Size &size):width(size.width),height(size.height){}///////////////////////////Vec3b///////////////////////////////////////////////class Vec3b{public:    //构造函数    Vec3b(uchar val0 = 0, uchar val1 = 0, uchar val2 = 0);//默认都为0    Vec3b(const Vec3b &vec3b);    inline uchar& operator[](int i);    //成员变量    uchar val[3];};inline Vec3b::Vec3b(uchar val0, uchar val1, uchar val2){    val[0] = val0;    val[1] = val1;    val[2] = val2;}inline Vec3b::Vec3b(const Vec3b &vec3b){    val[0] = vec3b.val[0];    val[1] = vec3b.val[1];    val[2] = vec3b.val[2];}inline uchar& Vec3b::operator[](int i){    return val[i];}///////////////////////////Point///////////////////////////////////////////////class Point{public:    //构造函数    Point() :x(0), y(0){}    Point(int _x, int _y) :x(_x), y(_y){}    //Point(const Point &point);    //成员变量    int x, y;};}//namespace QQ#endif

结束语

重复造轮子对程序员能力的提高还是很大的,希望通过构建自己的图像处理库不断提高自己的能力,也希望自己能够在这个领域越走越远,实现自己的人生价值。

2017-1-10 17:59:32

非常感谢您的阅读,如果您觉得这篇文章对您有帮助,欢迎扫码进行赞赏。
这里写图片描述

1 0
原创粉丝点击