opencv构造Mat方法及其访问图像中的像素

1.构造Mat:

#include <stdio.h>
#include<sstream>
#include <string>  
#include <iostream>  
#include <cstdlib>
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main() {
    //1.使用Mat类的create成员函数创建Mat
    cv::Mat M0;
    M0.create(4, 4, CV_8UC3);//M矩阵的元素默认初始化为205;
    cout << "m0=" << M0 << endl;
    //2.使用Mat构造函数初始化,可以不指定初始值
    cv::Mat M1(cv::Size(5, 5), CV_8UC1); // 单通道 a矩阵的元素默认初始化为205;
    cv::Mat M2 = cv::Mat(cv::Size(5, 5), CV_8UC3); //3通道每个矩阵元素包含3个uchar值
    cout << "m1  = " << endl << M1 << endl << endl;
    cout << "m2  = " << endl << M2 << endl << endl;
    //3.使用Mat构造函数初始化M时指定初始值
    Mat M3 = cv::Mat(3, 3, CV_8UC3, Scalar(5, 100, 200));
    cout << "m3  = " << endl << M3 << endl << endl;
    //4.Matlab式初始化方式
    Mat M4 = cv::Mat::zeros(Size(5, 5), CV_8UC1);
    Mat M5= cv::Mat::ones(Size(5, 5), CV_8UC1);
    Mat M6= cv::Mat::eye(Size(5, 5), CV_64FC1);
    cout << "m3  = " << endl << M4 << endl << endl;
    cout << "m4  = " << endl << M5 << endl << endl;
    cout << "m5  = " << endl << M6 << endl << endl;
    //5.随意给M矩阵赋值
    Mat M7 = (Mat_<double>(3, 3) << 1, 2, 3, 7, 8, 9, 4, 5, 6);
    cout << "m7  = " << endl << M7 << endl << endl;
    Mat Rowclone = M7.row(1).clone();
    cout << "Rowclone  = " << endl << Rowclone << endl;
    //6.使用随机数构造任意矩阵
    Mat r = Mat(10, 3, CV_8UC3);
    randu(r, Scalar::all(0), Scalar::all(255));
    cout <<"r="<< r << endl << endl;

    system("pause");
    return 0;
}

2.访问图像中的元素案例-图像反色:

#include <stdio.h>
#include<sstream>
#include <string>  
#include <iostream>  
#include <cstdlib>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
//Vec的表示----Vec2b,Vec3b,Vec2s, Vec3s
//(1)Vec2b—表示每个Vec2b对象中, 存储2个char(字符型)数据
//typedef Vec<uchar, 2> Vec2b; 、
//(2)Vec3b—表示每一个Vec3b对象中, 存储3个char(字符型)数据, 比如用这样的对象, 去存储RGB图像中的一个像素点
//typedef Vec<uchar, 3> Vec3b;
//(3)Vec4b—表示每一个Vec4b对象中, 存储4个字符型数据, 用这样的类对象去存储—4通道RGB + Alpha的图像中的像素点
//typedef Vec<uchar, 4> Vec4b;
//(4)Vec2s—表示这个类的每一个类对象,存储2个short int(短整型)的数据
//typedef Vec<short, 2> Vec2s;
//typedef Vec<short, 3> Vec3s;
//typedef Vec<short, 4> Vec4s;
//
//Vec的表示—Vec3b Vec3f
//8U 类型的 RGB 彩色图像可以使用Vec3b
//3 通道 float 类型的矩阵可以使用Vec3f
//对于 Vec 对象,可以使用[] 符号如操作数组般读写其元素,
//
//Vec3b color; //用 color 变量描述一种 RGB 颜色
//color[0] = 255; //0通道的B 分量
//color[1] = 0; //1通道的G 分量
//color[2] = 0; //2通道的R 分量
//1.使用M.at(i,j)访问图像中的像素
void InverseColor1(Mat src, Mat dst) {
    int dims = src.channels();
    for (int row = 0; row < src.rows; row++) {
        for (int col = 0; col < src.cols; col++) {
            if (dims == 1)
            {
                /* saturate_cast<uchar>主要是为了防止颜色溢出操作
                原理大致如下
                    if (data < 0)
                        data = 0;
                elseif(data > 255)
                    data = 255;*/
                dst.at<uchar>(row, col) = saturate_cast<uchar>(255 - src.at<uchar>(row, col));
            }
            if (dims == 3) {
                dst.at<cv::Vec3b>(row, col)[0] = 255 - src.at<cv::Vec3b>(row, col)[0];//0、1、2分别表示B、G、R
                dst.at<cv::Vec3b>(row, col)[1] = 255 - src.at<cv::Vec3b>(row, col)[1];
                dst.at<cv::Vec3b>(row, col)[2] = 255 - src.at<cv::Vec3b>(row, col)[2];
            }
        }
    }
}
//2.0使用指针ptr<>(row)访问图像中的像素
void InverseColor2(Mat src) { 
    int rows = src.rows;
    int cols = src.cols;
    int nSteps = src.cols * src.channels();
    for (int i = 0; i < rows; i++) {
        uchar* pStarsrc = src.ptr<uchar>(i);     
        for (int j = 0; j < nSteps;j++) {
            pStarsrc[j] = saturate_cast<uchar>(255 - pStarsrc[j]);
        }
    }
}
//2.1 使用指针ptr<>(row)访问图像中的像素另一种写法
void InverseColor2_1(Mat src) {    
    int height = src.rows;
    int width = src.cols;
    int dims = src.channels();
    for (int row = 0; row < height; ++row)
    {
        if (dims == 1) {
            uchar* current_row = src.ptr<uchar>(row);
            for (int col = 0; col < width; ++col)
            {
                *current_row++ = 255 - *current_row;//current_row[]数组的首地址,每行第一个像素
            }
        }
            if (dims == 3)
            {
                Vec3b *current_row = src.ptr<Vec3b>(row);
                for (int col = 0; col < width; ++col)
                {
                    (*current_row)[0]= 255 - (*current_row)[0];
                    (*current_row)[1] = 255 - (*current_row)[1];
                    (*current_row)[2]= 255 - (*current_row)[2];
                    *current_row++;
                }
            }
        }
    }
//2.2使用指针ptr<>(row)反转图像中的像素
void InverseColor2_2(Mat src) {  
    
    int dims = src.channels();
    for (int row = 0; row < src.rows; row++)
    {
        for (int col = 0; col < src.cols; col++)
        {
            if (dims == 1) { 
                uchar* pData = src.ptr<uchar>(row, col);
                *pData = 255 - *pData;
            }
            if (dims == 3) {
                Vec3b* pData = src.ptr<Vec3b>(row, col);//彩图
                (*pData)[0] = 255 - (*pData)[0];
                (*pData)[1] = 255 - (*pData)[1];
                (*pData)[2] = 255 - (*pData)[2];
            }
          
        }
    }
}
//3.使用MatIterator迭代器
void InverseColor3(Mat src, Mat dst) {
    if (src.channels() == 1) {
        MatIterator_<uchar>srcbeg, srcend, dstbeg, dstend;
        srcbeg = src.begin<uchar>();
        srcend = src.end<uchar>();
        dstbeg = dst.begin<uchar>();
        dstend = dst.end<uchar>();
        while (srcbeg != srcend) {
            (*dstbeg) = 255 - (*srcbeg);           
            srcbeg++;
            dstbeg++;
        }
    }
    if(src.channels()==3){
     MatIterator_<Vec3b>srcbeg, srcend, dstbeg, dstend;
    srcbeg = src.begin<Vec3b>();
    srcend = src.end<Vec3b>();
    dstbeg = dst.begin<Vec3b>();
    dstend = dst.end<Vec3b>();
    while(srcbeg!=srcend) {
        (*dstbeg)[0] = 255-(*srcbeg)[0];
        (*dstbeg)[1] = 255 - (*srcbeg)[1];
        (*dstbeg)[2] = 255 - (*srcbeg)[2];
        srcbeg++;
        dstbeg++;
    }
    }
}
//4.利用LUT查表法,opencv中LUT函数如下:
//void LUT(InputArray src, InputArray lut, OutputArray dst);
//src表示的是输入图像(可以是单通道也可是3通道)
//lut表示查找表(查找表也可以是单通道,也可以是3通道,如果输入图像为单通道,那查找表必须为单通道,若输入图像为3通道,
// 查找表可以为单通道,也可以为3通道,若为单通道则表示对图像3个通道都应用这个表,若为3通道则分别应用 )
//dst表示输出图像
void InverseColor4(Mat src, Mat dst) { 
    if (src.channels() == 1) {
        uchar LutTable[256];
        for (int i = 0; i < 256; ++i)
        {
            LutTable[i] = 255 - i;
        }
        Mat lookUpTable(1, 256, CV_8UC1, LutTable);
        //uchar* pData = lookUpTable.data;
         建立映射表
        //for (int i = 0; i < 256; ++i)
        //{
        //    pData[i] = LutTable[i];
        //}
        // 应用索引表进行查找
       cv:: LUT(src, lookUpTable, dst);
    }
    if (src.channels() == 3) {
        // 建立LUT 反色table
        uchar LutTable[256 * 3];
        for (int i = 0; i < 256; ++i)
        {
            LutTable[i * 3] = 255 - i;
            LutTable[i * 3 + 1] = 255 - i;
            LutTable[i * 3 + 2] = 255 - i;
        }
        Mat lookUpTable(1, 256, CV_8UC3, LutTable);
        // 应用索引表进行查找
       cv:: LUT(src, lookUpTable, dst);
    }
}

//5.使用data结合step访问图像像素,成员函数step是返回该Mat对象一行所占的数据字节数。
//成员函数data:uchar类型的指针,指向Mat数据矩阵的首地址
void InverseColor5(Mat src) {//该函数有问题
    uchar* pData = src.data;
    MatStep mst = src.step;
    for (int row = 0; row < src.rows; row++)
    {
        for (int col = 0; col < src.cols; col++)
        {
            *(pData + row * mst + col * src.channels() + 0) = 255 - *(pData + row * mst + col * src.channels() + 0);
            *(pData + row * mst + col * src.channels() + 1) = 255 - *(pData + row * mst + col * src.channels() + 1);
            *(pData + row * mst + col * src.channels() + 2) = 255 - *(pData + row * mst + col * src.channels() + 2);
        }
    }
}

int main() 
{
    Mat srcImage, srcImg,srcs;
    srcImage = imread("E:\\vs2019wenjian\\Cpptest\\data\\face.png");    //原图
    cvtColor(srcImage, srcImg, COLOR_BGR2GRAY);   //转化为灰度图
    cv::imwrite("E:\\vs2019wenjian\\Cpptest\\data\\test04.jpg", srcImg);
    if (srcImage.empty())
    {
        cout << "can not load image" << endl;
        return -1;
    }
  //  InverseColor2(srcImage);
 /*   InverseColor2_1(srcImage);
    InverseColor2_1(srcImg);*/
  InverseColor1(srcImage,srcImage);
  InverseColor1(srcImg,srcImg);
 /*   uchar lutData[256];
    for (int i = 0; i < 256; i++)
    {
        if (i <= 100)
            lutData[i] = 0;
        if (i > 100 && i <= 200)
            lutData[i] = 100;
        if (i > 200)
            lutData[i] = 255;
    }
    Mat lut(1, 256, CV_8UC1, lutData);
    LUT(srcImg, lut, b);*/
    cv::imwrite("E:\\vs2019wenjian\\Cpptest\\data\\test02.jpg",srcImage);
    cv::imwrite("E:\\vs2019wenjian\\Cpptest\\data\\test03.jpg", srcImg);   
    std:: system("pause");
    return 0;
}

图像反色的结果如图:
实验结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值