Как получить данные пикселей в виде матрицы / вектора в CImg? - PullRequest
0 голосов
/ 02 июля 2018

Мне нужно прочитать изображение в оттенках серого в формате png, чтобы значения пикселей (0-255) сохранялись в двумерной матрице беззнаковых символов. В настоящее время я использую CImg в C ++, который успешно читает изображение, но я не мог понять, как получить данные пикселей из контейнера CImg.

Я могу сделать это:

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

но он дает мне символ *, который, согласно документации, является "указателем на первое значение изображения", но я не знаю, что с ним делать или как получить доступ к другим значениям.

Какие-нибудь советы по этому поводу?

Спасибо, David

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Не уверен, почему вы захотите скопировать все данные из структуры / класса CImg в другой двумерный массив, если вы в любом случае можете получить к нему доступ именно так. Итак, если вы хотите, чтобы пиксель находился в местоположении [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 (Portable Grey Map), чтобы вы могли легко видеть значения пикселей, но оно точно такое же с 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
0 голосов
/ 02 июля 2018

Там действительно много возможностей сделать это.

  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));
    }
    

Согласно документам :

Size () возвращает width () * height () * deep () * 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);
    }
    

Или, если вы хотите попробовать что-то еще, просмотрите документацию, примеры, которые я привел, не являются исчерпывающими.

...