Opencv 学习(1) Mat详解

Opencv 学习(1)

  • Mat提供内联函数
    优点:编译的时候会把该段代码直接拷贝到自己的代码中,非内联函数的话会造成堆栈出栈的空间消耗。

  • Mat创建与清理空间
    创建:通过构造函数直接创建,
    释放:
    1、create时会把之前的空间清理。
    2、release或者析构-引用计数为1时释放

//创建3000*4000的RGB图像,UC3为unsigned char型,3个字节,对应RGB
Mat mat(3000,4000, CV_8UC3);
//或者
mat.create(rows, cols, CV_8UC1);
  • 3XRGB图像存放方式(连续)
    这里写图片描述

  • isContinuous
    1、判断存储空间是否连续
    2、通过step记录

  • 直接地址访问连续空间

int  size = mat.rows*mat.cols*mat.elemSize;
for(int i=0; i<size; i+=3)
{
    mat.data[i] = 0; //B
    mat.data[i+1] = 0; //G
    mat.data[i+2] = 0; //R
}
  • 简单的实例
#include<stdio.h>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
void PrintMs(const char *text = "")
{
    static long long last = 0;
    long long cur = getTickCount();
    if (last == 0)
    {
        last = cur;
        return;
    }
    long long ms = 0;
    ms = ((double)(cur - last) / getTickFrequency()) * 1000;
    if (*text != 0)
    {
        printf("%s = %dms\n ", text, ms);
    }
    last = getTickCount();
}

int main(int argc, char *argv)
{
    Mat mat(3000,4000,CV_8UC3);
    int es = mat.elemSize();
    int size = mat.rows*mat.cols*es;

    PrintMs();//计时

    for (int i = 0; i < size; i += es)
    {
        mat.data[i] = 255; //B
        mat.data[i + 1] = 100; //G
        mat.data[i + 2] = 100; //R

    }

    PrintMs("mat.data ms");
    namedWindow("img");
    imshow("img", mat);
    waitKey(0);

    return 0;
}
  • 直接访问不连续空间
    1、
    for (int row = 0; row < mat.rows; row++)
    {
        for (int col = 0; col < mat.cols; col++)
        {
            (&mat.data[row*mat.step])[col*es] = 0;//B
            (&mat.data[row*mat.step])[col*es+1] = 0;//G
            (&mat.data[row*mat.step])[col*es+2] = 255;//R
        }
    }

2、通过ptr接口遍历Mat(模板函数)

mat.ptr<Vec3b>(row);//返回的指针
mat.ptr<Vec3b>(row,col);

例子:
#include<stdio.h>
#include<iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
void PrintMs(const char *text = "")
{
    static long long last = 0;
    long long cur = getTickCount();
    if (last == 0)
    {
        last = cur;
        return;
    }
    long long ms = 0;
    ms = ((double)(cur - last) / getTickFrequency()) * 1000;
    if (*text != 0)
    {
        printf("%s = %dms\n ", text, ms);
    }
    last = getTickCount();
}

int main(int argc, char *argv)
{
    Mat mat(3000,4000,CV_8UC3);
    int es = mat.elemSize();
    cout << es << endl;
    int size = mat.rows*mat.cols*es;

    PrintMs();

    for (int i = 0; i < size; i += es)
    {
        mat.data[i] = 255; //B
        mat.data[i + 1] = 100; //G
        mat.data[i + 2] = 100; //R

    }

    PrintMs("mat.data ms");

    for (int row = 0; row < mat.rows; row++)
    {
        for (int col = 0; col < mat.cols; col++)
        {
            (&mat.data[row*mat.step])[col*es] = 0;//B
            (&mat.data[row*mat.step])[col*es+1] = 0;//G
            (&mat.data[row*mat.step])[col*es+2] = 255;//R
        }
    }
    PrintMs("mat.step ms");

    //使用ptr遍历Mat
    for (int row = 0; row < mat.rows; row++)
    {
        for (int col = 0; col < mat.cols; col++)
        {
            Vec3b *c = mat.ptr<Vec3b>(row, col);
            c->val[0] = 0;//B
            c->val[1] = 255;//G
            c->val[2] = 0;//R

        }
    }
    PrintMs("mat.ptr ms");

    namedWindow("img");
    imshow("img", mat);
    waitKey(0);

    return 0;
}
  • 通过at接口遍历Mat(模板函数)
    1、接口最简单的遍历法
mat.at<Vec3b>(row,col)[0] = 255;
mat.at<Vec3b>(row,col)[1] = 0;
mat.at<Vec3b>(row,col)[2] = 255;
  • 通过迭代器遍历Mat
    1、可以不用管mat的行列
auto it = mr.begin<Vec3b>();//自动匹配类型
auto it_end = mr.end<Vec3b>();
for(;it != it_end; ++it)
{
    (*it).val[0] = 0;
    (*it).val[1] = 222;
    (*it).val[2] = 0;
}

所有的访问方式放在一块:

#include<stdio.h>
#include<iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
void PrintMs(const char *text = "")
{
    static long long last = 0;
    long long cur = getTickCount();
    if (last == 0)
    {
        last = cur;
        return;
    }
    long long ms = 0;
    ms = ((double)(cur - last) / getTickFrequency()) * 1000;
    if (*text != 0)
    {
        printf("%s = %dms\n ", text, ms);
    }
    last = getTickCount();
}

int main(int argc, char *argv)
{
    Mat mat(3000, 4000, CV_8UC3);
    int es = mat.elemSize();
    cout << es << endl;
    int size = mat.rows*mat.cols*es;

    PrintMs();

    for (int i = 0; i < size; i += es)
    {
        mat.data[i] = 255; //B
        mat.data[i + 1] = 100; //G
        mat.data[i + 2] = 100; //R

    }

    PrintMs("mat.data ms");

    for (int row = 0; row < mat.rows; row++)
    {
        for (int col = 0; col < mat.cols; col++)
        {
            (&mat.data[row*mat.step])[col*es] = 0;//B
            (&mat.data[row*mat.step])[col*es + 1] = 0;//G
            (&mat.data[row*mat.step])[col*es + 2] = 255;//R
        }
    }
    PrintMs("mat.step ms");

    //使用ptr遍历Mat
    for (int row = 0; row < mat.rows; row++)
    {
        for (int col = 0; col < mat.cols; col++)
        {
            Vec3b *c = mat.ptr<Vec3b>(row, col);
            c->val[0] = 0;//B
            c->val[1] = 255;//G
            c->val[2] = 0;//R

        }
    }
    PrintMs("mat.ptr ms");

    //使用at遍历,易于调试
    try //捕获异常,
    {
        for (int row = 0; row < mat.rows; row++)//乘2越界
        {
            for (int col = 0; col < mat.cols; col++)
            {
                Vec3b &m = mat.at<Vec3b>(row, col);
                m[0] = 100;
                m[1] = 100;
                m[2] = 100;
            }
        }
    }
    catch (Exception &ex)
    {
        cout << ex.what() << endl;
    }

    PrintMs("mat.at ms");
    PrintMs("");
    auto it = mat.begin<Vec3b>();
    auto it_end = mat.end<Vec3b>();
    for (; it != it_end; it++)
    {
        (*it).val[0] = 0; //B
        (*it).val[1] = 0; //G
        (*it).val[2] = 255; //R
    }
    PrintMs("mat.auto ms");

    namedWindow("img");
    imshow("img", mat);
    waitKey(0);

    return 0;

}
发布了38 篇原创文章 · 获赞 29 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/ruotianxia/article/details/79816457