如何使用Rasterio写入TIFF文件?解决写入后图像变黑问题及实现TIFF局部读写
Hey there! Let's tackle your two Rasterio issues one by one—first the black image problem, then reading/writing partial TIFF regions.
Your code has a critical issue with how you're opening the TIFF file, which is causing the black output:
- You're using
'w+'mode to open the original TIFF. This mode creates a brand new empty file (overwriting the original)—so when you rundataset.read(), you're pulling all 0s instead of the actual image data. That's why yourtotalarray ends up as all 0s, resulting in a black image when written. - Also,
height='360'andwidth='360'should be integers (360), not strings (Rasterio might handle this, but it's not best practice).
Here's a corrected workflow: first read the original TIFF in read mode, process the data, then create a new TIFF to write the result:
import rasterio import numpy as np from rasterio.transform import from_origin # Step 1: Read the original valid TIFF with rasterio.open('M:/tiffs/MOS_EU_LAEA_2000/MOS_EU_LAEA_2000.tif', 'r') as src: # Read all 3 bands r, g, b = src.read() # Calculate the average (cast to float first to avoid integer truncation) total = (r.astype(np.float32) + g + b) / 3 # Get the source profile to reuse (adjust count to 1 for single-band output) profile = src.profile profile.update(count=1, dtype=rasterio.uint16) # Step 2: Write the processed data to a new TIFF with rasterio.open('M:/tiffs/MOS_EU_LAEA_2000/processed_average.tif', 'w', **profile) as dst: dst.write(total.astype(rasterio.uint16), 1)
A few key notes:
- Casting bands to
float32before averaging prevents integer division truncation (e.g., avoiding incorrect rounding when sums aren't perfectly divisible by 3). - Reusing the original profile ensures the new TIFF retains the source's CRS, transform, and other critical spatial metadata—no need to manually define
from_originunless you need a different spatial reference.
To extract a specific portion of a TIFF, use Rasterio's Window class to define the region (left column, top row, window width, window height). You'll also need to adjust the transform for the new file to match the window's spatial position:
import rasterio from rasterio.windows import Window # Define your target region: (left_col, top_row, window_width, window_height) # Example: extract a 100x100 window starting at column 50, row 50 window = Window(50, 50, 100, 100) with rasterio.open('M:/tiffs/MOS_EU_LAEA_2000/MOS_EU_LAEA_2000.tif', 'r') as src: # Read the windowed data from all bands window_data = src.read(window=window) # Get the transform adjusted for the window's offset window_transform = src.window_transform(window) # Copy source profile and update with window parameters profile = src.profile profile.update( height=window.height, width=window.width, transform=window_transform ) # Write the partial region to a new TIFF with rasterio.open('M:/tiffs/MOS_EU_LAEA_2000/partial_region.tif', 'w', **profile) as dst: dst.write(window_data)
This creates a new TIFF containing only the 100x100 region you defined, with correct spatial metadata so it aligns perfectly with the original file.
内容的提问来源于stack exchange,提问作者Amrmsmb

