修改像素精度
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 文件路径
|
REF_TIF = r"E:\is2\dingshanhu\mask_water.tif" # 参考 tif 文件路径
|
||||||
BIP_DIR = Path(r"E:\is2\guidingsahn") # .bip 文件所在文件夹
|
BIP_DIR = Path(r"E:\is2\dingshanhu") # .bip 文件所在文件夹
|
||||||
OUT_DIR = Path(r"E:\is2\guidingsahn\output") # 输出文件夹
|
OUT_DIR = Path(r"E:\is2\dingshanhu\output") # 输出文件夹
|
||||||
|
|
||||||
# 匹配算法选择
|
# 匹配算法选择
|
||||||
MATCHER_NAME = "matchanything-roma" # 可选: xfeat-star, loftr, roma, superpoint-lightglue, sift-lightglue 等
|
MATCHER_NAME = "matchanything-roma" # 可选: xfeat-star, loftr, roma, superpoint-lightglue, sift-lightglue 等
|
||||||
|
|||||||
123
test V9.py
123
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 文件所在文件夹
|
BIP_DIR = Path(r"E:\is2\guidingsahn") # .bip 文件所在文件夹
|
||||||
OUT_DIR = Path(r"E:\is2\guidingsahn\output") # 输出文件夹
|
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))
|
row_off = int(max(0, win.row_off - pad))
|
||||||
col_end = int(min(max_w, win.col_off + win.width + 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))
|
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):
|
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
|
return False
|
||||||
|
|
||||||
bbox_window = rasterio.windows.Window(min_x, min_y, bbox_w, bbox_h)
|
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"
|
out_path = out_dir / f"{bip_path.stem}_registered.bip"
|
||||||
src_nodata = src.nodata
|
src_nodata = src.nodata
|
||||||
dst_nodata = src_nodata if src_nodata is not None else 0
|
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(
|
out_profile.update(
|
||||||
driver="ENVI",
|
driver="ENVI",
|
||||||
dtype=src.dtypes[0],
|
dtype=src.dtypes[0],
|
||||||
height=bbox_h,
|
height=out_h,
|
||||||
width=bbox_w,
|
width=out_w,
|
||||||
count=src.count,
|
count=src.count,
|
||||||
transform=bbox_transform,
|
transform=out_transform,
|
||||||
crs=ref_crs,
|
crs=ref_crs,
|
||||||
interleave="bip",
|
interleave="bip",
|
||||||
compress=None,
|
compress=None,
|
||||||
nodata=dst_nodata
|
nodata=dst_nodata
|
||||||
)
|
)
|
||||||
|
|
||||||
# 重采样到最小外接矩形
|
|
||||||
with rasterio.open(out_path, "w", **out_profile) as out_ds:
|
with rasterio.open(out_path, "w", **out_profile) as out_ds:
|
||||||
for b in range(1, src.count + 1):
|
for b in range(1, src.count + 1):
|
||||||
src_band = src.read(b).astype(np.float32)
|
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(
|
reproject(
|
||||||
source=src_band,
|
source=src_band,
|
||||||
destination=dst_band,
|
destination=dst_band,
|
||||||
src_transform=corrected_affine,
|
src_transform=corrected_affine,
|
||||||
src_crs=ref_crs,
|
src_crs=ref_crs,
|
||||||
dst_transform=bbox_transform,
|
dst_transform=out_transform,
|
||||||
dst_crs=ref_crs,
|
dst_crs=ref_crs,
|
||||||
src_nodata=src_nodata,
|
src_nodata=src_nodata,
|
||||||
dst_nodata=dst_nodata,
|
dst_nodata=dst_nodata,
|
||||||
resampling=Resampling.bilinear,
|
resampling=Resampling.nearest,
|
||||||
)
|
)
|
||||||
|
|
||||||
if np.issubdtype(np.dtype(out_profile["dtype"]), np.integer):
|
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}")
|
logger.warning(f"单应变换最小外接矩形无效: {bip_path.name}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 创建输出窗口
|
|
||||||
bbox_window = rasterio.windows.Window(min_x, min_y, bbox_w, bbox_h)
|
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)
|
||||||
T_off = np.array([[1,0,min_x],[0,1,min_y],[0,0,1]], dtype=np.float64)
|
out_transform, out_w, out_h = _grid_from_bounds(bounds, res_x, res_y)
|
||||||
H_sub = np.linalg.inv(T_off) @ H_full
|
|
||||||
|
|
||||||
out_path = out_dir / f"{bip_path.stem}_registered.bip"
|
out_path = out_dir / f"{bip_path.stem}_registered.bip"
|
||||||
src_nodata = src.nodata
|
src_nodata = src.nodata
|
||||||
dst_nodata = src_nodata if src_nodata is not None else 0
|
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(
|
out_profile.update(
|
||||||
driver="ENVI",
|
driver="ENVI",
|
||||||
dtype=src.dtypes[0],
|
dtype=src.dtypes[0],
|
||||||
height=bbox_h,
|
height=out_h,
|
||||||
width=bbox_w,
|
width=out_w,
|
||||||
count=src.count,
|
count=src.count,
|
||||||
transform=bbox_transform,
|
transform=out_transform,
|
||||||
crs=ref_crs,
|
crs=ref_crs,
|
||||||
interleave="bip",
|
interleave="bip",
|
||||||
compress=None,
|
compress=None,
|
||||||
nodata=dst_nodata
|
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:
|
with rasterio.open(out_path, "w", **out_profile) as out_ds:
|
||||||
for b in range(1, src.count + 1):
|
for b in range(1, src.count + 1):
|
||||||
src_band = src.read(b).astype(np.float32)
|
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(
|
dst_band = cv2.warpPerspective(
|
||||||
src_band, H_sub,
|
src_band,
|
||||||
(bbox_w, bbox_h),
|
M,
|
||||||
flags=cv2.INTER_LINEAR,
|
(out_w, out_h),
|
||||||
|
flags=cv2.INTER_NEAREST,
|
||||||
borderMode=cv2.BORDER_CONSTANT,
|
borderMode=cv2.BORDER_CONSTANT,
|
||||||
borderValue=dst_nodata
|
borderValue=float(dst_nodata)
|
||||||
)
|
).astype(np.float32)
|
||||||
|
|
||||||
# 转回目标 dtype
|
# 转回目标 dtype
|
||||||
if np.issubdtype(np.dtype(out_profile["dtype"]), np.integer):
|
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),
|
output_shape=(bbox_h, bbox_w),
|
||||||
mode='constant',
|
mode='constant',
|
||||||
cval=dst_nodata,
|
cval=dst_nodata,
|
||||||
preserve_range=True
|
preserve_range=True,
|
||||||
|
order=0
|
||||||
).astype(np.float32)
|
).astype(np.float32)
|
||||||
|
|
||||||
# 转回目标 dtype
|
# 转回目标 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),
|
output_shape=(bbox_h, bbox_w),
|
||||||
mode='constant',
|
mode='constant',
|
||||||
cval=dst_nodata,
|
cval=dst_nodata,
|
||||||
preserve_range=True
|
preserve_range=True,
|
||||||
|
order=0
|
||||||
).astype(np.float32)
|
).astype(np.float32)
|
||||||
|
|
||||||
if np.issubdtype(np.dtype(out_profile["dtype"]), np.integer):
|
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进行重采样
|
# 使用OpenCV的remap进行重采样
|
||||||
dst_band = cv2.remap(
|
dst_band = cv2.remap(
|
||||||
src_band, map_x, map_y,
|
src_band, map_x, map_y,
|
||||||
interpolation=cv2.INTER_LINEAR,
|
interpolation=cv2.INTER_NEAREST,
|
||||||
borderMode=cv2.BORDER_CONSTANT,
|
borderMode=cv2.BORDER_CONSTANT,
|
||||||
borderValue=dst_nodata
|
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}")
|
logger.warning(f"最小外接矩形无效: {bip_path.name}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 创建裁剪窗口和变换
|
|
||||||
bbox_window = rasterio.windows.Window(min_x, min_y, bbox_w, bbox_h)
|
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"
|
out_path = out_dir / f"{bip_path.stem}_registered.bip"
|
||||||
src_nodata = src.nodata
|
src_nodata = src.nodata
|
||||||
dst_nodata = src_nodata if src_nodata is not None else 0
|
dst_nodata = src_nodata if src_nodata is not None else 0
|
||||||
|
|
||||||
# 更新输出 profile 使用最小外接矩形
|
out_profile = src.profile.copy()
|
||||||
out_profile = ref_dataset.profile.copy()
|
|
||||||
out_profile.update(
|
out_profile.update(
|
||||||
driver="ENVI",
|
driver="ENVI",
|
||||||
dtype=src.dtypes[0],
|
dtype=src.dtypes[0],
|
||||||
height=bbox_h,
|
height=out_h,
|
||||||
width=bbox_w,
|
width=out_w,
|
||||||
count=src.count,
|
count=src.count,
|
||||||
transform=bbox_transform, # 使用最小外接矩形的变换
|
transform=out_transform,
|
||||||
crs=ref_crs,
|
crs=ref_crs,
|
||||||
interleave="bip",
|
interleave="bip",
|
||||||
compress=None,
|
compress=None,
|
||||||
nodata=dst_nodata
|
nodata=dst_nodata
|
||||||
)
|
)
|
||||||
|
|
||||||
# 重采样到最小外接矩形
|
|
||||||
with rasterio.open(out_path, "w", **out_profile) as out_ds:
|
with rasterio.open(out_path, "w", **out_profile) as out_ds:
|
||||||
for b in range(1, src.count + 1):
|
for b in range(1, src.count + 1):
|
||||||
src_band = src.read(b).astype(np.float32)
|
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(
|
reproject(
|
||||||
source=src_band,
|
source=src_band,
|
||||||
destination=dst_band,
|
destination=dst_band,
|
||||||
src_transform=corrected_affine,
|
src_transform=corrected_affine,
|
||||||
src_crs=ref_crs,
|
src_crs=ref_crs,
|
||||||
dst_transform=bbox_transform,
|
dst_transform=out_transform,
|
||||||
dst_crs=ref_crs,
|
dst_crs=ref_crs,
|
||||||
src_nodata=src_nodata,
|
src_nodata=src_nodata,
|
||||||
dst_nodata=dst_nodata,
|
dst_nodata=dst_nodata,
|
||||||
resampling=Resampling.bilinear,
|
resampling=Resampling.nearest,
|
||||||
)
|
)
|
||||||
# 转回目标 dtype
|
# 转回目标 dtype
|
||||||
if np.issubdtype(np.dtype(out_profile["dtype"]), np.integer):
|
if np.issubdtype(np.dtype(out_profile["dtype"]), np.integer):
|
||||||
|
|||||||
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