使用Rasterio与Numpy创建TIFF文件失败,报错CPLE_OpenFailedError求助
Hey there! Let's break down the issues you're facing and fix them one by one.
First: Fix the "No Such File or Directory" Error
The CPLE_OpenFailedError you're seeing isn't about your input file (since you can open montreal_30m.tif just fine) — it's about not being able to write the output file montreal_90m.tif. Here's why and how to fix it:
- Relative path confusion: You're using a relative filename, which means Rasterio tries to save the file in your current working directory. If that directory doesn't exist (or you don't have write permissions), it fails.
- To check your current working directory, run this:
import os print(os.getcwd()) - Solution 1: Use an absolute path for the output file, like
/home/your_username/data/montreal_90m.tif(adjust to your system's actual path). - Solution 2: If you want to save to a subfolder, make sure it exists first. Add this code before opening the output file:
output_path = "montreal_90m.tif" # Create parent directories if they don't exist os.makedirs(os.path.dirname(output_path), exist_ok=True)
- To check your current working directory, run this:
Second: Improve Your Transform Calculation
While your hardcoded transform values might be correct, it's better to derive them from the original dataset instead of manually typing coordinates — this avoids typos and ensures accuracy. Replace your newtransform line with this:
# Calculate new transform using original dataset's parameters new_transform = Affine( dataset.transform[0] * 3, # Scale x cell size by 3 dataset.transform[1], dataset.transform[2], # Keep original top-left x coordinate dataset.transform[3], dataset.transform[4] * 3, # Scale y cell size by 3 dataset.transform[5] # Keep original top-left y coordinate )
Bonus: Simplify Resampling with Rasterio's Built-in Tools
Your manual loop to downsample the raster works, but Rasterio has optimized resampling functions that are faster and cleaner. Here's a streamlined version of your code using Resampling.nearest (matches your current "take every 3rd pixel" logic):
import rasterio from rasterio.plot import show import numpy as np from affine import Affine from rasterio.enums import Resampling import os # Open input dataset with rasterio.open('montreal_30m.tif') as dataset: # Calculate new dimensions (downscale by 3x) new_height = dataset.height // 3 new_width = dataset.width // 3 # Downsample using nearest neighbor (matches your current approach) new_band = dataset.read( 1, out_shape=(new_height, new_width), resampling=Resampling.nearest ) # Calculate new transform automatically new_transform = dataset.transform * dataset.transform.scale( (dataset.width / new_width), (dataset.height / new_height) ) # Prepare output path and create directories if needed output_path = 'montreal_90m.tif' os.makedirs(os.path.dirname(output_path), exist_ok=True) # Write the new TIFF with rasterio.open( output_path, 'w', driver='GTiff', height=new_height, width=new_width, count=1, dtype=np.float32, crs=dataset.crs, transform=new_transform ) as new_raster: new_raster.write(new_band, 1)
This code handles path creation, uses Rasterio's optimized resampling, and avoids hardcoded coordinates — making it more robust and easier to maintain.
内容的提问来源于stack exchange,提问作者Lisa Wang

