First time here? Check out the FAQ!

Ask Your Question
1

Reading GEO Tiff

asked Feb 4 '16

Maik Angermann gravatar image

updated Nov 1 '0

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

Preview: (hide)

2 answers

Sort by » oldest newest most voted
4

answered Feb 5 '16

kbarni gravatar image

updated Feb 5 '16

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!

Preview: (hide)

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 (Feb 9 '16)edit
0

answered Feb 9 '16

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.

Preview: (hide)

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 (Feb 9 '16)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 (Feb 10 '16)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 (Feb 10 '16)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 (Feb 10 '16)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 (Jul 20 '18)edit

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

Otter gravatar imageOtter (Jul 21 '18)edit

Question Tools

1 follower

Stats

Asked: Feb 4 '16

Seen: 8,109 times

Last updated: Feb 09 '16