Reputation: 1031
i have a geotiff images that have 3bands.
band1,2 is a actual image values and band3 is a instance angle value.
band1,2 is float32 data type
under code is that i try before.
but it doesn't work.
i think band data's range is too large, so it doesn't
from osgeo import gdal, osr, ogr
from PIL import Image
import numpy as np
ds = gdal.Open('image path', gdal.GA_ReadOnly)
rb = ds.GetRasterBand(1)
test = rb.ReadAsArray()
rb2 = ds.GetRasterBand(2)
test2 = rb2.ReadAsArray()
rb3 = ds.GetRasterBand(3)
test3 = rb3.ReadAsArray()
slice56 = test2
formatted = (slice56 * 255 / np.max(slice56)).astype('uint8')
img = Image.fromarray(formatted)
img.save('save image path')
how can i solve this problem??
Upvotes: 5
Views: 10095
Reputation: 199
I have written the following module and more of that can be found on my GitHub:
import os
from osgeo import gdal
def geotiff_to_png(input_path, output_path=None, return_object=False):
"""
Converts a GeoTIFF file to a PNG file or object. Specific to Skysatimages with 4 bands (blue, green, red, nir).
Args:
input_path (str): The file path of the input GeoTIFF file.
output_path (str, optional): The file path of the output PNG file. If not provided, PNG object is returned. Defaults to None.
return_object (bool, optional): Whether to return the PNG data as an object. If True, the output_path parameter will be ignored. Defaults to False.
Returns:
numpy.ndarray or None: If output_path is not provided and return_object is True, returns a 3D numpy array representing the PNG image. Otherwise, returns None.
"""
# Open input file
dataset = gdal.Open(input_path)
output_types = [gdal.GDT_Byte, gdal.GDT_UInt16, gdal.GDT_Float32]
# Define output format and options
options = gdal.TranslateOptions(format='PNG', bandList=[3,2,1], creationOptions=['WORLDFILE=YES'], outputType=output_types[0])
# Translate to PNG
if output_path is not None:
gdal.Translate(output_path, dataset, options=options)
print(f'Successfully saved PNG file to {output_path}')
# Return PNG object
if return_object:
mem_driver = gdal.GetDriverByName('MEM')
mem_dataset = mem_driver.CreateCopy('', dataset, 0)
png_data = mem_dataset.ReadAsArray()
return png_data
Upvotes: 0
Reputation: 5040
You can use gdal.Translate
for this.
You can read the documentation here
from osgeo import gdal
options_list = [
'-ot Byte',
'-of JPEG',
'-b 1',
'-scale'
]
options_string = " ".join(options_list)
gdal.Translate(
'save_image_path.jpg',
'image_path.tif',
options=options_string
)
The above code simply create a jpg file with band 1 scaled into byte range. You could add more bands by adding, '-b 2'
etc. Also notice that scale automatically wraps the entire range into byte range. If you like something else you could use '-scale min_val max_val'
in order to specify the range you like, since often you have no need of either the lowest or highest values available.
Upvotes: 11
Reputation: 101
The above worked well for me except the JPEG resolution wasn't great. Swapping JPEG to PNG worked better.
Upvotes: 2