opencv:Mat对象

Mat对象:图像文件的内存数据对象

opencv:Mat对象_第1张图片

读取为 Mat 对象

读取图像位Mat对象,获取图像的相关信息

#include 
#include 

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{

    Mat src = imread("f:/temp/images/lena.jpg", IMREAD_GRAYSCALE);

    if (src.empty())
    {
        printf("Could not find the image!\n");
        return -1;
    }


    namedWindow("002-demo", WINDOW_AUTOSIZE);
    imshow("002-demo", src);

    // 获取图像的宽度
    int width = src.cols;
    // 获取图像的高度
    int height = src.rows;
    // 获取图像的通道数
    int dim = src.channels();
    int depth = src.depth();
    int type = src.type();

    if (type == CV_8UC1)
    {
        printf("type:CV_8UC1\n");
    }

    // 这里打印出来depth和type有时候为0,并不代表深度为0,而是代表一个枚举类型的值
    printf("width: %d, height: %d, dim: %d, depth: %d, type: %d\n", width, height, dim, depth, type);

   
    waitKey(0);
    destroyAllWindows();

    return 0;
}

图像的类型与结构信息:
opencv:Mat对象_第2张图片

#ifndef OPENCV_CORE_HAL_INTERFACE_H
#define OPENCV_CORE_HAL_INTERFACE_H

//! @addtogroup core_hal_interface
//! @{

//! @name Return codes
//! @{
#define CV_HAL_ERROR_OK 0
#define CV_HAL_ERROR_NOT_IMPLEMENTED 1
#define CV_HAL_ERROR_UNKNOWN -1
//! @}

#ifdef __cplusplus
#include 
#else
#include 
#include 
#endif

//! @name Data types
//! primitive types
//! - schar  - signed 1 byte integer
//! - uchar  - unsigned 1 byte integer
//! - short  - signed 2 byte integer
//! - ushort - unsigned 2 byte integer
//! - int    - signed 4 byte integer
//! - uint   - unsigned 4 byte integer
//! - int64  - signed 8 byte integer
//! - uint64 - unsigned 8 byte integer
//! @{
#if !defined _MSC_VER && !defined __BORLANDC__
#  if defined __cplusplus && __cplusplus >= 201103L && !defined __APPLE__
#    include 
#    ifdef __NEWLIB__
        typedef unsigned int uint;
#    else
        typedef std::uint32_t uint;
#    endif
#  else
#    include 
     typedef uint32_t uint;
#  endif
#else
   typedef unsigned uint;
#endif

typedef signed char schar;

#ifndef __IPL_H__
   typedef unsigned char uchar;
   typedef unsigned short ushort;
#endif

#if defined _MSC_VER || defined __BORLANDC__
   typedef __int64 int64;
   typedef unsigned __int64 uint64;
#  define CV_BIG_INT(n)   n##I64
#  define CV_BIG_UINT(n)  n##UI64
#else
   typedef int64_t int64;
   typedef uint64_t uint64;
#  define CV_BIG_INT(n)   n##LL
#  define CV_BIG_UINT(n)  n##ULL
#endif

#define CV_USRTYPE1 (void)"CV_USRTYPE1 support has been dropped in OpenCV 4.0"

#define CV_CN_MAX     512
#define CV_CN_SHIFT   3
#define CV_DEPTH_MAX  (1 << CV_CN_SHIFT)

#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6
#define CV_16F  7

#define CV_MAT_DEPTH_MASK       (CV_DEPTH_MAX - 1)
#define CV_MAT_DEPTH(flags)     ((flags) & CV_MAT_DEPTH_MASK)

#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
#define CV_MAKE_TYPE CV_MAKETYPE

#define CV_8UC1 CV_MAKETYPE(CV_8U,1)
#define CV_8UC2 CV_MAKETYPE(CV_8U,2)
#define CV_8UC3 CV_MAKETYPE(CV_8U,3)
#define CV_8UC4 CV_MAKETYPE(CV_8U,4)
#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n))

#define CV_8SC1 CV_MAKETYPE(CV_8S,1)
#define CV_8SC2 CV_MAKETYPE(CV_8S,2)
#define CV_8SC3 CV_MAKETYPE(CV_8S,3)
#define CV_8SC4 CV_MAKETYPE(CV_8S,4)
#define CV_8SC(n) CV_MAKETYPE(CV_8S,(n))

#define CV_16UC1 CV_MAKETYPE(CV_16U,1)
#define CV_16UC2 CV_MAKETYPE(CV_16U,2)
#define CV_16UC3 CV_MAKETYPE(CV_16U,3)
#define CV_16UC4 CV_MAKETYPE(CV_16U,4)
#define CV_16UC(n) CV_MAKETYPE(CV_16U,(n))

#define CV_16SC1 CV_MAKETYPE(CV_16S,1)
#define CV_16SC2 CV_MAKETYPE(CV_16S,2)
#define CV_16SC3 CV_MAKETYPE(CV_16S,3)
#define CV_16SC4 CV_MAKETYPE(CV_16S,4)
#define CV_16SC(n) CV_MAKETYPE(CV_16S,(n))

#define CV_32SC1 CV_MAKETYPE(CV_32S,1)
#define CV_32SC2 CV_MAKETYPE(CV_32S,2)
#define CV_32SC3 CV_MAKETYPE(CV_32S,3)
#define CV_32SC4 CV_MAKETYPE(CV_32S,4)
#define CV_32SC(n) CV_MAKETYPE(CV_32S,(n))

#define CV_32FC1 CV_MAKETYPE(CV_32F,1)
#define CV_32FC2 CV_MAKETYPE(CV_32F,2)
#define CV_32FC3 CV_MAKETYPE(CV_32F,3)
#define CV_32FC4 CV_MAKETYPE(CV_32F,4)
#define CV_32FC(n) CV_MAKETYPE(CV_32F,(n))

#define CV_64FC1 CV_MAKETYPE(CV_64F,1)
#define CV_64FC2 CV_MAKETYPE(CV_64F,2)
#define CV_64FC3 CV_MAKETYPE(CV_64F,3)
#define CV_64FC4 CV_MAKETYPE(CV_64F,4)
#define CV_64FC(n) CV_MAKETYPE(CV_64F,(n))

#define CV_16FC1 CV_MAKETYPE(CV_16F,1)
#define CV_16FC2 CV_MAKETYPE(CV_16F,2)
#define CV_16FC3 CV_MAKETYPE(CV_16F,3)
#define CV_16FC4 CV_MAKETYPE(CV_16F,4)
#define CV_16FC(n) CV_MAKETYPE(CV_16F,(n))
//! @}

//! @name Comparison operation
//! @sa cv::CmpTypes
//! @{
#define CV_HAL_CMP_EQ 0
#define CV_HAL_CMP_GT 1
#define CV_HAL_CMP_GE 2
#define CV_HAL_CMP_LT 3
#define CV_HAL_CMP_LE 4
#define CV_HAL_CMP_NE 5
//! @}

//! @name Border processing modes
//! @sa cv::BorderTypes
//! @{
#define CV_HAL_BORDER_CONSTANT 0
#define CV_HAL_BORDER_REPLICATE 1
#define CV_HAL_BORDER_REFLECT 2
#define CV_HAL_BORDER_WRAP 3
#define CV_HAL_BORDER_REFLECT_101 4
#define CV_HAL_BORDER_TRANSPARENT 5
#define CV_HAL_BORDER_ISOLATED 16
//! @}

//! @name DFT flags
//! @{
#define CV_HAL_DFT_INVERSE        1
#define CV_HAL_DFT_SCALE          2
#define CV_HAL_DFT_ROWS           4
#define CV_HAL_DFT_COMPLEX_OUTPUT 16
#define CV_HAL_DFT_REAL_OUTPUT    32
#define CV_HAL_DFT_TWO_STAGE      64
#define CV_HAL_DFT_STAGE_COLS    128
#define CV_HAL_DFT_IS_CONTINUOUS 512
#define CV_HAL_DFT_IS_INPLACE 1024
//! @}

//! @name SVD flags
//! @{
#define CV_HAL_SVD_NO_UV    1
#define CV_HAL_SVD_SHORT_UV 2
#define CV_HAL_SVD_MODIFY_A 4
#define CV_HAL_SVD_FULL_UV  8
//! @}

//! @name Gemm flags
//! @{
#define CV_HAL_GEMM_1_T 1
#define CV_HAL_GEMM_2_T 2
#define CV_HAL_GEMM_3_T 4
//! @}

//! @}

#endif

创建 Mat 对象

  1. 通过读入一张图像,直接转换为Mat对象
  2. 使用无参数构造函数,创建Mat对象
  3. 使用行、列、类型带这个三个参数的构造函数创建Mat对象
  4. 使用行、列、类型、Scalar向量四个参数的构造函数创建Mat对象
  5. 使用大小、类型两个参数的构造函数创建Mat对象
  6. 使用大小、类型、Scalar向量三个参数的构造函数创建Mat对象
  7. 使用Mat::zeros函数实现,两个参数一个是Size表示图像宽与高另外一个表示类型
  8. 使用Mat::ones函数实现,两个参数一个是Size表示图像宽与高,另外一个表示类型
    // 创建mat对象
    Mat t1 = Mat(256, 256, CV_8UC3);
    // Scalar(...) 是一个标量,表示一个颜色值
    // 灰度图像是一个通道的,一个参数就可以
    t1 = Scalar(0, 0, 255);
    imshow("t1", t1);

    // 方法2
    Mat t2 = Mat(Size(512, 512), CV_8UC3);
    t2 = Scalar(255, 0, 255);
    imshow("t2", t2);

    // 创建时指定大小
    Mat t3 = Mat::zeros(Size(256, 256), CV_8UC3);
    imshow("t3", t3);

    // 从现有的图像create
    // 只是对象引用的赋值,本质上还是一张图像
    // 如果对原图像进行修改,t4也会被修改
    Mat t4 = src; 
    // 克隆,是一个新的对象
    // 对原图进行修改,t5并不改变
    Mat t5 = src.clone();
    imshow("t5", t5);

    // 拷贝
    Mat t6;
    src.copyTo(t6);
    imshow("t6", t6);

    // 创建一个和现有图像大小、类型一样的空白图像
    Mat t7 = Mat::zeros(src.size(), src.type());

Mat 像素信息遍历

    /*
    for (int row = 0; row < height; row++) {
        for (int col = 0; col < width; col++) {
            if (dim == 3) {
                Vec3b pixel = src.at(row, col);
                int blue = pixel[0];
                int green = pixel[1];
                int red = pixel[2];
                src.at(row, col)[0] = 255 - blue;
                src.at(row, col)[1] = 255 - green;
                src.at(row, col)[2] = 255 - red;
            }
            if (dim == 1) {
                int pv = src.at(row, col);
                src.at(row, col) = (255 - pv);
            }
        }
    }
    imshow("fan", src);
    */

    // 指针方式遍历,并拷贝图像
    Mat result = Mat::zeros(src.size(), src.type());
    for (int row = 0; row < height; row++) {
        uchar* curr_row = src.ptr(row);
        uchar* result_row = result.ptr(row);
        for (int col = 0; col < width; col++) {
            if (dim == 3) {
                int blue = *curr_row++;
                int green = *curr_row++;
                int red = *curr_row++;

                *result_row++ = blue;
                *result_row++ = green;
                *result_row++ = red;
            }
            if (dim == 1) {
                int pv = *curr_row++;
                *result_row++ = pv;
            }
        }
    }
    imshow("src", src);

Mat对象起源

当OpenCV 1.0发布时候没有Mat对象,是个C语言风格的数据结构IPlImage来表示内存中图像对象,但是OpenCV开发者在做复杂图像处理算法分析与计算时候,创建了很多IplImage这样的数据结构,偶尔最后可能忘记释放内存了,这样算法就有了内存泄漏,导致开发者浪费很多精力去寻找这个错误,这个已经跟图像处理算法没有关系了,但是它却困扰了很多OpenCV开发者。Intel发现自己做的库居然这么渣,广大群众不满意,决定从OpenCV 2.0开始使用一个新的内存对象Mat来表示内存中的图像对象。它是C++风格的数据结构,自动实现内存分配与回收,这样OpenCV开发者就再也不用担心因为使用OpenCV的图像对象数据结构而导致内存泄漏问题了。但是仍然有些开发者直到现在还在顽固的使用IplImage这个对象,Intel为了照顾他们,所以允许IplImage对象继续存在,还提供可以把IplImage对象转换成Mat对象的构造函数,作为开源SDK可谓仁至义尽。

你可能感兴趣的:(opencv:Mat对象)