Mat数据格式

1 row、col 和 x、y 的关系

  • rows:表示图像有多少行
  • cols: 表示图像有多少列
  • heigh: 高度
  • width: 宽度

关系:

rows == heigh == Point.y
cols == width == Point.x
Mat::at(Point(x, y)) == Mat::at(y,x)

2 创建Mat图像

//创建Mat图像(像素值自定义)
    Mat MM(5, 5, CV_8UC1, Scalar(128,0,0));// 参数(int rows, int cols, int type, const Scalar& s)
    cout << "MM = " << endl << " " << MM << endl;
 
    //创建Mat图像(像素值205)
    Mat MC;
    MC.create(5, 5, CV_8UC1);
    cout << "MC = "<< endl << " "  << MC << endl;
 
    //创建Mat图像(像素值单位矩阵)
    Mat E = Mat::eye(5, 5, CV_8UC1);
    cout << "E = " << endl << " " << E << endl;
 
    //创建Mat图像(像素值全1矩阵)
    Mat O = Mat::ones(5, 5, CV_32FC1);
    cout << "O = " << endl << " " << O << endl;
 
    //创建Mat图像(像素值全0矩阵)
    Mat Z = Mat::zeros(5, 5, CV_64FC1);
    cout << "Z = " << endl << " " << Z << endl;

3 读写Mat数据

    cv::Mat mat = ...;
    mat.at<cv::Vec3b>(0, 3)[3] = 0;
	
    std::cout << mat.rows << std::endl;//行数
    std::cout << mat.cols << std::endl;//列数
    std::cout << mat.channals() << std::endl;//通道数

4 遍历Mat数据

at 的方式:

    int i;
    for (int m = 0; m < mat.cols; m++) {
        for (int n = 0; n < mat.rows; n++) {
            for (int c = 0; c < mat.channels(); c++) {
                //Vec3b:表示mat的向量格式,也就是读写的数据格式,这里表示一个像素有3个byte;
                i = mat_RGB.at<cv::Vec3b>(n, m)[c];
            }
            // 若为单通道
            // i = mat_RGB.at<cv::Vec3b>(n, m);
        }
    }

ptr 的方式(效率更高):

    for (int i =0; i < img.rows; ++i) {
        const int * ptr = img.ptr<int>(i);
        for (int j = 0; j < img.cols * img.channels(); ++j) {
            int data = ptr[j];
        }
    }

5 图片 0-1 和 0-255 的转换

    // 0~255 -> 0~1
    img.convertTo(img, CV_32F, 1.0/255);
 
    // 0~1 -> 0~255
    color.convertTo(color, CV_8U, 255);

6 改变 Mat 尺寸

    // img1是输入图像,img2是输出图像,后面那个是尺寸
    cv::resize(img1, imgc2, cv::Size(500,311));

7 读取 Mat 类型

参考这里

myMat = imread("C:\someimage.jpg");
int type = myMat.type();

返回的类型是个数字,数字的含义可以在下面表格中查找:

-C1C2C3C4C5C6C7C8
CV_8U08162432404856
CV_8S19172533414957
CV_16U210182634425058
CV_16S311192735435159
CV_32S412202836445260
CV_32F513212937455361
CV_64F614223038465462

C1~C8是通道数,CV_8U ~ CV_64F是图像的数据格式;

8 色彩空间的转换

//将RGB格式的图像转换成BGR格式
cvtColor(RGB_image, BGR_image, COLOR_RGB2BGR);
//将BGR格式的图像转换成灰度图
cvtColor(BGR_imgage, gray_image, COLOR_BGR2GRAY);
//将BGR格式的图像转换为BGRA
cvtColor(BGR_imgage, gray_image, COLOR_BGR2BGRA);
  • HSV六棱锥
    H参数表示色彩信息,即所处的光谱颜色的位置,用一角度量来表示;红绿蓝间隔隔120度,互补色分别相差180度;
    S纯度为一比例值,范围从0到1,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率,S=0时,只有灰度;
    V表示色彩的明亮程度,范围从0到1;有一点要注意:它和光强度之间并没有直接的联系。
pic pic pic
  • I420(YUV420P)
    相比于 RGB 格式,I420 所需要的物理内存更小,当然也有一定精度的损失。I420 格式的内存分布如下,y1 - y16 是图像的尺寸(w * h),也就是一副黑白图,u1 - u4 可以计算蓝色像素的分量,v1 - v4 可以计算红色像素的分量,YUV 和 RGB 的转换公式:

    R = Y + 1.403V
    G = Y - 0.344U - 0.714V
    B = Y + 1.770U
    
    y1y2y3y4
    y5y6y7y8
    y9y10y11y12
    y13y14y15y16
    u1u2u3u4
    v1v2v3v4

    可能会有一个疑问,为什么 U、V 的数量都是 Y 的 1 4 \frac{1}{4} 41 ?
    我们首先将 Y 的尺寸 (w * h) 全部划分为 (2*2) 小矩形,每一个小矩形(4像素)分别对应了一个 u、v,所以是 4 被倍关系。从内存分布上看,RGB 占用了 (w * h * 3) 的空间,而 YUV 占用了 (w * h * 1.5) 的空间,缩减了一半。注意:转换时需要划分为小矩形,所以图片的尺寸要求一定是偶数。

  • 420SP
    420SP 只是在 I420 的基础上改变了 U、V 的分布:

    y1y2y3y4
    y5y6y7y8
    y9y10y11y12
    y13y14y15y16
    u1v1u2v2
    u3v3u4v4

9 数据格式的转换

//将[0,1]范围内的浮点表示的图像转换成8bit整数表示的图像
float_image.convertTo(integer_image, CV_8U, 255.0);
 
convertTo函数定义如下:
/** @brief Converts an array to another data type with optional scaling.
 
    The method converts source pixel values to the target data type. saturate_cast\<\> is applied at
    the end to avoid possible overflows:
 
    \f[m(x,y) = saturate \_ cast<rType>( \alpha (*this)(x,y) +  \beta )\f]
    @param m output matrix; if it does not have a proper size or type before the operation, it is
    reallocated.
    @param rtype desired output matrix type or, rather, the depth since the number of channels are the
    same as the input has; if rtype is negative, the output matrix will have the same type as the input.
    @param alpha optional scale factor.
    @param beta optional delta added to the scaled values.
     */
    void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;

10 单通道转换为多通道

// 把传入的单通道灰度图转换为3通道RGB
cv::Mat convertTo3Channels(const cv::Mat& binImg)
{
    cv::Mat three_channel = cv::Mat::zeros(binImg.rows,binImg.cols,CV_8UC3);
    std::vector<cv::Mat> channels;
    for (int i=0;i<3;i++)
    {
        channels.push_back(binImg);
    }
    merge(channels,three_channel);
    return three_channel;
}

11 从多通道中分离单通道

cv::Mat img = ...;
std::vector<cv::Mat> channals[0]);
cv::split(img, channals);
cv::imshow("通道0", channals[0]);
cv::imshow("通道1", channals[1]);
cv::imshow("通道2", channals[2]);

12 Mat、QImage、QPixmap 之间的转换

:::details 头文件

#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
 
#include <imgproc/types_c.h>
#include <QtGui/QImage>
#include <QtWidgets/QFileDialog>
 
cv::Mat QImage2cvMat(QImage image);
cv::Mat QPixmapcvMat(QPixmap image);
 
QImage cvMat2QImage(const cv::Mat& mat);
QPixmap cvMat2QPixmap(const cv::Mat& mat);
 
QImage QPixmapQImage(QPixmap image);
QPixmap QImageQPixmap(QImage image);

:::

:::details c文件

#include "ImaRormConv.h"
 
cv::Mat QImage2cvMat(QImage image)
{
    cv::Mat mat;
    switch(image.format())
    {
    case QImage::Format_ARGB32:
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32_Premultiplied:
        mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
        break;
    case QImage::Format_RGB888:
        mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
        cv::cvtColor(mat, mat, CV_BGR2RGB);
        break;
    case QImage::Format_Indexed8:
        mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
        break;
    }
    return mat;
}
 
cv::Mat QPixmapcvMat(QPixmap image)
{
    QImage img = image.toImage();
    cv::Mat mat = QImage2cvMat(img);
    return mat;
}
 
QImage cvMat2QImage(const cv::Mat& mat)
{
    // 8-bits unsigned, NO. OF CHANNELS = 1
    if(mat.type() == CV_8UC1)
    {
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        // Set the color table (used to translate colour indexes to qRgb values)
        image.setColorCount(256);
        for(int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        // Copy input Mat
        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++)
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }
    // 8-bits unsigned, NO. OF CHANNELS = 3
    else if(mat.type() == CV_8UC3)
    {
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return image.rgbSwapped();
    }
    else if(mat.type() == CV_8UC4)
    {
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image.copy();
    }
    else
    {
        return QImage();
    }
}
QPixmap cvMat2QPixmap(const cv::Mat& mat)
{
    QImage img = cvMat2QImage(mat);
    QPixmap pix = QPixmap::fromImage(img);
    return pix;
}
 
QImage QPixmapQImage(QPixmap image)
{
    QImage img = image.toImage();
    return img;
}
 
QPixmap QImageQPixmap(QImage image)
{
    QPixmap pix = QPixmap::fromImage(image);
    return pix;
}

:::

13 Mat 和 Vector 互换

/***************** Mat转vector **********************/
template<typename _Tp>
vector<_Tp> convertMat2Vector(const Mat &mat)
{
    return (vector<_Tp>)(mat.reshape(1, 1));//通道数不变,按行转为一行
}
 
/****************** vector转Mat *********************/
template<typename _Tp>
cv::Mat convertVector2Mat(vector<_Tp> v, int channels, int rows)
{
    cv::Mat mat = cv::Mat(v);//将vector变成单列的mat
    cv::Mat dest = mat.reshape(channels, rows).clone();//channels是通道数,rows是行数,这里的.clone是防止下面的return出错
    return dest;
}
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV(Open Source Computer Vision Library)是一个广泛使用的计算机视觉库,提供了许多处理图像和视频的功能。在OpenCV中,Mat是一种常用的数据结构,用于存储和操作图像和矩阵数据。 Mat是一个多维数组,可以表示灰度图像、彩色图像、深度图像等。它由数据指针、行数、列数、通道数和其他一些元数据组成。 在OpenCV中,Mat的数据类型可以是8位、16位、32位浮点型或64位浮点型。对于灰度图像,通常使用单通道的Mat表示,而对于彩色图像,则使用3通道(BGR顺序)的Mat。 你可以通过以下代码创建一个Mat对象并访问其数据: ```cpp #include <opencv2/opencv.hpp> int main() { cv::Mat image; // 创建一个空的Mat对象 // 从文件加载图像 image = cv::imread("image.jpg"); // 访问图像数据 int rows = image.rows; // 获取图像的行数 int cols = image.cols; // 获取图像的列数 int channels = image.channels(); // 获取图像的通道数 // 遍历图像 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { // 访问像素值 cv::Vec3b pixel = image.at<cv::Vec3b>(i, j); // 对像素进行操作 pixel[0] = 255; // 修改蓝色通道值为255 // 更新像素值 image.at<cv::Vec3b>(i, j) = pixel; } } // 保存图像 cv::imwrite("modified_image.jpg", image); return 0; } ``` 这是一个简单的示例,展示了如何创建、加载、访问和保存图像数据。Mat对象的数据可以通过at()方法访问,其中指定了要访问的像素的行和列。对于彩色图像,可以使用Vec3b类型的对象来表示每个像素的值,其中每个通道的值由0到255的整数表示。 希望这能帮到你!如果还有其他问题,请随时问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值