【问题标题】:How to get pixel data as a matrix/vector in CImg?如何在 CImg 中将像素数据作为矩阵/向量获取?
【发布时间】:2018-07-03 00:29:44
【问题描述】:

我需要读取一个灰度 png 图像,以便将像素值 (0-255) 存储在无符号字符的二维矩阵中。 目前我在 C++ 中使用 CImg,它成功读取了图像,但我不知道如何从 CImg 容器中获取像素数据。

我可以这样做:

CImg<unsigned char> image("img1.png");
unsigned char* img1 = image.data();

但它给了我一个 char*,根据文档,它是“指向图像第一个值的指针”,但我不知道如何处理它,或者如何访问其他值。

对此有什么建议吗?

谢谢你, 大卫

【问题讨论】:

    标签: c++ matrix pixel cimg


    【解决方案1】:

    不确定为什么要将 CImg 结构/类中的所有数据复制到另一个 2D 数组中,但无论如何都可以访问它。因此,如果您想要位置 [x,y] 的像素,只需使用:

    img(x,y)
    

    这是一个转储图像的完整程序 - 访问内部循环中的单个像素:

    #include <iostream>
    #include <cstdlib>
    
    #define cimg_display 0
    #include "CImg.h"
    
    using namespace cimg_library;
    using namespace std;
    
    int main() {
        CImg<unsigned char> img("test.pgm");
    
        // Get width, height, number of channels
        int w=img.width();
        int h=img.height();
        int c=img.spectrum();
        cout << "Dimensions: " << w << "x" << h << " " << c << " channels" <<endl;
    
        // Dump all pixels
        for(int y=0;y<h;y++){
           for(int x=0;x<w;x++){
              cout << y << "," << x << " " << (int)img(x,y) << endl;
           }
        }
    }
    

    我使用了这张测试图像 - 它是 5x3 PGM(便携式灰度图),因此您可以轻松查看像素值,但它与 PNG 图像相同:

    P2
    5 3
    255
    0 1 2 3 4
    10 11 12 13 14
    100 101 102 103 104
    

    这是输出,你可以看到与图像匹配:

    Dimensions: 5x3 1 channels
    0,0 0
    0,1 1
    0,2 2
    0,3 3
    0,4 4
    1,0 10
    1,1 11
    1,2 12
    1,3 13
    1,4 14
    2,0 100
    2,1 101
    2,2 102
    2,3 103
    2,4 104
    

    【讨论】:

      【解决方案2】:

      这样做真的有很多可能性。

      1. 您可以使用您当前的方法,只需遍历原始像素数组:

        CImg<unsigned char> image("img1.png");
        unsigned char* img1 = image.data();
        for(int i=0; i < image.size(); i++) {
            logger_->info("*img1 value: {}", *(img1+i));
        }
        

      根据docs

      Size()返回width()*height()*depth()*spectrum(),即图像实例的像素缓冲区中T类型值的总数

      所以你也可以直接使用这些维度:

      1. 像这样:

        CImg<unsigned char> image("img1.png");
        unsigned char* img1 = image.data();
        for(int i=0; i < image.width()*image.height()*image.depth()*image.spectrum(); i++) {
            logger_->info("*img1 value: {}", *(img1+i));
        }
        

        这当然允许您编写嵌套循环,分别遍历每个维度。

      2. 如果你不喜欢遍历原始数组,你可以使用迭代器:

        CImg<unsigned char> image("img1.png");
        unsigned char* img1 = image.data();
        for (CImg<unsigned char>::iterator it = image.begin(); it < image.end(); ++it) {
            logger_->info("it value: {}", *it);
        }
        

      或者,如果您想尝试其他方法,请查看文档,我提供的示例并不详尽。

      【讨论】:

      • 好的,现在我明白了。我尝试了建议的两种方法,但是对于 ~10MP 图像,它们的速度非常慢。最初我想将它移动到另一个数组以使其更快,但由于无法直接复制数组,因此迭代速度要慢得多,并在每次迭代时更改向量大小......所以我会坚持使用 img(x,y) 访问方法
      • 当然有办法将数据复制到另一个数组:std::memcpy(dest, source, size);。我只是不知道你应该如何在复制后让它更快。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-12
      • 1970-01-01
      • 1970-01-01
      • 2023-01-02
      相关资源
      最近更新 更多