Как я могу просто загрузить tiff в оттенках серого в libtiff и получить массив интенсивностей пикселей?

Я пытаюсь лучше понять образы, и у меня большие проблемы. Благодаря использованию Matlab у меня есть опыт использования imread('test.tif') и получения красивой матрицы строк и столбцов, где у вас есть интенсивность каждого пикселя как целое число. Итак, изображение 720 x 250 даст матрицу 720 x 250, где каждая ячейка содержит интенсивность пикселя по шкале от 0 до 255 (в зависимости от типа данных). Итак, 0 — черный, 255 — белый.

Это было так просто и имело такой смысл. Теперь я пытаюсь использовать libtiff, и я действительно борюсь. Я хочу сделать то же самое — получить доступ к этим пикселям, но не могу.

У меня есть следующий код:

int main(int argc, char *argv[]){
  TIFF* tif = TIFFOpen( argv[1], "r");
    FILE *fp = fopen("test2.txt", "w+");

  if (tif) {
      int * buf;
      tstrip_t strip;
      uint32* bc;
      uint32 stripsize;
  TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &bc);
  stripsize = bc[0];
  buf   = _TIFFmalloc(stripsize);
  for(strip = 0; strip < TIFFNumberOfStrips(tif); strip++ ) {
      if( bc[strip] > stripsize) {
          buf = _TIFFrealloc(buf, bc[strip]);
          stripsize = bc[strip];
      }
      TIFFReadRawStrip(tif, strip, buf, bc[strip]);
  }
  int i;
  for (i=0; i<stripsize; i++) {
      if ( i % 960 ==0 )
          fprintf(fp, "\n");
      fprintf(fp,"%d ",  buf[i]);
  }
  _TIFFfree(buf);
  TIFFClose(tif);
  }
  exit(0);
}

Но я получаю совершенно бессмысленные результаты — просто полностью выбитые числа. Ничего похожего на цифры, которые я вижу, когда загружаю изображение в Matlab.

Как я могу просто получить доступ к значениям пикселей и посмотреть на них?

Большое спасибо.


person The_Anomaly    schedule 29.03.2011    source источник
comment
Я никогда не использовал libtiff, но похоже, что вы читаете необработанные данные изображения. Формат файла Tiff может содержать необработанные данные изображения, а также сжатые форматы. Так что, возможно, данные все еще сжаты.   -  person Lucas    schedule 30.03.2011
comment
Начните с того, что обратите внимание на возвращаемое значение этих функций. Вы понятия не имеете, вышла ли функция из строя или нет.   -  person Hans Passant    schedule 30.03.2011


Ответы (3)


Думаю, вам следует прочитать статью об использовании библиотеки TIFF. Он содержит достаточно информации для начала работы с libtiff.

Вот некоторый код для чтения строк сканирования изображения и печати значений каждого образца.

main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
        uint32 imagelength;
        tsize_t scanline;
        tdata_t buf;
        uint32 row;
        uint32 col;

        TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
        scanline = TIFFScanlineSize(tif);
        buf = _TIFFmalloc(scanline);
        for (row = 0; row < imagelength; row++)
        {
            TIFFReadScanline(tif, buf, row);
            for (col = 0; col < scanline; col++)
                printf("%d ", buf[col]);

            printf("\n");
        }
        _TIFFfree(buf);
        TIFFClose(tif);
    }
}
person Bobrovsky    schedule 30.03.2011
comment
ошибка: слишком мало аргументов для функции «TIFFReadScanline» - person malat; 04.02.2015
comment
@ЭдС. Пожалуйста, определите «значение по умолчанию для последнего аргумента» для функции C. Также откройте в оболочке справочную страницу: $ man TIFFReadScanline - person malat; 21.08.2017
comment
@malat: Я помню, как некоторое время назад оставлял здесь комментарий, но сейчас его, похоже, нет. В любом случае ... Бобровский использует здесь C ++, а OP использует C. Думаю, я не ясно выразил это в своем ныне несуществующем комментарии. Вот объявление, если c_plusplus || __cplusplus определено: extern int TIFFReadScanline(TIFF* tif, void* buf, uint32 row, uint16 sample = 0); - person Ed S.; 22.08.2017

Что касается этой статьи, я думаю, что будет лучше использовать подход TIFFRGBAImage, потому что, как оказалось, файл TIFF может быть одного из разных форматов: мозаичный, на основе строки сканирования и ориентированный на полосу. Вот пример из той же статьи.

TIFF* tif = TIFFOpen(argv[1], "r");
if (tif) {
    uint32 w, h;
    size_t npixels;
    uint32* raster;

    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
    npixels = w * h;
    raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
    if (raster != NULL) {
        if (TIFFReadRGBAImage(tif, w, h, raster, 0)) {
            ...process raster data...
        }
        _TIFFfree(raster);
    }
    TIFFClose(tif);
}
person kmityak    schedule 26.05.2012

растр представляет собой массив uint32 (максимальное значение = 0xffffffff), но вы пытаетесь прочитать 16-битный массив (максимальное значение 0xffff). вы столкнетесь с проблемами преобразования 32-бит в 16-бит. Чтение метода сканирования - лучший способ сделать это. Таким образом, вы можете преобразовать void* buf в uint16* и получить доступ к значениям пикселей.

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <inttypes.h>
#include "tiffio.h"


using namespace std;


void printArray(uint16 * array, uint16 width);
int main()
{


    TIFF* tif = TIFFOpen("16bit_grayscale_image.tif", "r");
     if (tif) {
    uint32 imagelength,height;
    tdata_t buf;
    uint32 row;
    uint32 config;

    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
    TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &config);
    buf = _TIFFmalloc(TIFFScanlineSize(tif));


        uint16 s, nsamples;
        uint16* data;
        TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &nsamples);
        for (s = 0; s < nsamples; s++)
        {
            for (row = 0; row < imagelength; row++)
                {
                TIFFReadScanline(tif, buf, row, s);
                data=(uint16*)buf;
                printArray(data,imagelength);
                }
                // printArray(data,imagelength,height);
        }


    _TIFFfree(buf);
    TIFFClose(tif);
    }
    exit(0);
}



void printArray(uint16 * array, uint16 width)
{
    uint32 i;
    for (i=0;i<width;i++)
    {
        printf("%u ", array[i]);
    }
        printf("\n");


}
person Nehad Hirmiz    schedule 24.11.2013