с плавающей запятой — может ли LibTIFF использоваться с C ++ для получения значений с плавающей запятой изображений?

Я читаю Вот этот LibTIFF может отображать TIFF с плавающей запятой. Тем не менее, я хотел бы загрузить изображение, а затем получить значения с плавающей точкой в ​​виде массива.

Можно ли это сделать с помощью LibTIFF?

РЕДАКТИРОВАТЬ: я использую RHEL 6.

РЕДАКТИРОВАТЬ: https://www.dropbox.com/s/f15fkkj5dg5ojzt/map.tif?dl=0

Извините за неправильную ссылку!

Ссылка на пример TIFF.

0

Решение

Если вы хотите сделать это с чистым LibTIFF, Ваш код может выглядеть примерно так: обратите внимание, что я не провел большую проверку ошибок, чтобы не запутать читателя кода, — но вы должны проверить, что изображение имеет тип float, и вы должны проверить результаты выделения памяти и вы, вероятно, не должны использовать malloc() как я делаю, а скорее новые методы распределения памяти C ++ — но концепция, надеюсь, ясна, и код генерирует те же ответы, что и мой CImg версия…

#include "tiffio.h"#include <cstdio>
#include <iostream>

using namespace std;

int main()
{

TIFF* tiff = TIFFOpen("image.tif","r");
if (!tiff) {
cerr << "Failed to open image" << endl;
exit(1);
}

uint32 width, height;
tsize_t scanlength;

// Read dimensions of image
if (TIFFGetField(tiff,TIFFTAG_IMAGEWIDTH,&width) != 1) {
cerr << "Failed to read width" << endl;
exit(1);
}
if (TIFFGetField(tiff,TIFFTAG_IMAGELENGTH, &height) != 1) {
cerr << "Failed to read height" << endl;
exit(1);
}

scanlength = TIFFScanlineSize(tiff);

// Make space for image in memory
float** image= (float**)malloc(sizeof (float*)*height);

cout << "Dimensions: " << width << "x" << height << endl;
cout << "Line buffer length (bytes): " << scanlength << endl;

// Read image data allocating space for each line as we get it
for (uint32 y = 0; y < height; y++) {
image[y]=(float*)malloc(scanlength);
TIFFReadScanline(tiff,image[y],y);
cout << "Line(" << y << "): " << image[y][0] << "," << image[y][1] << "," << image[y][2] << endl;
}
TIFFClose(tiff);

}

Пример вывода

Dimensions: 512x256
Line buffer length (bytes): 6144
Line(0): 3.91318e-06,0.232721,128
Line(1): 0.24209,1.06866,128
Line(2): 0.185419,2.45852,128
Line(3): 0.141297,3.06488,128
Line(4): 0.346642,4.35358,128
...
...

Кстати…

Я преобразовал ваше изображение в обычный JPEG с помощью ImageMagick в Терминале в командной строке:

convert map.tif[0] -auto-level result.jpg

введите описание изображения здесь

1

Другие решения

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

Вот как вы можете прочитать TIFF RGB-поплавков:

#define cimg_display 0
#define cimg_use_tiff
#include "CImg.h"#include <iostream>

using namespace cimg_library;
using namespace std;

int main(){

// Read in an image
CImg <float>img("image.tif");

// Get its width and height and tell user
int w=img.width();
int h=img.height();
cout << "Dimensions: " << w << "x" << h << endl;

// Get pointer to buffer/array of floats
float* buffer = img.data();

cout << buffer[0] << "," << buffer[1] << "," << buffer[2] << endl;
}

Это печатает первые три красных пикселя, потому что они расположены в плоскостях — то есть сначала все красные пиксели, затем все зеленые пиксели, а затем все синие пиксели.

Вы бы скомпилировали это с:

g++-6 -std=c++11 read.cpp -I/usr/local/include -L/usr/local/lib -ltiff -o read

Если вы предпочитаете, вы можете получить доступ к пикселям немного по-другому:

#define cimg_display 0
#define cimg_use_tiff
#include "CImg.h"#include <iostream>

using namespace cimg_library;
using namespace std;

int main(){

// Read in an image
CImg <float>img("image.tif");

// Get its width and height and tell user
int w=img.width();
int h=img.height();
cout << "Dimensions: " << w << "x" << h << endl;

// Dump the pixels
for(int y=0;y<h;y++)
for(int x=0;x<w;x++)
cout << x << "," << y << ": "<< img(x,y,0,0) << "/"<< img(x,y,0,1) << "/"<< img(x,y,0,2) << endl;

}

Пример вывода

Dimensions: 512x256
0,0: 3.91318e-06/0.232721/128
1,0: 1.06577/0.342173/128
2,0: 2.3778/0.405881/128
3,0: 3.22933/0.137184/128
4,0: 4.26638/0.152943/128
5,0: 5.10948/0.00773837/128
6,0: 6.02352/0.058757/128
7,0: 7.33943/0.02835/128
8,0: 8.33965/0.478541/128
9,0: 9.46735/0.335981/128
10,0: 10.1918/0.340277/128
...
...

Для вашей информации, я сделал файл тестового изображения также с CImg вот так — в основном каждый красный пиксель имеет свою координату х плюс небольшое случайное смещение менее 0,5. каждый зеленый пиксель имеет свою координату y плюс небольшое случайное значение с плавающей запятой менее 0,5, а каждый синий пиксель установлен на средний тон.

#define cimg_display 0
#define cimg_use_tiff
#define cimg_use_png
#include "CImg.h"#include <cstdlib>

using namespace cimg_library;

int main(){
const int w=512;
const int h=256;
const int channels=3;
float* buffer = new float[w*h*channels];
float* fp=buffer;
for(int y=0;y<h;y++){
for(int x=0;x<w;x++){
*fp++=x+float(rand())/(2.0*RAND_MAX);    // red
}
}
for(int y=0;y<h;y++){
for(int x=0;x<w;x++){
*fp++=y+float(rand())/(2.0*RAND_MAX);    // green
}
}
for(int y=0;y<h;y++){
for(int x=0;x<w;x++){
*fp++=128;    // blue
}
}

CImg <float>img(buffer,w,h,1,channels);
img.save_tiff("result.tif");
}

введите описание изображения здесь

1

Да, но вам будет намного легче с этим, если вы используете библиотеку OpenCV.

Если у вас есть библиотека OpenCV, скомпилированная и установленная, выполнить то, что вы просите, так же просто, как использовать imread () функция. Это сохраняет его в объект с именем cv :: Mat (он же матрица) с теми же размерами и значениями, что и tiff.

Оттуда вы можете делать с ней все, что захотите.

0

Еще один, легко устанавливаемый, легкий вариант будет использовать vips, Вы можете конвертировать 32-битный TIF в необработанный файл с 32-битными числами с плавающей запятой и считывать их прямо в вашу C ++ программу. В командной строке выполните преобразование с

vips rawsave yourImage.tif raw.bin

а затем прочитать в несжатом, неотформатированном плавает из файла raw.bin, Если мы сейчас дамп файла raw.binинтерпретируя данные как числа с плавающей точкой, вы можете увидеть те же значения, что и в других моих ответах:

od -f raw.bin

0000000     3.913185e-06    2.327210e-01    1.280000e+02    1.065769e+00
0000020     3.421732e-01    1.280000e+02    2.377803e+00    4.058807e-01
0000040     1.280000e+02    3.229325e+00    1.371841e-01    1.280000e+02

Конечно, вы можете заставить свою программу выполнить преобразование, связавшись с libvips или просто используя system() запустить версию командной строки, а затем прочитать его выходной файл.

0
По вопросам рекламы [email protected]