修改像素精度
This commit is contained in:
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@ -61,9 +61,9 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# ---------- 配置 ----------
|
||||
# 请根据实际情况修改这些路径
|
||||
REF_TIF = r"E:\is2\guidingsahn\result.tif" # 参考 tif 文件路径
|
||||
BIP_DIR = Path(r"E:\is2\guidingsahn") # .bip 文件所在文件夹
|
||||
OUT_DIR = Path(r"E:\is2\guidingsahn\output") # 输出文件夹
|
||||
REF_TIF = r"E:\is2\dingshanhu\mask_water.tif" # 参考 tif 文件路径
|
||||
BIP_DIR = Path(r"E:\is2\dingshanhu") # .bip 文件所在文件夹
|
||||
OUT_DIR = Path(r"E:\is2\dingshanhu\output") # 输出文件夹
|
||||
|
||||
# 匹配算法选择
|
||||
MATCHER_NAME = "matchanything-roma" # 可选: xfeat-star, loftr, roma, superpoint-lightglue, sift-lightglue 等
|
||||
|
||||
125
test V9.py
125
test V9.py
@ -61,7 +61,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# ---------- 配置 ----------
|
||||
# 请根据实际情况修改这些路径
|
||||
REF_TIF = r"E:\is2\guidingsahn\result.tif" # 参考 tif 文件路径
|
||||
REF_TIF = r"E:\is2\guidingsahn\mask_water.tif" # 参考 tif 文件路径
|
||||
BIP_DIR = Path(r"E:\is2\guidingsahn") # .bip 文件所在文件夹
|
||||
OUT_DIR = Path(r"E:\is2\guidingsahn\output") # 输出文件夹
|
||||
|
||||
@ -157,7 +157,30 @@ def _expand_window(win, pad, max_w, max_h):
|
||||
row_off = int(max(0, win.row_off - pad))
|
||||
col_end = int(min(max_w, win.col_off + win.width + pad))
|
||||
row_end = int(min(max_h, win.row_off + win.height + pad))
|
||||
return rasterio.windows.Window(col_off, row_off, col_end - col_off, row_end - row_off)
|
||||
return rasterio.windows.Window(col_off, row_off, col_end - col_off, col_end - col_off,)
|
||||
|
||||
|
||||
def _pixel_size_xy(transform: Affine):
|
||||
rx = float(np.hypot(transform.a, transform.d))
|
||||
ry = float(np.hypot(transform.b, transform.e))
|
||||
if not np.isfinite(rx) or rx <= 0:
|
||||
rx = float(abs(transform.a)) if transform.a != 0 else 1.0
|
||||
if not np.isfinite(ry) or ry <= 0:
|
||||
ry = float(abs(transform.e)) if transform.e != 0 else 1.0
|
||||
return rx, ry
|
||||
|
||||
|
||||
def _grid_from_bounds(bounds, res_x: float, res_y: float):
|
||||
left, bottom, right, top = [float(v) for v in bounds]
|
||||
res_x = float(abs(res_x))
|
||||
res_y = float(abs(res_y))
|
||||
w = int(np.ceil((right - left) / max(1e-12, res_x)))
|
||||
h = int(np.ceil((top - bottom) / max(1e-12, res_y)))
|
||||
w = max(1, w)
|
||||
h = max(1, h)
|
||||
out_transform = Affine(res_x, 0.0, left, 0.0, -res_y, top)
|
||||
return out_transform, w, h
|
||||
|
||||
|
||||
def estimate_transform(method, k0, k1):
|
||||
"""统一的变换估计函数,支持多种变换类型"""
|
||||
@ -689,41 +712,43 @@ def process_bip_to_tif(bip_path: Path, ref_dataset, matcher, out_dir: Path, stat
|
||||
return False
|
||||
|
||||
bbox_window = rasterio.windows.Window(min_x, min_y, bbox_w, bbox_h)
|
||||
bbox_transform = ref_dataset.window_transform(bbox_window)
|
||||
bounds = rasterio.windows.bounds(bbox_window, transform=ref_dataset.transform)
|
||||
|
||||
res_x, res_y = _pixel_size_xy(src.transform)
|
||||
out_transform, out_w, out_h = _grid_from_bounds(bounds, res_x, res_y)
|
||||
|
||||
out_path = out_dir / f"{bip_path.stem}_registered.bip"
|
||||
src_nodata = src.nodata
|
||||
dst_nodata = src_nodata if src_nodata is not None else 0
|
||||
|
||||
out_profile = ref_dataset.profile.copy()
|
||||
out_profile = src.profile.copy()
|
||||
out_profile.update(
|
||||
driver="ENVI",
|
||||
dtype=src.dtypes[0],
|
||||
height=bbox_h,
|
||||
width=bbox_w,
|
||||
height=out_h,
|
||||
width=out_w,
|
||||
count=src.count,
|
||||
transform=bbox_transform,
|
||||
transform=out_transform,
|
||||
crs=ref_crs,
|
||||
interleave="bip",
|
||||
compress=None,
|
||||
nodata=dst_nodata
|
||||
)
|
||||
|
||||
# 重采样到最小外接矩形
|
||||
with rasterio.open(out_path, "w", **out_profile) as out_ds:
|
||||
for b in range(1, src.count + 1):
|
||||
src_band = src.read(b).astype(np.float32)
|
||||
dst_band = np.zeros((bbox_h, bbox_w), dtype=np.float32)
|
||||
dst_band = np.zeros((out_h, out_w), dtype=np.float32)
|
||||
reproject(
|
||||
source=src_band,
|
||||
destination=dst_band,
|
||||
src_transform=corrected_affine,
|
||||
src_crs=ref_crs,
|
||||
dst_transform=bbox_transform,
|
||||
dst_transform=out_transform,
|
||||
dst_crs=ref_crs,
|
||||
src_nodata=src_nodata,
|
||||
dst_nodata=dst_nodata,
|
||||
resampling=Resampling.bilinear,
|
||||
resampling=Resampling.nearest,
|
||||
)
|
||||
|
||||
if np.issubdtype(np.dtype(out_profile["dtype"]), np.integer):
|
||||
@ -772,46 +797,56 @@ def process_bip_to_tif(bip_path: Path, ref_dataset, matcher, out_dir: Path, stat
|
||||
logger.warning(f"单应变换最小外接矩形无效: {bip_path.name}")
|
||||
return False
|
||||
|
||||
# 创建输出窗口
|
||||
bbox_window = rasterio.windows.Window(min_x, min_y, bbox_w, bbox_h)
|
||||
bbox_transform = ref_dataset.window_transform(bbox_window)
|
||||
bounds = rasterio.windows.bounds(bbox_window, transform=ref_dataset.transform)
|
||||
|
||||
# 子窗口坐标的单应矩阵(输出坐标系是子窗口像素)
|
||||
T_off = np.array([[1,0,min_x],[0,1,min_y],[0,0,1]], dtype=np.float64)
|
||||
H_sub = np.linalg.inv(T_off) @ H_full
|
||||
res_x, res_y = _pixel_size_xy(src.transform)
|
||||
out_transform, out_w, out_h = _grid_from_bounds(bounds, res_x, res_y)
|
||||
|
||||
out_path = out_dir / f"{bip_path.stem}_registered.bip"
|
||||
src_nodata = src.nodata
|
||||
dst_nodata = src_nodata if src_nodata is not None else 0
|
||||
|
||||
out_profile = ref_dataset.profile.copy()
|
||||
out_profile = src.profile.copy()
|
||||
out_profile.update(
|
||||
driver="ENVI",
|
||||
dtype=src.dtypes[0],
|
||||
height=bbox_h,
|
||||
width=bbox_w,
|
||||
height=out_h,
|
||||
width=out_w,
|
||||
count=src.count,
|
||||
transform=bbox_transform,
|
||||
transform=out_transform,
|
||||
crs=ref_crs,
|
||||
interleave="bip",
|
||||
compress=None,
|
||||
nodata=dst_nodata
|
||||
)
|
||||
|
||||
# 使用 OpenCV 进行单应变换重采样
|
||||
ref_transform = ref_dataset.transform
|
||||
Rt = np.array(
|
||||
[[ref_transform.a, ref_transform.b, ref_transform.c],
|
||||
[ref_transform.d, ref_transform.e, ref_transform.f],
|
||||
[0.0, 0.0, 1.0]],
|
||||
dtype=np.float64,
|
||||
)
|
||||
Out = np.array(
|
||||
[[out_transform.a, out_transform.b, out_transform.c],
|
||||
[out_transform.d, out_transform.e, out_transform.f],
|
||||
[0.0, 0.0, 1.0]],
|
||||
dtype=np.float64,
|
||||
)
|
||||
M = np.linalg.inv(Out) @ Rt @ H_full.astype(np.float64)
|
||||
|
||||
with rasterio.open(out_path, "w", **out_profile) as out_ds:
|
||||
for b in range(1, src.count + 1):
|
||||
src_band = src.read(b).astype(np.float32)
|
||||
dst_band = np.full((bbox_h, bbox_w), dst_nodata, dtype=np.float32)
|
||||
|
||||
# 使用 OpenCV warpPerspective(子窗口坐标)
|
||||
dst_band = cv2.warpPerspective(
|
||||
src_band, H_sub,
|
||||
(bbox_w, bbox_h),
|
||||
flags=cv2.INTER_LINEAR,
|
||||
src_band,
|
||||
M,
|
||||
(out_w, out_h),
|
||||
flags=cv2.INTER_NEAREST,
|
||||
borderMode=cv2.BORDER_CONSTANT,
|
||||
borderValue=dst_nodata
|
||||
)
|
||||
borderValue=float(dst_nodata)
|
||||
).astype(np.float32)
|
||||
|
||||
# 转回目标 dtype
|
||||
if np.issubdtype(np.dtype(out_profile["dtype"]), np.integer):
|
||||
@ -957,7 +992,8 @@ def process_bip_to_tif(bip_path: Path, ref_dataset, matcher, out_dir: Path, stat
|
||||
output_shape=(bbox_h, bbox_w),
|
||||
mode='constant',
|
||||
cval=dst_nodata,
|
||||
preserve_range=True
|
||||
preserve_range=True,
|
||||
order=0
|
||||
).astype(np.float32)
|
||||
|
||||
# 转回目标 dtype
|
||||
@ -1060,7 +1096,8 @@ def process_bip_to_tif(bip_path: Path, ref_dataset, matcher, out_dir: Path, stat
|
||||
output_shape=(bbox_h, bbox_w),
|
||||
mode='constant',
|
||||
cval=dst_nodata,
|
||||
preserve_range=True
|
||||
preserve_range=True,
|
||||
order=0
|
||||
).astype(np.float32)
|
||||
|
||||
if np.issubdtype(np.dtype(out_profile["dtype"]), np.integer):
|
||||
@ -1091,7 +1128,7 @@ def process_bip_to_tif(bip_path: Path, ref_dataset, matcher, out_dir: Path, stat
|
||||
# 使用OpenCV的remap进行重采样
|
||||
dst_band = cv2.remap(
|
||||
src_band, map_x, map_y,
|
||||
interpolation=cv2.INTER_LINEAR,
|
||||
interpolation=cv2.INTER_NEAREST,
|
||||
borderMode=cv2.BORDER_CONSTANT,
|
||||
borderValue=dst_nodata
|
||||
)
|
||||
@ -1192,44 +1229,44 @@ def process_bip_to_tif(bip_path: Path, ref_dataset, matcher, out_dir: Path, stat
|
||||
logger.warning(f"最小外接矩形无效: {bip_path.name}")
|
||||
return False
|
||||
|
||||
# 创建裁剪窗口和变换
|
||||
bbox_window = rasterio.windows.Window(min_x, min_y, bbox_w, bbox_h)
|
||||
bbox_transform = ref_dataset.window_transform(bbox_window)
|
||||
bounds = rasterio.windows.bounds(bbox_window, transform=ref_dataset.transform)
|
||||
|
||||
res_x, res_y = _pixel_size_xy(src.transform)
|
||||
out_transform, out_w, out_h = _grid_from_bounds(bounds, res_x, res_y)
|
||||
|
||||
out_path = out_dir / f"{bip_path.stem}_registered.bip"
|
||||
src_nodata = src.nodata
|
||||
dst_nodata = src_nodata if src_nodata is not None else 0
|
||||
|
||||
# 更新输出 profile 使用最小外接矩形
|
||||
out_profile = ref_dataset.profile.copy()
|
||||
out_profile = src.profile.copy()
|
||||
out_profile.update(
|
||||
driver="ENVI",
|
||||
dtype=src.dtypes[0],
|
||||
height=bbox_h,
|
||||
width=bbox_w,
|
||||
height=out_h,
|
||||
width=out_w,
|
||||
count=src.count,
|
||||
transform=bbox_transform, # 使用最小外接矩形的变换
|
||||
transform=out_transform,
|
||||
crs=ref_crs,
|
||||
interleave="bip",
|
||||
compress=None,
|
||||
nodata=dst_nodata
|
||||
)
|
||||
|
||||
# 重采样到最小外接矩形
|
||||
with rasterio.open(out_path, "w", **out_profile) as out_ds:
|
||||
for b in range(1, src.count + 1):
|
||||
src_band = src.read(b).astype(np.float32)
|
||||
dst_band = np.zeros((bbox_h, bbox_w), dtype=np.float32)
|
||||
dst_band = np.zeros((out_h, out_w), dtype=np.float32)
|
||||
reproject(
|
||||
source=src_band,
|
||||
destination=dst_band,
|
||||
src_transform=corrected_affine,
|
||||
src_crs=ref_crs,
|
||||
dst_transform=bbox_transform,
|
||||
dst_transform=out_transform,
|
||||
dst_crs=ref_crs,
|
||||
src_nodata=src_nodata,
|
||||
dst_nodata=dst_nodata,
|
||||
resampling=Resampling.bilinear,
|
||||
resampling=Resampling.nearest,
|
||||
)
|
||||
# 转回目标 dtype
|
||||
if np.issubdtype(np.dtype(out_profile["dtype"]), np.integer):
|
||||
@ -1296,4 +1333,4 @@ def main():
|
||||
logger.info(f"处理完成: {success_count}/{len(bip_files)} 个文件成功配准")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
1714
test V9GUI.py
Normal file
1714
test V9GUI.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user