常用的基本函数
Mat矩阵的定义
data:Mat对象中的一个指针,指向内存中存放矩阵数据的一块内存 (uchar* data)
dims:Mat所代表的矩阵的维度,如 3 * 4 的矩阵为 2 维, 3 * 4 * 5 的为3维
channels:通道,矩阵中的每一个矩阵元素拥有的值的个数,比如说 3 * 4 矩阵中一共 12 个元素,如果每个元素有三个值,那么就说这个矩阵是 3 通道的,即 channels = 3。常见的是一张彩色图片有红、绿、蓝三个通道。
depth:深度,即每一个像素的位数(bits),在opencv的Mat.depth()中得到的是一个 0 – 6 的数字,分别代表不同的位数:enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }; 可见 0和1都代表8位, 2和3都代表16位,4和5代表32位,6代表64位;
step:是一个数组,定义了矩阵的布局,具体见下面图片分析,另外注意 step1 (step / elemSize1),M.step[m-1] 总是等于 elemSize,M.step1(m-1)总是等于 channels;
elemSize : 矩阵中每一个元素的数据大小,如果Mat中的数据的数据类型是 CV_8U 那么 elemSize = 1,CV_8UC3 那么 elemSize = 3,CV_16UC2 那么 elemSize = 4;记住另外有个 elemSize1 表示的是矩阵中数据类型的大小,即 elemSize / channels 的大小
获取某一点的像素点
最快的获取形式
Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)
{
// accept only char type matrices
CV_Assert(I.depth() != sizeof(uchar));
int channels = I.channels();
int nRows = I.rows ;
int nCols = I.cols* channels;
if (I.isContinuous())
{
nCols *= nRows;
nRows = 1;
}
int i,j;
uchar* p;
for( i = 0; i < nRows; ++i)
{
p = I.ptr<uchar>(i);
for ( j = 0; j < nCols; ++j)
{
p[j] = table[p[j]];
}
}
return I;
}
获其中一个点的函数
//获得某点像素值
int get_pixel(Mat & img, Point pt) {
int width = img.cols; //图片宽度
int height = img.rows; //图片宽度t;//图片高度
// x 是 列 , y 是 行
uchar* ptr = (uchar*) img.data + pt.y * width; //获得灰度值数据指针
int intensity = ptr[pt.x];
return intensity;
}
Mat最直接的访问方法是通过.ptr<>函数得到一行的指针,并用[]操作符访问某一列的像素值。
注意不可以像matlab中直接‘img[1][1]’来获取第一个元素,因为openCV应该没有重构这个[i][j]操作符。
// using .ptr and []
void colorReduce0(cv::Mat &image, int div=64) {
int nr= image.rows; // number of rows
int nc= image.cols * image.channels(); // total number of elements per line
for (int j=0; j<nr; j++) {
uchar* data= image.ptr<uchar>(j);
for (int i=0; i<nc; i++) {
data[i]= data[i]/div*div + div/2;
}
}
灰度图存储可视化:
三通道彩色图存储可视化:
这是使用opencv中自己定义的at函数来取像素值,代码如下,函数更为简洁,但是速度方面却更慢。这个例子也可以看出opencv的图像存储格式是HWC,其中最后的channel是按照BGR的格式来存放的,通过【0】来获取Blue通道的值。
// using (j,i)
void colorReduce11(cv::Mat &image, int div=64) {
int nr= image.rows; // number of rows
int nc= image.cols; // number of columns
for (int j=0; j<nr; j++) {
for (int i=0; i<nc; i++) {
image.at<cv::Vec3b>(j,i)[0]= image.at<cv::Vec3b>(j,i)[0]/div*div + div/2;
image.at<cv::Vec3b>(j,i)[1]= image.at<cv::Vec3b>(j,i)[1]/div*div + div/2;
image.at<cv::Vec3b>(j,i)[2]= image.at<cv::Vec3b>(j,i)[2]/div*div + div/2;
} // end of row
}
}
不同获取方式的速度对比:https://blog.csdn.net/xiaowei_cqu/article/details/19839019
关于step和elemSize的讲解:https://blog.csdn.net/dcrmg/article/details/52294259?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param