Ask Your Question
1

Reading GEO Tiff

asked 2016-02-04 08:43:02 -0600

Maik Angermann gravatar image

updated 2020-11-01 06:36:49 -0600

Hi everone.

I build an OPENCV3.0 project in order to read big geo tiff satellite images. I was able to link gdal lib to OCV but still have problems opening tiffs. I am not sure if the there are 2 issues. One might be the coding of the tif and the other might be the file size. It seems that I can not open file sizes bigger than 300 Mbyte. My goal is it to open up geo tiffs (basically satelite images) up to 800 Mbyte. Either I get an out of memory failure or the program fails with exception. imgread_LOAD_GDAL will result in "Exception at 0x7633c42d, code: 0xe06d7363: C++ exception, flags=0x1 (execution cannot be continued) at e:\docs\opencv3\sources\modules\core\src\system.cpp:656"

I use QT creator with VS2010 compiler.

Does anyone have any experiences with that and might help me. Thanks

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
4

answered 2016-02-05 07:01:38 -0600

kbarni gravatar image

updated 2016-02-05 08:54:42 -0600

For GeoTIFF images it might be better to use directly libtiff. It's very robust and can handle any TIFF image. Most general purpose libraries or software are having difficulties when loading multispectral or large images.

If you built OpenCV for yourself, you might have libtiff already, otherwise download it here.

Here's how to use it:

#include "tiffio.h"
....

TIFF *tif=TIFFOpen(filename, "r");
uint32 W,H;
uint16 Bands,bps,sf;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &W);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &H);
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &Bands);
TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bps);
TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sf);

The size of your matrix is W * H * Bands. The type is determined using sf and bpp: sf=1:unsigned; sf=2:signed;sf=3:floating point (e.g. if sf=1 and bpp=32 then type=CV_32U; for sf=3 and bpp=64 you have type=CV_64F)

long sls=TIFFScanlineSize(tif);
void *raster;
raster=_TIFFmalloc(sls);
int sizes[3]={H,W,Bands};
Mat geotiff(3,sizes,type);
char *scanline;
for(int i=0;i<H;i++){
    TIFFReadScanline(tif,raster,i,0);
    scanline=geotiff.ptr(i);
    memcpy(raster,scanline,sls);
}
_TIFFfree(raster);
TIFFClose(tif);

This should probably work, however the code is untested (I adapted an old code I had). Note that this works for any number of bands; for panchromatic, RGB or RGBA images the code is much simpler (use TIFFReadRGBAImageOriented or similar functions). For more information, read the documentation.

Finally, don't forget to add the libtiff.lib to the QT project libs.

Hope this helps!

edit flag offensive delete link more

Comments

Just a quick note: it might be easier to work with an array of 2D single channel images in the case of multispectral (more than 3 color plane) Geotiff images. I found very little reference about handling 3D Mat variables in OpenCV.

kbarni gravatar imagekbarni ( 2016-02-09 10:32:16 -0600 )edit
0

answered 2016-02-09 07:10:46 -0600

Maik Angermann gravatar image

Kbarni, Well this seem to be a long road to the finish. Anyway, I managed to convert the the TIFFS in bmp but stil the problem is that OpenCV can't handle it because of the image size.

So how can I open huge images even if I dont use TIFF files.

edit flag offensive delete link more

Comments

Maik, please read what I wrote: "Most general purpose libraries or software are having difficulties when loading multispectral or large images." That's why I suggested to use libtiff. cv::imread won't work in this case for tif, bmp or any format.

Believe me, my solution works. I tested it on 1.4GB GeoTiff image (60MP resolution, 7 bands, floating point) and I don't get any error.

OpenCV can handle Mat data of this size. If you still have a problem, check the memory usage of your program.

kbarni gravatar imagekbarni ( 2016-02-09 10:26:33 -0600 )edit

Thanks, Are you refering to a linux or windows system? I tried to include libtif but it seems to be very old fashioned. I have read that libitf is included in windows systems since a while.

Maik Angermann gravatar imageMaik Angermann ( 2016-02-10 06:54:11 -0600 )edit

I tested it on Linux, however I used libtiff to open large GeoTiff images on Windows too. It works exactly the same way.

If you want to test first if OpenCV can handle this size of image, create an empty Mat with the same type and size, fill it with some data and display it.

Opening an image with libtiff might be more complicated than cv::imread, but when you want to handle any kind of tif image and allow it to be handled by any application and OS, that's the only way.

kbarni gravatar imagekbarni ( 2016-02-10 08:34:26 -0600 )edit

And I repeat myself one last time: If you want to be sure to be able to open more complex Geotiff images, use libtiff! I'm pretty sure that the Windows API, even if it handles normal tif images, won't be able to open more exotic formats.

So please, if you don't want to use my solution or you don't like to mess with low-level libraries, you don't have to, but then go complaining to Microsoft for their basic API that won't handle Geotiff images, not here!

kbarni gravatar imagekbarni ( 2016-02-10 08:37:14 -0600 )edit

But if I try seeing that mat imshow("this mat", geotiff) it throws below exception. System.Runtime.InteropServices.SEHException: 'External component has thrown an exception.

Otter gravatar imageOtter ( 2018-07-20 17:45:20 -0600 )edit

memcpy(raster,scanline,sls); should it not be in source and destination reversed ?

Otter gravatar imageOtter ( 2018-07-20 23:52:51 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-02-04 08:43:02 -0600

Seen: 7,956 times

Last updated: Feb 09 '16