slambook2+ch5+图像基本操作(读取像素)

代码

#include 
#include 

using namespace std;

#include 
#include 
#include 

int main(int argc, char **argv) {
    cv::Mat image;

    //image = cv::imread(argv[1]);
    image = cv::imread("/home/automobile/wcm/slambook2/ch5/ubuntu.png");

    if (image.data == nullptr){
        cerr << "文件不存在" << endl;
        return 0;
    }

    cout << "图像宽为 " << image.cols << ", 高为 " << image.rows
        << ", 通道数为 " << image.channels() << endl;
    cv::imshow("image_原图", image);
    cv::waitKey(0);

    //判断image类型
    if (image.type() != CV_8UC1 && image.type() != CV_8UC3){
        //图像类型不符合输入要求
        cout << "请输入一张彩色或灰度图." << endl;
        return 0;
    }

    //遍历图像,请注意以下遍历方式也可用于随机像素的访问
    chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
    for (std::size_t y = 0; y < image.rows; y++){
        unsigned char *row_ptr = image.ptr<unsigned char>(y);   //row_ptr是第y行的头指针
        for(std::size_t x = 0; x < image.cols; x++){
            //访问位于x,y处的像素
            unsigned char *data_ptr = &row_ptr[x * image.channels()];   //data_ptr指向待访问的像素数据
            //输出该像素的每个通道,如果是灰度图,只有一个通道
            for (int c = 0; c != image.channels(); c++) {
                unsigned char data = data_ptr[c];   //data为I(x,y)的第C个通道的值
            }
        }

    }

    chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
    chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);
    cout <<"遍历图像用时: " << time_used.count() << "秒." << endl;


    //读取图像像素
    for (std::size_t y = 100; y < 102; y++){
        unsigned char *row_ptr = image.ptr<unsigned char>(y);   //row_ptr是第y行的头指针
        for(std::size_t x = 900; x < 902; x++){
            //访问位于x,y处的像素
            //data_ptr指向待访问的像素数据
            //row_ptr为像素行的头指针
            //【x * chaaannels()】为头指针row_ptr开拓空间,使得row_ptr有足够的空间存储像素
            unsigned char *data_ptr = &row_ptr[x * image.channels()];  
            
           cout << "data_ptr  = " << (int) (*(data_ptr))  << endl;
            cout << "data_ptr + 1  = " << (int) (*(data_ptr + 1))  << endl;
            cout << "data_ptr + 2 = " << (int) (*(data_ptr + 2))  << endl;

            //输出该像素的每个通道,如果是灰度图,只有一个通道
            for (int c = 0; c != image.channels(); c++) {
                unsigned char data = data_ptr[c];   //data为I(x,y)的第C个通道的值
               cout << "data = " << (int)data << endl;

            }
        }
    }

    //关于cv::Mat 的拷贝
    //直接赋值并不会拷贝数据
    cv::Mat image_another = image;
    //修改image_another会导致image发生变化
    image_another(cv::Rect(0, 0, 100, 100)).setTo(0);   //将左上角100*100的块置0
    cv::imshow("image_原图直接赋值给image_another", image);

    //使用clone函数拷贝数据
    cv::Mat image_clone = image.clone();
    image_clone (cv::Rect(0, 0, 100, 100)).setTo(255);
    cv::imshow("image_原图_1", image);
    cv::imshow("image_clone_使用clone函数拷贝图像并赋给image_clone", image_clone);
    cv::waitKey(0);

   cv::destroyAllWindows();

    std::cout << "Hello, World!" << std::endl;
   
    return 0;
}

slambook2+ch5+图像基本操作(读取像素)_第1张图片slambook2+ch5+图像基本操作(读取像素)_第2张图片slambook2+ch5+图像基本操作(读取像素)_第3张图片

slambook2+ch5+图像基本操作(读取像素)_第4张图片分析
访问图片像素

  1. 确定图片像素的行指针
  2. 为行指针数组拓展(列数*图像通道)的空间,便于存储像素信息
  3. 输出每个通道的像素值

浅拷贝

  1. 通过图片赋值,改变image_another原图像image也被改变了
  2. 通过图片clone,改变image_clone原图像image不变

你可能感兴趣的:(slambook)