自己实现的矩阵类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
非常感谢您的阅读,如果您觉得这篇文章对您有帮助,欢迎扫码进行赞赏。
- 自己实现的矩阵类QQ::Mat
- c++实现简单矩阵类Mat
- Mat矩阵的初始化
- Mat矩阵的初始化
- OpenCv:Mat矩阵的初始化
- OpenCv矩阵(Mat)的构造
- Opencv Mat 矩阵的运算
- Opencv Mat类的操作符重载及矩阵操作
- OpenCV Mat的实现
- cv::Mat 的子矩阵赋值
- MAT矩阵的应用(一)
- cv::Mat 的子矩阵赋值
- opencv 保存mat矩阵的数据
- opencv Mat矩阵的“深浅”复制
- OpenCV图像矩阵Mat的基本操作
- 在自己的网站上实现QQ授权登录
- OpenCV Mat类矩阵元素访问
- OpenCV中矩阵类详解之一:Mat
- 在Linux服务器上配置多个Tomcat服务
- java集合中的List接口
- C#中的线程之Abort陷阱
- 响应式
- Codeforces Round #383 (Div. 2) B. Arpa’s obvious problem and Mehrdad’s terrible solution 数论、易错
- 自己实现的矩阵类QQ::Mat
- 寻找链表中间节点
- 微信小程序一.初识微信小程序
- IDEA快捷键
- 你能直接写出多少个C++关键字?
- 2.非关系型数据库(Nosql)之mongodb:mongodb显示所有数据库,使用数据库,集合创建(显示和隐式创建),集合查询,初步数据的增删改查,分页
- MTK Log和Systrace简介
- C语言:数组排序(插入排序、选择排序、泡排序、谢尔排序、快速排序、堆排序)
- Oracle CASE WHEN 用法介绍