Compare commits
29 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
e1fad5f0f1 | |
|
|
9c8e14e2c7 | |
|
|
5794cfbe49 | |
|
|
acf441db4a | |
|
|
7226fe582f | |
|
|
b2f9b01555 | |
|
|
d63423ff18 | |
|
|
c689b2d84d | |
|
|
7882cdfe62 | |
|
|
0f44939718 | |
|
|
654df6d3cc | |
|
|
cf2423fc6b | |
|
|
db88494e41 | |
|
|
a521ccb844 | |
|
|
d5e6af700a | |
|
|
9ad27ac6d4 | |
|
|
0b64b18ef0 | |
|
|
83f3d5750b | |
|
|
4cad12128c | |
|
|
ec99cabb07 | |
|
|
1a5372f04a | |
|
|
c702658884 | |
|
|
595751a3c3 | |
|
|
a66f9ac220 | |
|
|
a9f390d2f8 | |
|
|
2b72ea22db | |
|
|
2b3b14fa83 | |
|
|
e032838c39 | |
|
|
dd10658c05 |
|
|
@ -3,3 +3,4 @@
|
||||||
/workspace.xml
|
/workspace.xml
|
||||||
# 基于编辑器的 HTTP 客户端请求
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
/httpRequests/
|
/httpRequests/
|
||||||
|
/vcs.xml
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<module type="PYTHON_MODULE" version="4">
|
<module type="PYTHON_MODULE" version="4">
|
||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$" />
|
<content url="file://$MODULE_DIR$" />
|
||||||
<orderEntry type="jdk" jdkName="Python 3.9" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="spacetySliceEnv" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PyDocumentationSettings">
|
<component name="PyDocumentationSettings">
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,5 @@
|
||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="sdkName" value="spacetySliceEnv" />
|
<option name="sdkName" value="spacetySliceEnv" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="spacetySliceEnv" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,561 @@
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
from osgeo import ogr,gdal
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
from osgeo import gdal
|
||||||
|
import matplotlib
|
||||||
|
import matplotlib.patches as patches
|
||||||
|
from osgeo import gdal
|
||||||
|
from PIL import Image
|
||||||
|
from scipy.spatial import cKDTree
|
||||||
|
import numpy as np
|
||||||
|
from tools.DotaOperator import DotaObj,createDota,readDotaFile,writerDotaFile
|
||||||
|
import argparse
|
||||||
|
import math
|
||||||
|
from math import ceil, floor
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# 参数区
|
||||||
|
##########################################################################
|
||||||
|
SliceSize=5000
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# 函数区
|
||||||
|
##########################################################################
|
||||||
|
def read_tif(path):
|
||||||
|
dataset = gdal.Open(path) # 打开TIF文件
|
||||||
|
if dataset is None:
|
||||||
|
print("无法打开文件")
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
cols = dataset.RasterXSize # 图像宽度
|
||||||
|
rows = dataset.RasterYSize # 图像高度
|
||||||
|
bands = dataset.RasterCount
|
||||||
|
im_proj = dataset.GetProjection() # 获取投影信息
|
||||||
|
im_Geotrans = dataset.GetGeoTransform() # 获取仿射变换信息
|
||||||
|
im_data = dataset.ReadAsArray(0, 0, cols, rows) # 读取栅格数据为NumPy数组
|
||||||
|
print("行数:", rows)
|
||||||
|
print("列数:", cols)
|
||||||
|
print("波段:", bands)
|
||||||
|
del dataset # 关闭数据集
|
||||||
|
return im_proj, im_Geotrans, im_data
|
||||||
|
|
||||||
|
|
||||||
|
def Strech_SquareRoot(im_data):
|
||||||
|
# 判断是否为dB
|
||||||
|
# immask = np.isfinite(im_data)
|
||||||
|
# imvail_data = im_data[immask]
|
||||||
|
# minvalue = np.percentile(imvail_data,30)
|
||||||
|
# if minvalue<0 :
|
||||||
|
# im_data=np.power(10.0,im_data/10.0)
|
||||||
|
|
||||||
|
im_data=np.sqrt(im_data)
|
||||||
|
immask = np.isfinite(im_data)
|
||||||
|
imvail_data = im_data[immask]
|
||||||
|
|
||||||
|
minvalue=np.nanmin(imvail_data)
|
||||||
|
maxvalue=np.nanmax(imvail_data)
|
||||||
|
minvalue_01Prec = np.percentile(imvail_data, 0.1) # 20250904 1%拉伸
|
||||||
|
maxvalue_999Prec = np.percentile(imvail_data, 99.9)
|
||||||
|
print('sqrt root min - max ', minvalue,maxvalue)
|
||||||
|
if (maxvalue-minvalue)/(maxvalue_999Prec-minvalue_01Prec)>3: # 表示 拉伸之后,像素值绝大部分很有可能集中在 80
|
||||||
|
minvalue=minvalue_01Prec
|
||||||
|
maxvalue=maxvalue_999Prec
|
||||||
|
print('sqrt root min(0.1) - max(99.9) ', minvalue, maxvalue)
|
||||||
|
|
||||||
|
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254 + 1
|
||||||
|
im_data = np.clip(im_data, 0, 255)
|
||||||
|
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
def write_envi(im_data, im_geotrans, im_proj, output_path):
|
||||||
|
"""
|
||||||
|
将数组数据写入ENVI格式文件
|
||||||
|
:param im_data: 输入的numpy数组(2D或3D)
|
||||||
|
:param im_geotrans: 仿射变换参数(6元组)
|
||||||
|
:param im_proj: 投影信息(WKT字符串)
|
||||||
|
:param output_path: 输出文件路径(无需扩展名,会自动生成.dat和.hdr)
|
||||||
|
"""
|
||||||
|
im_bands = 1
|
||||||
|
im_height, im_width = im_data.shape
|
||||||
|
# 创建ENVI格式驱动
|
||||||
|
driver = gdal.GetDriverByName("GTiff")
|
||||||
|
dataset = driver.Create(output_path, im_width, im_height, 1, gdal.GDT_Float32)
|
||||||
|
|
||||||
|
if dataset is not None:
|
||||||
|
dataset.SetGeoTransform(im_geotrans) # 设置地理变换参数
|
||||||
|
dataset.SetProjection(im_proj) # 设置投影
|
||||||
|
|
||||||
|
dataset.GetRasterBand(1).WriteArray(im_data)
|
||||||
|
|
||||||
|
dataset.FlushCache() # 确保数据写入磁盘
|
||||||
|
dataset = None # 关闭文件
|
||||||
|
outfilepath=output_path.replace(".tiff",".png")
|
||||||
|
im_data_uint8=Strech_SquareRoot(im_data)
|
||||||
|
Image.fromarray(im_data_uint8).save(outfilepath, compress_level=0)
|
||||||
|
|
||||||
|
def geoXY2pixelXY(geo_x, geo_y, inv_gt):
|
||||||
|
pixel_x = inv_gt[0] + geo_x * inv_gt[1] + geo_y * inv_gt[2]
|
||||||
|
pixel_y = inv_gt[3] + geo_x * inv_gt[4] + geo_y * inv_gt[5]
|
||||||
|
return pixel_x, pixel_y
|
||||||
|
|
||||||
|
def label2pixelpoints(dotapath,tiff_inv_trans,methodstr,filterlabels):
|
||||||
|
dotalist = readDotaFile(dotapath,filterlabels)
|
||||||
|
if methodstr=="geolabel":
|
||||||
|
for i in range(len(dotalist)):
|
||||||
|
geo_x = dotalist[i].x1 # x1
|
||||||
|
geo_y = dotalist[i].y1
|
||||||
|
pixel_x, pixel_y = geoXY2pixelXY(geo_x, geo_y, tiff_inv_trans)
|
||||||
|
dotalist[i].x1 = pixel_x
|
||||||
|
dotalist[i].y1 = pixel_y
|
||||||
|
|
||||||
|
geo_x = dotalist[i].x2 # x2
|
||||||
|
geo_y = dotalist[i].y2
|
||||||
|
pixel_x, pixel_y = geoXY2pixelXY(geo_x, geo_y, tiff_inv_trans)
|
||||||
|
dotalist[i].x2 = pixel_x
|
||||||
|
dotalist[i].y2 = pixel_y
|
||||||
|
|
||||||
|
geo_x = dotalist[i].x3 # x3
|
||||||
|
geo_y = dotalist[i].y3
|
||||||
|
pixel_x, pixel_y = geoXY2pixelXY(geo_x, geo_y, tiff_inv_trans)
|
||||||
|
dotalist[i].x3 = pixel_x
|
||||||
|
dotalist[i].y3 = pixel_y
|
||||||
|
|
||||||
|
geo_x = dotalist[i].x4 # x4
|
||||||
|
geo_y = dotalist[i].y4
|
||||||
|
pixel_x, pixel_y = geoXY2pixelXY(geo_x, geo_y, tiff_inv_trans)
|
||||||
|
dotalist[i].x4 = pixel_x
|
||||||
|
dotalist[i].y4 = pixel_y
|
||||||
|
|
||||||
|
print("点数:", len(dotalist))
|
||||||
|
return dotalist
|
||||||
|
|
||||||
|
def getMaxEdge(dotalist, ids):
|
||||||
|
cornpoint = np.zeros((len(ids) * 4, 2))
|
||||||
|
for idx in range(len(ids)):
|
||||||
|
cornpoint[idx * 4 + 0, 0] = dotalist[ids[idx]].x1
|
||||||
|
cornpoint[idx * 4 + 1, 0] = dotalist[ids[idx]].x2
|
||||||
|
cornpoint[idx * 4 + 2, 0] = dotalist[ids[idx]].x3
|
||||||
|
cornpoint[idx * 4 + 3, 0] = dotalist[ids[idx]].x4
|
||||||
|
|
||||||
|
cornpoint[idx * 4 + 0, 1] = dotalist[ids[idx]].y1
|
||||||
|
cornpoint[idx * 4 + 1, 1] = dotalist[ids[idx]].y2
|
||||||
|
cornpoint[idx * 4 + 2, 1] = dotalist[ids[idx]].y3
|
||||||
|
cornpoint[idx * 4 + 3, 1] = dotalist[ids[idx]].y4
|
||||||
|
|
||||||
|
xedge = np.max(cornpoint[:, 0]) - np.min(cornpoint[:, 0])
|
||||||
|
yedge = np.max(cornpoint[:, 1]) - np.min(cornpoint[:, 1])
|
||||||
|
|
||||||
|
edgelen = xedge if xedge > yedge else yedge
|
||||||
|
return edgelen
|
||||||
|
|
||||||
|
def getExternCenter(dotalist, ids):
|
||||||
|
cornpoint = np.zeros((len(ids) * 4, 2))
|
||||||
|
for idx in range(len(ids)):
|
||||||
|
cornpoint[idx * 4 + 0, 0] = dotalist[ids[idx]].x1
|
||||||
|
cornpoint[idx * 4 + 1, 0] = dotalist[ids[idx]].x2
|
||||||
|
cornpoint[idx * 4 + 2, 0] = dotalist[ids[idx]].x3
|
||||||
|
cornpoint[idx * 4 + 3, 0] = dotalist[ids[idx]].x4
|
||||||
|
|
||||||
|
cornpoint[idx * 4 + 0, 1] = dotalist[ids[idx]].y1
|
||||||
|
cornpoint[idx * 4 + 1, 1] = dotalist[ids[idx]].y2
|
||||||
|
cornpoint[idx * 4 + 2, 1] = dotalist[ids[idx]].y3
|
||||||
|
cornpoint[idx * 4 + 3, 1] = dotalist[ids[idx]].y4
|
||||||
|
|
||||||
|
minX = np.min(cornpoint[:, 0])
|
||||||
|
minY = np.min(cornpoint[:, 1])
|
||||||
|
maxX = np.max(cornpoint[:, 0])
|
||||||
|
maxY = np.max(cornpoint[:, 1])
|
||||||
|
centerX = (minX + maxX) / 2
|
||||||
|
centerY = (minY + maxY) / 2
|
||||||
|
return [centerX, centerY, minX, minY, maxX, maxY]
|
||||||
|
|
||||||
|
def drawSliceRasterPrivew(tiff_data,dotalist,clusterDict):
|
||||||
|
# 绘制图形
|
||||||
|
# 创建图形和坐标轴
|
||||||
|
fig, ax = plt.subplots(figsize=(20, 16))
|
||||||
|
ax.imshow(tiff_data, cmap='gray')
|
||||||
|
# 绘制每个目标的矩形框并标注坐标
|
||||||
|
for i in range(len(dotalist)):
|
||||||
|
# 提取x和y坐标
|
||||||
|
x_coords = [dotalist[i].x1, dotalist[i].x2, dotalist[i].x3, dotalist[i].x4]
|
||||||
|
y_coords = [dotalist[i].y1, dotalist[i].y2, dotalist[i].y3, dotalist[i].y4]
|
||||||
|
|
||||||
|
# 计算最小外接矩形(AABB)
|
||||||
|
x_min, x_max = min(x_coords), max(x_coords)
|
||||||
|
y_min, y_max = min(y_coords), max(y_coords)
|
||||||
|
width = x_max - x_min
|
||||||
|
height = y_max - y_min
|
||||||
|
|
||||||
|
# 绘制无填充矩形框(仅红色边框)
|
||||||
|
rect = patches.Rectangle(
|
||||||
|
(x_min, y_min), width, height,
|
||||||
|
linewidth=2, edgecolor='red', facecolor='none' # 关键:facecolor='none'
|
||||||
|
)
|
||||||
|
ax.add_patch(rect)
|
||||||
|
|
||||||
|
# ax.annotate(f'({x},{y})', xy=(x, y), xytext=(5, 5),
|
||||||
|
# textcoords='offset points', fontsize=10,
|
||||||
|
# bbox=dict(boxstyle='round,pad=0.5', fc='white', alpha=0.8))
|
||||||
|
|
||||||
|
# 在矩形中心标注目标编号
|
||||||
|
center_x = sum(x_coords) / 4
|
||||||
|
center_y = sum(y_coords) / 4
|
||||||
|
ax.text(center_x, center_y, str(i),
|
||||||
|
ha='center', va='center', fontsize=6, color='red')
|
||||||
|
|
||||||
|
# 以类别中心为中心绘制四边形
|
||||||
|
for k in clusterDict:
|
||||||
|
# 绘制无填充矩形框(仅红色边框)
|
||||||
|
minX = clusterDict[k]["p"][0]
|
||||||
|
minY = clusterDict[k]["p"][1]
|
||||||
|
rect = patches.Rectangle(
|
||||||
|
(minX , minY), SliceSize, SliceSize,
|
||||||
|
linewidth=2, edgecolor='green', facecolor='none' # 关键:facecolor='none'
|
||||||
|
)
|
||||||
|
ax.add_patch(rect)
|
||||||
|
ax.text(minX+512, minY+512, str(k),
|
||||||
|
ha='center', va='center', fontsize=6, color='green')
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
print("绘图结束")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def find_optimal_slices(H, W, boxes, patch_size=1024, max_overlap_rate=0.2):
|
||||||
|
"""
|
||||||
|
Compute optimal slice positions for the image to maximize the number of fully contained rectangular patches (boxes),
|
||||||
|
while ensuring the overlap rate between any two slices does not exceed the specified maximum.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- H: Height of the image.
|
||||||
|
- W: Width of the image.
|
||||||
|
- boxes: List of tuples or lists, each containing (x1, y1, x2, y2) where (x1, y1) is the top-left and (x2, y2) is the bottom-right of a rectangular patch.
|
||||||
|
- patch_size: Size of each slice (square, e.g., 1024).
|
||||||
|
- max_overlap_rate: Maximum allowed overlap rate (e.g., 0.2).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- slices: List of (sx, sy) starting positions for the slices.
|
||||||
|
- covered_count: Number of patches that appear fully in at least one slice.
|
||||||
|
"""
|
||||||
|
overlap_max = patch_size * max_overlap_rate
|
||||||
|
stride = patch_size - floor(overlap_max) # Ensures overlap <= max_overlap_rate in linear dimensions
|
||||||
|
|
||||||
|
N = len(boxes)
|
||||||
|
x_covered = [set() for _ in range(stride)]
|
||||||
|
y_covered = [set() for _ in range(stride)]
|
||||||
|
|
||||||
|
for i in range(N):
|
||||||
|
x1, y1, x2, y2 = boxes[i]
|
||||||
|
b_w = x2 - x1
|
||||||
|
b_h = y2 - y1
|
||||||
|
|
||||||
|
# For x-dimension
|
||||||
|
lx = max(0, x2 - patch_size)
|
||||||
|
rx = min(W - patch_size, x1)
|
||||||
|
if lx <= rx:
|
||||||
|
start_x = ceil(lx)
|
||||||
|
end_x = floor(rx)
|
||||||
|
l_x = end_x - start_x + 1
|
||||||
|
if l_x > 0:
|
||||||
|
if l_x >= stride:
|
||||||
|
for ox in range(stride):
|
||||||
|
x_covered[ox].add(i)
|
||||||
|
else:
|
||||||
|
for sx in range(start_x, end_x + 1):
|
||||||
|
ox = sx % stride
|
||||||
|
x_covered[ox].add(i)
|
||||||
|
|
||||||
|
# For y-dimension
|
||||||
|
ly = max(0, y2 - patch_size)
|
||||||
|
ry = min(H - patch_size, y1)
|
||||||
|
if ly <= ry:
|
||||||
|
start_y = ceil(ly)
|
||||||
|
end_y = floor(ry)
|
||||||
|
l_y = end_y - start_y + 1
|
||||||
|
if l_y > 0:
|
||||||
|
if l_y >= stride:
|
||||||
|
for oy in range(stride):
|
||||||
|
y_covered[oy].add(i)
|
||||||
|
else:
|
||||||
|
for sy in range(start_y, end_y + 1):
|
||||||
|
oy = sy % stride
|
||||||
|
y_covered[oy].add(i)
|
||||||
|
|
||||||
|
# Find the best offset pair (ox, oy) that maximizes covered patches
|
||||||
|
max_covered = 0
|
||||||
|
best_ox = 0
|
||||||
|
best_oy = 0
|
||||||
|
for ox in range(stride):
|
||||||
|
for oy in range(stride):
|
||||||
|
current_covered = len(x_covered[ox] & y_covered[oy])
|
||||||
|
if current_covered > max_covered:
|
||||||
|
max_covered = current_covered
|
||||||
|
best_ox = ox
|
||||||
|
best_oy = oy
|
||||||
|
|
||||||
|
# Generate the slice positions using the best offsets and stride
|
||||||
|
slices = []
|
||||||
|
sx = best_ox
|
||||||
|
while sx + patch_size <= W:
|
||||||
|
sy = best_oy
|
||||||
|
while sy + patch_size <= H:
|
||||||
|
slices.append((sx, sy))
|
||||||
|
sy += stride
|
||||||
|
sx += stride
|
||||||
|
|
||||||
|
return slices, max_covered
|
||||||
|
|
||||||
|
def check_B_in_A(A,B):
|
||||||
|
"""
|
||||||
|
判断A包含B
|
||||||
|
:param A: [x0,y0.w.h]
|
||||||
|
:param B: [x0,y0.w.h]
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
# 解构矩形A和B的参数
|
||||||
|
Ax0, Ay0, Aw, Ah = A
|
||||||
|
Bx0, By0, Bw, Bh = B
|
||||||
|
|
||||||
|
# 计算矩形A和B的右边界和下边界
|
||||||
|
Ax1 = Ax0 + Aw
|
||||||
|
Ay1 = Ay0 + Ah
|
||||||
|
|
||||||
|
Bx1 = Bx0 + Bw
|
||||||
|
By1 = By0 + Bh
|
||||||
|
|
||||||
|
# 判断B是否完全在A内部
|
||||||
|
return (Bx0 >= Ax0) and (Bx1 <= Ax1) and (By0 >= Ay0) and (By1 <= Ay1)
|
||||||
|
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# 切分算法流程图
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
def getclusterDict(dotalist,imgheight,imgwidth,pitchSize=1024,max_overlap_rate=0.2):
|
||||||
|
"""
|
||||||
|
生成切片数据
|
||||||
|
:param dotalist: 样本集
|
||||||
|
:param imgheight: 图像高度
|
||||||
|
:param imgwidth: 图像宽度
|
||||||
|
:return: 切片类型
|
||||||
|
"""
|
||||||
|
boxs=[]
|
||||||
|
for i in range(len(dotalist)):
|
||||||
|
xs=np.array([dotalist[i].x1,dotalist[i].x2,dotalist[i].x3, dotalist[i].x4])
|
||||||
|
ys=np.array([dotalist[i].y1,dotalist[i].y2,dotalist[i].y3, dotalist[i].y4])
|
||||||
|
x1=np.min(xs)
|
||||||
|
x2=np.max(xs)
|
||||||
|
y1=np.min(ys)
|
||||||
|
y2=np.max(ys)
|
||||||
|
boxs.append([x1,y1,x2,y2]) # x1, y1, x2, y2 = boxes[i]
|
||||||
|
|
||||||
|
slices, max_covered=find_optimal_slices(imgheight,imgwidth,boxs,pitchSize,max_overlap_rate)
|
||||||
|
|
||||||
|
clusterDict={}
|
||||||
|
|
||||||
|
waitContaindota=[]
|
||||||
|
hasContainIds=[]
|
||||||
|
for i in range(len(slices)):
|
||||||
|
sx,sy=slices[i]
|
||||||
|
clusterDict[i]={"p":[sx,sy],"id":[]}
|
||||||
|
slicesExten=[sx,sy,SliceSize,SliceSize]
|
||||||
|
for ids in range(len(dotalist)):
|
||||||
|
if ids in hasContainIds:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
[centerX, centerY, minX, minY, maxX, maxY]=getExternCenter(dotalist, [ids])
|
||||||
|
dotaExtend=[minX,minY,maxX-minX,maxY-minY]
|
||||||
|
if check_B_in_A(slicesExten,dotaExtend):
|
||||||
|
print("True: ", slicesExten, dotaExtend)
|
||||||
|
clusterDict[i]["id"].append(ids)
|
||||||
|
# hasContainIds.append(ids)
|
||||||
|
else:
|
||||||
|
print("False: ",slicesExten,dotaExtend)
|
||||||
|
|
||||||
|
for ids in range(len(dotalist)):
|
||||||
|
if ids in hasContainIds:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
waitContaindota.append(ids)
|
||||||
|
print("No in slice dota : ",str(dotalist[ids]) )
|
||||||
|
|
||||||
|
print("no process ids ",str(waitContaindota))
|
||||||
|
return clusterDict
|
||||||
|
|
||||||
|
|
||||||
|
def drawSlictplot(clusterDict,dotalist,tiff_data,nrows=10,ncols=9):
|
||||||
|
"""
|
||||||
|
:param clusterDict: clusterDict[i]={"p":[sx,sy],"id":[]}
|
||||||
|
:param dotalist: (x1, y1, x2, y2, x3, y3, x4, y4 clsname diffcule)
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
fig, axes = plt.subplots(nrows=nrows,ncols=ncols,figsize=(20, 16))
|
||||||
|
plt.tight_layout(pad=3.0)
|
||||||
|
print(tiff_data.shape)
|
||||||
|
# 9*10
|
||||||
|
subid=0
|
||||||
|
for cid in clusterDict:
|
||||||
|
sx,sy=clusterDict[cid]["p"]
|
||||||
|
colid=subid//nrows
|
||||||
|
rowid=subid%nrows
|
||||||
|
subid=subid+1
|
||||||
|
ax = axes[rowid]
|
||||||
|
ax.set_title(str(cid))
|
||||||
|
sliceData=tiff_data[sy:(sy+SliceSize),sx:(sx+SliceSize)]
|
||||||
|
ax.imshow(sliceData, cmap='gray')
|
||||||
|
|
||||||
|
for did in clusterDict[cid]["id"] :
|
||||||
|
# 提取x和y坐标
|
||||||
|
x_coords = [dotalist[did].x1-sx, dotalist[did].x2-sx, dotalist[did].x3-sx, dotalist[did].x4-sx]
|
||||||
|
y_coords = [dotalist[did].y1-sy, dotalist[did].y2-sy, dotalist[did].y3-sy, dotalist[did].y4-sy]
|
||||||
|
|
||||||
|
# 计算最小外接矩形(AABB)
|
||||||
|
x_min, x_max = min(x_coords), max(x_coords)
|
||||||
|
y_min, y_max = min(y_coords), max(y_coords)
|
||||||
|
width = x_max - x_min
|
||||||
|
height = y_max - y_min
|
||||||
|
|
||||||
|
|
||||||
|
# 绘制无填充矩形框(仅红色边框)
|
||||||
|
rect = patches.Rectangle(
|
||||||
|
(x_min, y_min), width, height,
|
||||||
|
linewidth=2, edgecolor='red', facecolor='none' # 关键:facecolor='none'
|
||||||
|
)
|
||||||
|
ax.add_patch(rect)
|
||||||
|
|
||||||
|
# 在矩形中心标注目标编号
|
||||||
|
center_x = x_min+width/2
|
||||||
|
center_y = y_min+height/2
|
||||||
|
ax.text(center_x, center_y, str(did),
|
||||||
|
ha='center', va='center', fontsize=6, color='red')
|
||||||
|
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
print("绘图结束")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def slictDataAndOutlabel(clusterDict,dotalist,tiff_data,tiff_basename,outfolderpath,im_geotrans, im_proj):
|
||||||
|
"""
|
||||||
|
切分标签,输出结果与文件
|
||||||
|
:param clusterDict:
|
||||||
|
:param dotalist:
|
||||||
|
:param tiff_data:
|
||||||
|
:param tiff_name:
|
||||||
|
:param outfolderpath:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
for cid in clusterDict:
|
||||||
|
sx, sy = clusterDict[cid]["p"]
|
||||||
|
if len(clusterDict[cid]["id"])==0:
|
||||||
|
continue
|
||||||
|
sliceData = tiff_data[sy:(sy + SliceSize), sx:(sx + SliceSize)]
|
||||||
|
outbinname="{}_{}.tiff".format(tiff_basename,cid)
|
||||||
|
outlabelname="{}_{}.txt".format(tiff_basename,cid)
|
||||||
|
# 获取样本列表
|
||||||
|
outdotalist=[]
|
||||||
|
for did in clusterDict[cid]["id"] :
|
||||||
|
x1=dotalist[did].x1-sx
|
||||||
|
x2=dotalist[did].x2-sx
|
||||||
|
x3=dotalist[did].x3-sx
|
||||||
|
x4=dotalist[did].x4-sx
|
||||||
|
y1=dotalist[did].y1-sy
|
||||||
|
y2=dotalist[did].y2-sy
|
||||||
|
y3=dotalist[did].y3-sy
|
||||||
|
y4=dotalist[did].y4-sy
|
||||||
|
tempdota=createDota(x1,y1,x2,y2,x3,y3,x4,y4,dotalist[did].clsname,dotalist[did].difficulty)
|
||||||
|
outdotalist.append(tempdota)
|
||||||
|
|
||||||
|
outlabelpath=os.path.join(outfolderpath,outlabelname)
|
||||||
|
outbinpath=os.path.join(outfolderpath,outbinname)
|
||||||
|
|
||||||
|
temp_im_geotrans=[tempi for tempi in im_geotrans]
|
||||||
|
# 处理 0,3
|
||||||
|
temp_im_geotrans[0]=im_geotrans[0]+sx*im_geotrans[1]+im_geotrans[2]*sy # x
|
||||||
|
temp_im_geotrans[3]=im_geotrans[3]+sx*im_geotrans[4]+im_geotrans[5]*sy # y
|
||||||
|
write_envi(sliceData,temp_im_geotrans,im_proj,outbinpath)
|
||||||
|
writerDotaFile(outdotalist,outlabelpath)
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# 处理流程图
|
||||||
|
##########################################################################
|
||||||
|
def DataSampleSliceRasterProcess(inbinfile,labelfilepath,outfolderpath,methodstr,filterlabels):
|
||||||
|
tiff_proj, tiff_trans, tiff_data = read_tif(inbinfile)
|
||||||
|
tiff_inv_trans = gdal.InvGeoTransform(tiff_trans)
|
||||||
|
dotalist=label2pixelpoints(labelfilepath,tiff_inv_trans,methodstr,filterlabels)
|
||||||
|
imgheight, imgwidth=tiff_data.shape
|
||||||
|
clusterDict=getclusterDict(dotalist,imgheight,imgwidth,SliceSize,0.25)
|
||||||
|
# drawSliceRasterPrivew(tiff_data, dotalist, clusterDict)
|
||||||
|
nrows=int(len(clusterDict)/1+1)
|
||||||
|
# drawSlictplot(clusterDict, dotalist, tiff_data, nrows, 1)
|
||||||
|
tiff_name=os.path.basename(inbinfile)
|
||||||
|
tiff_basename=os.path.splitext(tiff_name)[0]
|
||||||
|
slictDataAndOutlabel(clusterDict, dotalist, tiff_data, tiff_basename, outfolderpath, tiff_trans, tiff_proj)
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getParams():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-i','--inbinfile',type=str,default=r'D:\港口\Geo_bc2-sm-org-vv-20231016t135315-008424-0020e8-01.tiff', help='输入tiff的bin文件')
|
||||||
|
parser.add_argument('-l', '--labelfilepath',type=str,default=r"D:\港口\港口dota\Geo_bc2-sm-org-vv-20231016t135315-008424-0020e8-01.military_harbor.txt", help='输入标注')
|
||||||
|
parser.add_argument('-o', '--outfolderpath',type=str,default=r'D:\港口\切片结果', help='切片文件夹地址')
|
||||||
|
parser.add_argument('-f', '--filterlabel',type=str,default=r'mix_airport;civil_harbor;military_harbor;no_harbor', help='标签过滤')
|
||||||
|
group = parser.add_mutually_exclusive_group()
|
||||||
|
group.add_argument(
|
||||||
|
'--geolabel',
|
||||||
|
action='store_const',
|
||||||
|
const='geolabel',
|
||||||
|
dest='method',
|
||||||
|
help='标注坐标点为地理坐标'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--pixellabel',
|
||||||
|
action='store_const',
|
||||||
|
const='pixellabel',
|
||||||
|
dest='method',
|
||||||
|
help='标注坐标系统为输入影像的像空间坐标'
|
||||||
|
)
|
||||||
|
parser.set_defaults(method='geolabel')
|
||||||
|
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
parser = getParams()
|
||||||
|
inbinfile=parser.inbinfile
|
||||||
|
labelfilepath=parser.labelfilepath
|
||||||
|
outfolderpath=parser.outfolderpath
|
||||||
|
methodstr= parser.method
|
||||||
|
filterlabels=parser.filterlabel.strip().split(';')
|
||||||
|
print('inbinfile=',inbinfile)
|
||||||
|
print('labelfilepath=',labelfilepath)
|
||||||
|
print('outfolderpath=',outfolderpath)
|
||||||
|
print('methodstr=',methodstr)
|
||||||
|
print('filterlabels=',filterlabels)
|
||||||
|
DataSampleSliceRasterProcess(inbinfile, labelfilepath, outfolderpath,methodstr,filterlabels)
|
||||||
|
print("样本切分完成")
|
||||||
|
exit(2)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
exit(3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
from glob import glob
|
||||||
|
from pathlib import Path
|
||||||
|
from multiprocessing import Pool
|
||||||
|
########################################################
|
||||||
|
# 函数区
|
||||||
|
########################################################
|
||||||
|
|
||||||
|
spacetySliceEnvPathExEPath=r"d:\ProgramData\anaconda3\envs\spacetySliceEnv\python.exe"
|
||||||
|
|
||||||
|
def find_tif_files_pathlib(directory):
|
||||||
|
"""
|
||||||
|
使用pathlib.Path.rglob递归查找指定目录下所有.tif和.tiff文件
|
||||||
|
|
||||||
|
参数:
|
||||||
|
directory (str): 要搜索的根目录路径
|
||||||
|
|
||||||
|
返回:
|
||||||
|
list: 包含所有找到的.tif/.tiff文件完整路径的列表
|
||||||
|
"""
|
||||||
|
path = Path(directory)
|
||||||
|
# 使用rglob递归匹配所有.tif和.tiff文件
|
||||||
|
tif_files = list(path.rglob('*.tiff'))+list(path.rglob('*.tif'))
|
||||||
|
# 将Path对象转换为字符串路径
|
||||||
|
return [str(file) for file in tif_files]
|
||||||
|
|
||||||
|
|
||||||
|
def find_txt_files_pathlib(directory):
|
||||||
|
"""
|
||||||
|
使用pathlib.Path.rglob递归查找指定目录下所有.tif和.tiff文件
|
||||||
|
|
||||||
|
参数:
|
||||||
|
directory (str): 要搜索的根目录路径
|
||||||
|
|
||||||
|
返回:
|
||||||
|
list: 包含所有找到的.tif/.tiff文件完整路径的列表
|
||||||
|
"""
|
||||||
|
path = Path(directory)
|
||||||
|
# 使用rglob递归匹配所有.tif和.tiff文件
|
||||||
|
tif_files = list(path.rglob('*.txt'))
|
||||||
|
# 将Path对象转换为字符串路径
|
||||||
|
return [str(file) for file in tif_files]
|
||||||
|
|
||||||
|
|
||||||
|
def matchTiff_Txt(tiffpaths,txtPaths):
|
||||||
|
match_results={}
|
||||||
|
tiffID=0
|
||||||
|
for tid in range(len(tiffpaths)):
|
||||||
|
tiffID=tiffID+1
|
||||||
|
match_results[tiffID]={"tiff":tiffpaths[tid],"txt":[]}
|
||||||
|
rootname=Path(tiffpaths[tid]).stem
|
||||||
|
for txtpath in txtPaths:
|
||||||
|
txtrootname=Path(txtpath).stem
|
||||||
|
if txtrootname.startswith(rootname):
|
||||||
|
match_results[tiffID]["txt"].append(txtpath)
|
||||||
|
|
||||||
|
return match_results
|
||||||
|
|
||||||
|
def sliceTiFFAndTxt(match_meta,outfolderpath):
|
||||||
|
resultTxt=""
|
||||||
|
programpath = r"R:\TYSAR-德清院\A-预处理-未标注\A0-算法版本\AA\SpacetySliceDataTools\LabelPortShipRasterSlice\DataSamplePortSliceRaster_AA.py"
|
||||||
|
tiffPath=match_meta["tiff"]
|
||||||
|
for txtpath in match_meta["txt"]:
|
||||||
|
cmdtxt = r"{} {} -i {} -l {} -o {}".format(spacetySliceEnvPathExEPath, programpath,
|
||||||
|
tiffPath,
|
||||||
|
txtpath,
|
||||||
|
outfolderpath
|
||||||
|
)
|
||||||
|
|
||||||
|
if os.system(cmdtxt) == 2:
|
||||||
|
resultTxt="{}\nsucess: {}".format(resultTxt,txtpath)
|
||||||
|
print("sucess:", cmdtxt)
|
||||||
|
|
||||||
|
else:
|
||||||
|
resultTxt = "{}\nfailed: {}".format(resultTxt, txtpath)
|
||||||
|
print("failed:", cmdtxt)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
preFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250813-不分类\0-原图"
|
||||||
|
dotafolderPath=r"D:\港口\港口dota"
|
||||||
|
outfolderPath=r"D:\港口\切片结果"
|
||||||
|
tiffPaths = find_tif_files_pathlib(preFolderPath)
|
||||||
|
txtPaths = find_txt_files_pathlib(dotafolderPath)
|
||||||
|
match_results=matchTiff_Txt(tiffPaths,txtPaths)
|
||||||
|
|
||||||
|
for tiffID in match_results:
|
||||||
|
match_meta=match_results[tiffID]
|
||||||
|
sliceTiFFAndTxt(match_meta,outfolderPath)
|
||||||
|
|
||||||
|
preFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250818-不分类\0-原图"
|
||||||
|
dotafolderPath=r"D:\港口\港口dota"
|
||||||
|
outfolderPath=r"D:\港口\切片结果"
|
||||||
|
tiffPaths = find_tif_files_pathlib(preFolderPath)
|
||||||
|
txtPaths = find_txt_files_pathlib(dotafolderPath)
|
||||||
|
match_results=matchTiff_Txt(tiffPaths,txtPaths)
|
||||||
|
|
||||||
|
for tiffID in match_results:
|
||||||
|
match_meta=match_results[tiffID]
|
||||||
|
sliceTiFFAndTxt(match_meta,outfolderPath)
|
||||||
|
|
||||||
|
preFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\0-原图"
|
||||||
|
dotafolderPath=r"D:\港口\港口dota"
|
||||||
|
outfolderPath=r"D:\港口\切片结果"
|
||||||
|
tiffPaths = find_tif_files_pathlib(preFolderPath)
|
||||||
|
txtPaths = find_txt_files_pathlib(dotafolderPath)
|
||||||
|
match_results=matchTiff_Txt(tiffPaths,txtPaths)
|
||||||
|
|
||||||
|
for tiffID in match_results:
|
||||||
|
match_meta=match_results[tiffID]
|
||||||
|
sliceTiFFAndTxt(match_meta,outfolderPath)
|
||||||
|
|
||||||
|
preFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\0-原图"
|
||||||
|
dotafolderPath=r"D:\港口\港口dota"
|
||||||
|
outfolderPath=r"D:\港口\切片结果"
|
||||||
|
tiffPaths = find_tif_files_pathlib(preFolderPath)
|
||||||
|
txtPaths = find_txt_files_pathlib(dotafolderPath)
|
||||||
|
match_results=matchTiff_Txt(tiffPaths,txtPaths)
|
||||||
|
|
||||||
|
for tiffID in match_results:
|
||||||
|
match_meta=match_results[tiffID]
|
||||||
|
sliceTiFFAndTxt(match_meta,outfolderPath)
|
||||||
|
|
||||||
|
preFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250910-不分类\0-原图"
|
||||||
|
dotafolderPath=r"D:\港口\港口dota"
|
||||||
|
outfolderPath=r"D:\港口\切片结果"
|
||||||
|
tiffPaths = find_tif_files_pathlib(preFolderPath)
|
||||||
|
txtPaths = find_txt_files_pathlib(dotafolderPath)
|
||||||
|
match_results=matchTiff_Txt(tiffPaths,txtPaths)
|
||||||
|
|
||||||
|
for tiffID in match_results:
|
||||||
|
match_meta=match_results[tiffID]
|
||||||
|
sliceTiFFAndTxt(match_meta,outfolderPath)
|
||||||
|
|
@ -0,0 +1,446 @@
|
||||||
|
from osgeo import ogr
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
from osgeo import ogr
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
from osgeo import ogr, gdal
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import numpy as np
|
||||||
|
from scipy.spatial import KDTree
|
||||||
|
from tools.DotaOperator import DotaObj,readDotaFile,writerDotaFile,createDota
|
||||||
|
from glob import glob
|
||||||
|
from pathlib import Path
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
MLCName="MLC" # M
|
||||||
|
JLCName="JLC" # J
|
||||||
|
MJLCName="MJLC" # JM 混合
|
||||||
|
NOLCName="NOLC" # 没有港口
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def find_tif_files_pathlib(directory):
|
||||||
|
path = Path(directory)
|
||||||
|
# 使用rglob递归匹配所有.tif和.tiff文件
|
||||||
|
tif_files = list(path.rglob('*.tiff'))+list(path.rglob('*.tif'))
|
||||||
|
# 将Path对象转换为字符串路径
|
||||||
|
return [str(file) for file in tif_files]
|
||||||
|
|
||||||
|
|
||||||
|
def find_srcPath(srcFolder):
|
||||||
|
root_path = Path(srcFolder)
|
||||||
|
target_path = [folderpath for folderpath in root_path.rglob("*") if folderpath.is_dir() and folderpath.name=="0-原图"]
|
||||||
|
tiff_files = []
|
||||||
|
for folderpath in target_path:
|
||||||
|
tiff_files=tiff_files+find_tif_files_pathlib(folderpath)
|
||||||
|
|
||||||
|
tiff_dict={}
|
||||||
|
for filepath in tiff_files:
|
||||||
|
rootname=Path(filepath).stem
|
||||||
|
tiff_dict[rootname]=filepath
|
||||||
|
|
||||||
|
return tiff_dict
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def read_tifInfo(path):
|
||||||
|
dataset = gdal.Open(path) # 打开TIF文件
|
||||||
|
if dataset is None:
|
||||||
|
print("无法打开文件,读取文件信息")
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
cols = dataset.RasterXSize # 图像宽度
|
||||||
|
rows = dataset.RasterYSize # 图像高度
|
||||||
|
bands = dataset.RasterCount
|
||||||
|
im_proj = dataset.GetProjection() # 获取投影信息
|
||||||
|
im_Geotrans = dataset.GetGeoTransform() # 获取仿射变换信息
|
||||||
|
# im_data = dataset.ReadAsArray(0, 0, cols, rows) # 读取栅格数据为NumPy数组
|
||||||
|
print("行数:", rows)
|
||||||
|
print("列数:", cols)
|
||||||
|
print("波段:", bands)
|
||||||
|
x1=im_Geotrans[0]+im_Geotrans[1]*0
|
||||||
|
x2=im_Geotrans[0]+im_Geotrans[1]*cols
|
||||||
|
|
||||||
|
y1=im_Geotrans[3]+im_Geotrans[5]*0
|
||||||
|
y2=im_Geotrans[3]+im_Geotrans[5]*rows
|
||||||
|
|
||||||
|
xmin=min(x1,x2)
|
||||||
|
xmax=max(x1,x2)
|
||||||
|
ymin=min(y1,y2)
|
||||||
|
ymax=max(y1,y2)
|
||||||
|
|
||||||
|
geoExtend=[xmin,ymin,xmax,ymax]
|
||||||
|
del dataset # 关闭数据集
|
||||||
|
return im_proj, im_Geotrans,geoExtend
|
||||||
|
|
||||||
|
def getshapefileInfo(shp_path):
|
||||||
|
"""
|
||||||
|
将Shapefile转换为DOTA格式
|
||||||
|
:param shp_path: Shapefile文件路径
|
||||||
|
"""
|
||||||
|
|
||||||
|
geom_points=[]
|
||||||
|
|
||||||
|
print("shapefile: ",shp_path)
|
||||||
|
|
||||||
|
# 注册所有驱动
|
||||||
|
ogr.RegisterAll()
|
||||||
|
|
||||||
|
# 打开Shapefile文件
|
||||||
|
driver = ogr.GetDriverByName('ESRI Shapefile')
|
||||||
|
datasource = driver.Open(shp_path, 0)
|
||||||
|
if datasource is None:
|
||||||
|
print("无法打开Shapefile文件")
|
||||||
|
return
|
||||||
|
|
||||||
|
print("layer count: ",datasource.GetLayerCount())
|
||||||
|
for layerid in range(datasource.GetLayerCount()):
|
||||||
|
print("layer id: ",layerid)
|
||||||
|
# 获取图层
|
||||||
|
layer = datasource.GetLayer(layerid)
|
||||||
|
layer_defn=layer.GetLayerDefn()
|
||||||
|
field_count=layer_defn.GetFieldCount()
|
||||||
|
|
||||||
|
print("field_count:", field_count)
|
||||||
|
for i in range (field_count):
|
||||||
|
field_defn=layer_defn.GetFieldDefn(i)
|
||||||
|
field_name=field_defn.GetName()
|
||||||
|
field_type=field_defn.GetType()
|
||||||
|
field_type_name=field_defn.GetFieldTypeName(field_type)
|
||||||
|
print("field_name:", field_name, field_type_name, field_type_name)
|
||||||
|
|
||||||
|
for feature in layer:
|
||||||
|
geom = feature.GetGeometryRef()
|
||||||
|
if geom.GetGeometryName() == 'POINT':
|
||||||
|
x=geom.GetX()
|
||||||
|
y=geom.GetY()
|
||||||
|
geom_points.append([x,y])
|
||||||
|
return np.array(geom_points)
|
||||||
|
|
||||||
|
|
||||||
|
def getTiffsInfo(tiffnames,folderpath):
|
||||||
|
"""
|
||||||
|
获取所有影像的几何信息
|
||||||
|
Args:
|
||||||
|
tiff_paths: tiff列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
tiffdict={}
|
||||||
|
for tiff_name in tiffnames:
|
||||||
|
if tiff_name.endswith(".tiff"):
|
||||||
|
tiff_path=os.path.join(folderpath,tiff_name)
|
||||||
|
im_proj, im_Geotrans, geoExtend=read_tifInfo(tiff_path)
|
||||||
|
tiffdict[tiff_name]={"geoExtend":geoExtend,"geoTrans":im_Geotrans,"imProj":im_proj}
|
||||||
|
return tiffdict
|
||||||
|
|
||||||
|
|
||||||
|
def getMJSignal(tiffpath,shipPortTree,outfolderPath):
|
||||||
|
rootname=Path(tiffpath).stem
|
||||||
|
portTxtpath=os.path.join(outfolderPath,rootname+".txt")
|
||||||
|
im_proj, im_Geotrans, geoExtend = read_tifInfo(tiffpath) # geoExtend : [xmin,ymin,xmax,ymax]
|
||||||
|
[xmin, ymin, xmax, ymax]=geoExtend
|
||||||
|
center_x = (xmin + xmax) / 2.0
|
||||||
|
center_y = (ymin + ymax) / 2.0
|
||||||
|
center_point = [center_x, center_y]
|
||||||
|
# 2. 计算能够覆盖整个矩形区域的最小半径(中心点到任一角点的最大距离)
|
||||||
|
radius_to_corner = np.sqrt((xmax - center_x) ** 2 + (ymax - center_y) ** 2)
|
||||||
|
|
||||||
|
MLCFlag=False
|
||||||
|
JLCFlag=False
|
||||||
|
## MLC
|
||||||
|
if MLCName in shipPortTree and not shipPortTree[MLCName] is None:
|
||||||
|
# 3. 使用 query_ball_point 查找以中心点为圆心,radius_to_corner 为半径的圆内的所有点的索引
|
||||||
|
potential_indices = shipPortTree[MLCName].query_ball_point(center_point, r=radius_to_corner)
|
||||||
|
|
||||||
|
# 4. 获取这些潜在点的实际坐标
|
||||||
|
# 假设你的 KDTree 是从 data_points 构建的:MLCTree = KDTree(data_points)
|
||||||
|
potential_points = shipPortTree[MLCName].data[potential_indices] # 这是所有潜在点的坐标数组
|
||||||
|
|
||||||
|
# 5. 进行精确的矩形范围过滤
|
||||||
|
# 条件判断:x 坐标在 xmin 和 xmax 之间,且 y 坐标在 ymin 和 ymax 之间
|
||||||
|
x_in_range = (potential_points[:, 0] >= xmin) & (potential_points[:, 0] <= xmax)
|
||||||
|
y_in_range = (potential_points[:, 1] >= ymin) & (potential_points[:, 1] <= ymax)
|
||||||
|
within_rect_indices_mask = x_in_range & y_in_range
|
||||||
|
|
||||||
|
# 6. 获取最终在矩形范围内的点的坐标(在原始 data_points 中的索引是 potential_indices[within_rect_indices_mask])
|
||||||
|
final_points = potential_points[within_rect_indices_mask]
|
||||||
|
|
||||||
|
# final_points 就是你要的矩形范围内的点
|
||||||
|
# 如果你需要的是这些点在原始数据中的索引,而不是坐标本身:
|
||||||
|
final_indices = np.array(potential_indices)[within_rect_indices_mask]
|
||||||
|
if final_points.shape[0]>0:
|
||||||
|
MLCFlag=True
|
||||||
|
with open(portTxtpath,"w",encoding="utf-8") as f:
|
||||||
|
for i in range(final_points.shape[0]):
|
||||||
|
f.write("{}\t\t{},{}\n".format("MLC",final_points[i,0],final_points[i,1]))
|
||||||
|
pass
|
||||||
|
if JLCName in shipPortTree and not shipPortTree[JLCName] is None:
|
||||||
|
# 3. 使用 query_ball_point 查找以中心点为圆心,radius_to_corner 为半径的圆内的所有点的索引
|
||||||
|
potential_indices = shipPortTree[JLCName].query_ball_point(center_point, r=radius_to_corner)
|
||||||
|
|
||||||
|
# 4. 获取这些潜在点的实际坐标
|
||||||
|
# 假设你的 KDTree 是从 data_points 构建的:MLCTree = KDTree(data_points)
|
||||||
|
potential_points = shipPortTree[JLCName].data[potential_indices] # 这是所有潜在点的坐标数组
|
||||||
|
|
||||||
|
# 5. 进行精确的矩形范围过滤
|
||||||
|
# 条件判断:x 坐标在 xmin 和 xmax 之间,且 y 坐标在 ymin 和 ymax 之间
|
||||||
|
x_in_range = (potential_points[:, 0] >= xmin) & (potential_points[:, 0] <= xmax)
|
||||||
|
y_in_range = (potential_points[:, 1] >= ymin) & (potential_points[:, 1] <= ymax)
|
||||||
|
within_rect_indices_mask = x_in_range & y_in_range
|
||||||
|
|
||||||
|
# 6. 获取最终在矩形范围内的点的坐标(在原始 data_points 中的索引是 potential_indices[within_rect_indices_mask])
|
||||||
|
final_points = potential_points[within_rect_indices_mask]
|
||||||
|
|
||||||
|
# final_points 就是你要的矩形范围内的点
|
||||||
|
# 如果你需要的是这些点在原始数据中的索引,而不是坐标本身:
|
||||||
|
final_indices = np.array(potential_indices)[within_rect_indices_mask]
|
||||||
|
if final_points.shape[0]>0:
|
||||||
|
JLCFlag=True
|
||||||
|
with open(portTxtpath,"a",encoding="utf-8") as f:
|
||||||
|
for i in range(final_points.shape[0]):
|
||||||
|
f.write("{}\t\t{},{}\n".format("JLC",final_points[i,0],final_points[i,1]))
|
||||||
|
pass
|
||||||
|
# 处理软件
|
||||||
|
return MLCFlag,JLCFlag
|
||||||
|
|
||||||
|
|
||||||
|
def getTiffInPort(shipPortTree,srcFolderPath_0img,outTiffInfoFilePath,outfolderPath):
|
||||||
|
tiffpaths=find_tif_files_pathlib(srcFolderPath_0img)
|
||||||
|
tiffLCPort={
|
||||||
|
MLCName:[],
|
||||||
|
JLCName:[],
|
||||||
|
MJLCName:[],
|
||||||
|
NOLCName:[]
|
||||||
|
}
|
||||||
|
for tiffpath in tiffpaths:
|
||||||
|
MLCFlag,JLCFlag=getMJSignal(tiffpath,shipPortTree,outfolderPath)
|
||||||
|
|
||||||
|
if MLCFlag and JLCFlag:
|
||||||
|
tiffLCPort[MJLCName].append(tiffpath)
|
||||||
|
elif MLCFlag:
|
||||||
|
tiffLCPort[MLCName].append(tiffpath)
|
||||||
|
elif JLCFlag:
|
||||||
|
tiffLCPort[JLCName].append(tiffpath)
|
||||||
|
else:
|
||||||
|
tiffLCPort[NOLCName].append(tiffpath)
|
||||||
|
|
||||||
|
# 输出文件
|
||||||
|
with open(outTiffInfoFilePath,'w',encoding="utf-8") as f:
|
||||||
|
for k in tiffLCPort:
|
||||||
|
for tiffpath in tiffLCPort[k]:
|
||||||
|
f.write("{}\t\t{}\n".format(k,tiffpath))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getMJSignal(geoExtend,shipPortTree):
|
||||||
|
[xmin, ymin, xmax, ymax]=geoExtend
|
||||||
|
center_x = (xmin + xmax) / 2.0
|
||||||
|
center_y = (ymin + ymax) / 2.0
|
||||||
|
center_point = [center_x, center_y]
|
||||||
|
# 2. 计算能够覆盖整个矩形区域的最小半径(中心点到任一角点的最大距离)
|
||||||
|
radius_to_corner = np.sqrt((xmax - center_x) ** 2 + (ymax - center_y) ** 2)
|
||||||
|
|
||||||
|
MLCFlag=False
|
||||||
|
JLCFlag=False
|
||||||
|
## MLC
|
||||||
|
if MLCName in shipPortTree and not shipPortTree[MLCName] is None:
|
||||||
|
# 3. 使用 query_ball_point 查找以中心点为圆心,radius_to_corner 为半径的圆内的所有点的索引
|
||||||
|
potential_indices = shipPortTree[MLCName].query_ball_point(center_point, r=radius_to_corner)
|
||||||
|
|
||||||
|
# 4. 获取这些潜在点的实际坐标
|
||||||
|
# 假设你的 KDTree 是从 data_points 构建的:MLCTree = KDTree(data_points)
|
||||||
|
potential_points = shipPortTree[MLCName].data[potential_indices] # 这是所有潜在点的坐标数组
|
||||||
|
|
||||||
|
# 5. 进行精确的矩形范围过滤
|
||||||
|
# 条件判断:x 坐标在 xmin 和 xmax 之间,且 y 坐标在 ymin 和 ymax 之间
|
||||||
|
x_in_range = (potential_points[:, 0] >= xmin) & (potential_points[:, 0] <= xmax)
|
||||||
|
y_in_range = (potential_points[:, 1] >= ymin) & (potential_points[:, 1] <= ymax)
|
||||||
|
within_rect_indices_mask = x_in_range & y_in_range
|
||||||
|
|
||||||
|
# 6. 获取最终在矩形范围内的点的坐标(在原始 data_points 中的索引是 potential_indices[within_rect_indices_mask])
|
||||||
|
final_points = potential_points[within_rect_indices_mask]
|
||||||
|
|
||||||
|
# final_points 就是你要的矩形范围内的点
|
||||||
|
# 如果你需要的是这些点在原始数据中的索引,而不是坐标本身:
|
||||||
|
final_indices = np.array(potential_indices)[within_rect_indices_mask]
|
||||||
|
if final_points.shape[0]>0:
|
||||||
|
MLCFlag=True
|
||||||
|
# with open(portTxtpath,"w",encoding="utf-8") as f:
|
||||||
|
# for i in range(final_points.shape[0]):
|
||||||
|
# f.write("{}\t\t{},{}\n".format("MLC",final_points[i,0],final_points[i,1]))
|
||||||
|
# pass
|
||||||
|
if JLCName in shipPortTree and not shipPortTree[JLCName] is None:
|
||||||
|
# 3. 使用 query_ball_point 查找以中心点为圆心,radius_to_corner 为半径的圆内的所有点的索引
|
||||||
|
potential_indices = shipPortTree[JLCName].query_ball_point(center_point, r=radius_to_corner)
|
||||||
|
|
||||||
|
# 4. 获取这些潜在点的实际坐标
|
||||||
|
# 假设你的 KDTree 是从 data_points 构建的:MLCTree = KDTree(data_points)
|
||||||
|
potential_points = shipPortTree[JLCName].data[potential_indices] # 这是所有潜在点的坐标数组
|
||||||
|
|
||||||
|
# 5. 进行精确的矩形范围过滤
|
||||||
|
# 条件判断:x 坐标在 xmin 和 xmax 之间,且 y 坐标在 ymin 和 ymax 之间
|
||||||
|
x_in_range = (potential_points[:, 0] >= xmin) & (potential_points[:, 0] <= xmax)
|
||||||
|
y_in_range = (potential_points[:, 1] >= ymin) & (potential_points[:, 1] <= ymax)
|
||||||
|
within_rect_indices_mask = x_in_range & y_in_range
|
||||||
|
|
||||||
|
# 6. 获取最终在矩形范围内的点的坐标(在原始 data_points 中的索引是 potential_indices[within_rect_indices_mask])
|
||||||
|
final_points = potential_points[within_rect_indices_mask]
|
||||||
|
|
||||||
|
# final_points 就是你要的矩形范围内的点
|
||||||
|
# 如果你需要的是这些点在原始数据中的索引,而不是坐标本身:
|
||||||
|
final_indices = np.array(potential_indices)[within_rect_indices_mask]
|
||||||
|
if final_points.shape[0]>0:
|
||||||
|
JLCFlag=True
|
||||||
|
# with open(portTxtpath,"a",encoding="utf-8") as f:
|
||||||
|
# for i in range(final_points.shape[0]):
|
||||||
|
# f.write("{}\t\t{},{}\n".format("JLC",final_points[i,0],final_points[i,1]))
|
||||||
|
# pass
|
||||||
|
# 处理软件
|
||||||
|
if MLCFlag and JLCFlag:
|
||||||
|
return "mix_airport"
|
||||||
|
# tiffLCPort[MJLCName].append(tiffpath)
|
||||||
|
elif MLCFlag:
|
||||||
|
return "civil_harbor"
|
||||||
|
# tiffLCPort[MLCName].append(tiffpath)
|
||||||
|
elif JLCFlag:
|
||||||
|
return "military_harbor"
|
||||||
|
# tiffLCPort[JLCName].append(tiffpath)
|
||||||
|
else:
|
||||||
|
return "no_harbor"
|
||||||
|
# tiffLCPort[NOLCName].append(tiffpath)
|
||||||
|
# return MLCFlag,JLCFlag
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def shapefile_to_dota(shp_path, output_path, shipPortTree,difficulty_value=1):
|
||||||
|
"""
|
||||||
|
将Shapefile转换为DOTA格式
|
||||||
|
:param shp_path: Shapefile文件路径
|
||||||
|
:param output_path: 输出目录
|
||||||
|
:param class_field: 类别字段名
|
||||||
|
:param difficulty_value: 难度默认字段
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 注册所有驱动
|
||||||
|
ogr.RegisterAll()
|
||||||
|
|
||||||
|
# 打开Shapefile文件
|
||||||
|
driver = ogr.GetDriverByName('ESRI Shapefile')
|
||||||
|
datasource = driver.Open(shp_path, 0)
|
||||||
|
if datasource is None:
|
||||||
|
print("无法打开Shapefile文件")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 获取图层
|
||||||
|
layer = datasource.GetLayer()
|
||||||
|
|
||||||
|
output_file = output_path
|
||||||
|
|
||||||
|
with open(output_file, 'w',encoding="utf-8") as f:
|
||||||
|
# 写入DOTA格式头信息(可选)
|
||||||
|
# f.write('imagesource:unknown\n')
|
||||||
|
# f.write('gsd:1.0\n')
|
||||||
|
|
||||||
|
# 遍历所有要素
|
||||||
|
for feature in layer:
|
||||||
|
# 获取几何对象
|
||||||
|
geom = feature.GetGeometryRef()
|
||||||
|
if geom is None:
|
||||||
|
continue
|
||||||
|
# 获取类别和难度
|
||||||
|
try:
|
||||||
|
class_name = 'unknown'
|
||||||
|
except Exception as e:
|
||||||
|
class_name="MLC"
|
||||||
|
print(e)
|
||||||
|
difficulty = difficulty_value
|
||||||
|
|
||||||
|
# 处理不同类型的几何图形
|
||||||
|
if geom.GetGeometryName() == 'POLYGON':
|
||||||
|
# 获取多边形外环
|
||||||
|
ring = geom.GetGeometryRef(0)
|
||||||
|
# 获取所有点
|
||||||
|
points = []
|
||||||
|
for i in range(ring.GetPointCount()):
|
||||||
|
points.append(ring.GetPoint(i))
|
||||||
|
|
||||||
|
# 确保有足够的点(至少4个)
|
||||||
|
if len(points) >= 4:
|
||||||
|
# 取前4个点作为DOTA格式的四个角点
|
||||||
|
# 注意: DOTA要求按顺序排列(顺时针或逆时针)
|
||||||
|
x1, y1 = points[0][0], points[0][1]
|
||||||
|
x2, y2 = points[1][0], points[1][1]
|
||||||
|
x3, y3 = points[2][0], points[2][1]
|
||||||
|
x4, y4 = points[3][0], points[3][1]
|
||||||
|
|
||||||
|
xmin = min(x1, x2,x3,x4)
|
||||||
|
xmax = max(x1, x2,x3,x4)
|
||||||
|
ymin = min(y1, y2,y3,y4)
|
||||||
|
ymax = max(y1, y2,y3,y4)
|
||||||
|
# [xmin, ymin, xmax, ymax] = geoExtend
|
||||||
|
geoExtend = [xmin, ymin, xmax, ymax]
|
||||||
|
class_name=getMJSignal(geoExtend, shipPortTree)
|
||||||
|
# 写入DOTA格式行
|
||||||
|
line = f"{x1} {y1} {x2} {y2} {x3} {y3} {x4} {y4} {class_name} {difficulty}\n"
|
||||||
|
f.write(line)
|
||||||
|
|
||||||
|
# 释放资源
|
||||||
|
datasource.Destroy()
|
||||||
|
print("转换完毕")
|
||||||
|
|
||||||
|
|
||||||
|
def PortShapeProces(shp_path, output_path, MLCPath,JLCPath,JMLCPath,difficulty_value=1):
|
||||||
|
shipPort={
|
||||||
|
MLCName:getshapefileInfo(MLCPath),
|
||||||
|
JLCName:getshapefileInfo(JLCPath),
|
||||||
|
MJLCName:getshapefileInfo(JMLCPath), # 舰船不区分 居民一体
|
||||||
|
}
|
||||||
|
|
||||||
|
shipPortTree={
|
||||||
|
MLCName:KDTree(shipPort[MLCName]),
|
||||||
|
JLCName:KDTree(shipPort[JLCName]),
|
||||||
|
MJLCName:KDTree(shipPort[MJLCName]),
|
||||||
|
}
|
||||||
|
shapefile_to_dota(shp_path, output_path,shipPortTree, difficulty)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getParams():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-i','--infile',type=str,default=r'D:\港口\港口\Geo_bc2-sm-org-vv-20231016t135315-008424-0020e8-01.military_harbor.shp', help='输入shapefile文件')
|
||||||
|
parser.add_argument('-o', '--outfile',type=str,default=r'D:\港口\港口dota\Geo_bc2-sm-org-vv-20231016t135315-008424-0020e8-01.military_harbor.txt', help='输出geojson文件')
|
||||||
|
parser.add_argument('-m', '--mLC',type=str,help=r'MLC', default=r'D:\TYSAR-德清院\目标点位信息更新\0828目标点位\港口(民船).shp')
|
||||||
|
parser.add_argument('-j', '--jLC',type=str,help=r'JLC' ,default=r'D:\TYSAR-德清院\目标点位信息更新\0828目标点位\军港.shp')
|
||||||
|
parser.add_argument('-jm', '--jmlc',type=str,help=r'JMLC', default=r'D:\TYSAR-德清院\目标点位信息更新\0828目标点位\军民一体港口.shp')
|
||||||
|
parser.add_argument('-d', '--difficulty',type=int,default=1, help='输出geojson文件')
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
parser = getParams()
|
||||||
|
inFilePath=parser.infile
|
||||||
|
outpath=parser.outfile
|
||||||
|
mLCPath=parser.mLC
|
||||||
|
jLCPath=parser.jLC
|
||||||
|
jmLCPath=parser.jmlc
|
||||||
|
difficulty=parser.difficulty
|
||||||
|
print('infile=',inFilePath)
|
||||||
|
print('outfile=',outpath)
|
||||||
|
print('mLCPath=',mLCPath)
|
||||||
|
print('jLCPath=',jLCPath)
|
||||||
|
print('jmLCPath=',jmLCPath)
|
||||||
|
print('difficulty=',difficulty)
|
||||||
|
PortShapeProces(inFilePath, outpath, mLCPath, jLCPath, jmLCPath, difficulty_value=difficulty)
|
||||||
|
exit(2)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
exit(3)
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
from osgeo import ogr,gdal
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
from osgeo import gdal
|
||||||
|
import matplotlib
|
||||||
|
import matplotlib.patches as patches
|
||||||
|
from osgeo import gdal
|
||||||
|
from PIL import Image
|
||||||
|
from scipy.spatial import cKDTree
|
||||||
|
import numpy as np
|
||||||
|
from tools.DotaOperator import DotaObj,createDota,readDotaFile,writerDotaFile
|
||||||
|
import argparse
|
||||||
|
import math
|
||||||
|
from math import ceil, floor
|
||||||
|
|
||||||
|
pngpath=r"D:\港口\切片结果\Geo_bc2-sm-org-vv-20231016t135315-008424-0020e8-01_3.png"
|
||||||
|
txtpath=r"D:\港口\切片结果\Geo_bc2-sm-org-vv-20231016t135315-008424-0020e8-01_3.txt"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pngdata=np.array(Image.open(pngpath))
|
||||||
|
dotalist=readDotaFile(txtpath)
|
||||||
|
|
||||||
|
plt.figure()
|
||||||
|
plt.imshow(pngdata)
|
||||||
|
# 绘制每个目标的矩形框并标注坐标
|
||||||
|
for i in range(len(dotalist)):
|
||||||
|
# 提取x和y坐标
|
||||||
|
x_coords = [dotalist[i].x1, dotalist[i].x2, dotalist[i].x3, dotalist[i].x4]
|
||||||
|
y_coords = [dotalist[i].y1, dotalist[i].y2, dotalist[i].y3, dotalist[i].y4]
|
||||||
|
|
||||||
|
# 计算最小外接矩形(AABB)
|
||||||
|
x_min, x_max = min(x_coords), max(x_coords)
|
||||||
|
y_min, y_max = min(y_coords), max(y_coords)
|
||||||
|
width = x_max - x_min
|
||||||
|
height = y_max - y_min
|
||||||
|
|
||||||
|
# 绘制无填充矩形框(仅红色边框)
|
||||||
|
rect = patches.Rectangle(
|
||||||
|
(x_min, y_min), width, height,
|
||||||
|
linewidth=2, edgecolor='red', facecolor='none' # 关键:facecolor='none'
|
||||||
|
)
|
||||||
|
plt.gca().add_patch(rect)
|
||||||
|
|
||||||
|
# ax.annotate(f'({x},{y})', xy=(x, y), xytext=(5, 5),
|
||||||
|
# textcoords='offset points', fontsize=10,
|
||||||
|
# bbox=dict(boxstyle='round,pad=0.5', fc='white', alpha=0.8))
|
||||||
|
|
||||||
|
# 在矩形中心标注目标编号
|
||||||
|
center_x = sum(x_coords) / 4
|
||||||
|
center_y = sum(y_coords) / 4
|
||||||
|
plt.text(center_x, center_y, str(i),
|
||||||
|
ha='center', va='center', fontsize=6, color='red')
|
||||||
|
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
from glob import glob
|
||||||
|
from pathlib import Path
|
||||||
|
# from multiprocessing import Pool
|
||||||
|
########################################################
|
||||||
|
# 函数区
|
||||||
|
########################################################
|
||||||
|
|
||||||
|
spacetySliceEnvPathExEPath=r"d:\ProgramData\anaconda3\envs\spacetySliceEnv\python.exe"
|
||||||
|
|
||||||
|
def find_tif_files_pathlib(directory):
|
||||||
|
"""
|
||||||
|
使用pathlib.Path.rglob递归查找指定目录下所有.tif和.tiff文件
|
||||||
|
|
||||||
|
参数:
|
||||||
|
directory (str): 要搜索的根目录路径
|
||||||
|
|
||||||
|
返回:
|
||||||
|
list: 包含所有找到的.tif/.tiff文件完整路径的列表
|
||||||
|
"""
|
||||||
|
path = Path(directory)
|
||||||
|
# 使用rglob递归匹配所有.tif和.tiff文件
|
||||||
|
tif_files = list(path.rglob('*.tif')) + list(path.rglob('*.tiff'))
|
||||||
|
# 将Path对象转换为字符串路径
|
||||||
|
return [str(file) for file in tif_files]
|
||||||
|
|
||||||
|
|
||||||
|
def find_shp_files_pathlib(directory):
|
||||||
|
"""
|
||||||
|
使用pathlib.Path.rglob递归查找指定目录下所有.tif和.tiff文件
|
||||||
|
|
||||||
|
参数:
|
||||||
|
directory (str): 要搜索的根目录路径
|
||||||
|
|
||||||
|
返回:
|
||||||
|
list: 包含所有找到的.tif/.tiff文件完整路径的列表
|
||||||
|
"""
|
||||||
|
path = Path(directory)
|
||||||
|
# 使用rglob递归匹配所有.tif和.tiff文件
|
||||||
|
tif_files = list(path.rglob('*.shp'))
|
||||||
|
# 将Path对象转换为字符串路径
|
||||||
|
return [str(file) for file in tif_files]
|
||||||
|
|
||||||
|
|
||||||
|
def preProcessLabelshapefile(shpfilepath,preFolderPath):
|
||||||
|
if not os.path.exists(preFolderPath):
|
||||||
|
os.makedirs(preFolderPath)
|
||||||
|
file_path = Path(shpfilepath)
|
||||||
|
directory_path = str(file_path.resolve().parent.name)
|
||||||
|
|
||||||
|
rootname = Path(shpfilepath).stem
|
||||||
|
txtpath=os.path.join(preFolderPath,rootname+'.txt')
|
||||||
|
programpath=r"R:\TYSAR-德清院\A-预处理-未标注\A0-算法版本\AA\SpacetySliceDataTools\LabelPortShipRasterSlice\Portshapefile2dota_AA.py"
|
||||||
|
cmdtxt=r"{} {} -i {} -o {}".format(spacetySliceEnvPathExEPath,programpath,shpfilepath,txtpath)
|
||||||
|
if os.system(cmdtxt) ==2:
|
||||||
|
print("sucess:",cmdtxt)
|
||||||
|
return "sucess: {}".format(cmdtxt)
|
||||||
|
else:
|
||||||
|
print("failed:",cmdtxt)
|
||||||
|
return "failed: {}".format(cmdtxt)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
########################################################
|
||||||
|
# 流程执行区
|
||||||
|
########################################################
|
||||||
|
if __name__ == '__main__':
|
||||||
|
srcFolderPath = r"D:\港口\港口"
|
||||||
|
preFolderPath= r"D:\港口\港口dota"
|
||||||
|
shpPaths = find_shp_files_pathlib(srcFolderPath)
|
||||||
|
for shppath in shpPaths:
|
||||||
|
preProcessLabelshapefile(shppath, preFolderPath)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -118,14 +118,14 @@ def processPool(srcFolderPath,preFolderPath,targetfolderPath,logPath=r"R:\TYSAR-
|
||||||
print("{}/{}".format(pidx+1,len(async_results)),async_result.get())
|
print("{}/{}".format(pidx+1,len(async_results)),async_result.get())
|
||||||
writeoutlog(logPath,"{}/{} {}".format(pidx+1,len(async_results),async_result.get()))
|
writeoutlog(logPath,"{}/{} {}".format(pidx+1,len(async_results),async_result.get()))
|
||||||
writeoutlog(logPath, "\nprocess finished \n")
|
writeoutlog(logPath, "\nprocess finished \n")
|
||||||
moverTip,moveflag=moveDir(preFolderPath, targetfolderPath)
|
# moverTip,moveflag=moveDir(preFolderPath, targetfolderPath)
|
||||||
writeoutlog(logPath, moverTip)
|
# writeoutlog(logPath, moverTip)
|
||||||
|
|
||||||
writeoutlog(logPath, "====================================================================================\n")
|
writeoutlog(logPath, "====================================================================================\n")
|
||||||
if moveflag:
|
# if moveflag:
|
||||||
pass
|
# pass
|
||||||
else:
|
# else:
|
||||||
exit(3)
|
# exit(3)
|
||||||
|
|
||||||
########################################################
|
########################################################
|
||||||
# 流程执行区
|
# 流程执行区
|
||||||
|
|
@ -146,16 +146,16 @@ if __name__ == '__main__':
|
||||||
# processPool(srcFolderPath, preFolderPath,targetfolderPath, logPath)
|
# processPool(srcFolderPath, preFolderPath,targetfolderPath, logPath)
|
||||||
#
|
#
|
||||||
# 20250826-不分类 条带模式
|
# 20250826-不分类 条带模式
|
||||||
srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\0-原图"
|
srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\航道\20250930-不分类\0-原图"
|
||||||
preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\A-预处理\AB-图像预处理"
|
preFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\航道\20250930-不分类\A-预处理\AB-图像预处理"
|
||||||
targetfolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\A-预处理\AB-图像预处理"
|
targetfolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\A-预处理\AB-图像预处理"
|
||||||
processPool(srcFolderPath, preFolderPath, targetfolderPath,logPath)
|
processPool(srcFolderPath, preFolderPath, targetfolderPath,logPath)
|
||||||
|
|
||||||
# 20250903-不分类 条带模式
|
# # 20250903-不分类 条带模式
|
||||||
srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\0-原图"
|
# srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\0-原图"
|
||||||
preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\A-预处理\AB-图像预处理"
|
# preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\A-预处理\AB-图像预处理"
|
||||||
targetfolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\A-预处理\AB-图像预处理"
|
# targetfolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\A-预处理\AB-图像预处理"
|
||||||
processPool(srcFolderPath, preFolderPath,targetfolderPath, logPath)
|
# processPool(srcFolderPath, preFolderPath,targetfolderPath, logPath)
|
||||||
|
|
||||||
# # 20250910-不分类 条带模式
|
# # 20250910-不分类 条带模式
|
||||||
# srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250910-不分类\0-原图"
|
# srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250910-不分类\0-原图"
|
||||||
|
|
@ -164,7 +164,7 @@ if __name__ == '__main__':
|
||||||
# processPool(srcFolderPath, preFolderPath, targetfolderPath,logPath)
|
# processPool(srcFolderPath, preFolderPath, targetfolderPath,logPath)
|
||||||
|
|
||||||
|
|
||||||
result_flag_txt = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\strechResult_finish.log"
|
result_flag_txt = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\航道\20250930-不分类\strechResult_finish.log"
|
||||||
with open(result_flag_txt,"w",encoding="utf-8") as f:
|
with open(result_flag_txt,"w",encoding="utf-8") as f:
|
||||||
f.write("strech finied!!!\n")
|
f.write("strech finied!!!\n")
|
||||||
writeoutlog(logPath, "strech finied!!!\n")
|
writeoutlog(logPath, "strech finied!!!\n")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
from opcode import opname
|
||||||
|
|
||||||
|
from osgeo import ogr
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
from osgeo import ogr, gdal
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import numpy as np
|
||||||
|
from scipy.spatial import KDTree
|
||||||
|
from tools.DotaOperator import DotaObj,readDotaFile,writerDotaFile,createDota
|
||||||
|
from glob import glob
|
||||||
|
from pathlib import Path
|
||||||
|
import shutil
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
|
||||||
|
MLCName="MLC" # M
|
||||||
|
JLCName="JLC" # J
|
||||||
|
MJLCName="MJLC" # JM 混合
|
||||||
|
NOLCName="NOLC" # 没有港口
|
||||||
|
|
||||||
|
|
||||||
|
def existOrCreate(dirpath):
|
||||||
|
if not os.path.exists(dirpath):
|
||||||
|
os.makedirs(dirpath)
|
||||||
|
|
||||||
|
|
||||||
|
def find_tifPort_files_pathlib(directory):
|
||||||
|
path = Path(directory)
|
||||||
|
# 使用rglob递归匹配所有.tif和.tiff文件
|
||||||
|
tif_files = list(path.rglob('sumMJPort.txt'))
|
||||||
|
# 将Path对象转换为字符串路径
|
||||||
|
return [str(file) for file in tif_files]
|
||||||
|
|
||||||
|
|
||||||
|
def find_label_files_pathlib(directory):
|
||||||
|
path = Path(directory)
|
||||||
|
# 使用rglob递归匹配所有.tif和.tiff文件
|
||||||
|
tif_files = list(path.rglob('*.txt'))
|
||||||
|
# 将Path对象转换为字符串路径
|
||||||
|
return [str(file) for file in tif_files]
|
||||||
|
|
||||||
|
def read_MJPortFile(sumMJPortfilepath,deepsdict=None):
|
||||||
|
lines=None
|
||||||
|
with open(sumMJPortfilepath,'r',encoding="utf-8") as f:
|
||||||
|
lines= f.readlines()
|
||||||
|
if deepsdict is None :
|
||||||
|
deepsdict={}
|
||||||
|
for linestr in lines:
|
||||||
|
if len(linestr)<3:
|
||||||
|
continue
|
||||||
|
clsname=linestr.split("\t\t")[0]
|
||||||
|
tiffpath=linestr.split("\t\t")[1].replace("\n","")
|
||||||
|
rootname=Path(tiffpath).stem
|
||||||
|
deepsdict[rootname]=clsname
|
||||||
|
return deepsdict
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def SpliteProcess(srcfolderpath,infolderpath,outfolderpath):
|
||||||
|
sumMJPortPaths=find_tifPort_files_pathlib(srcfolderpath)
|
||||||
|
sumMJPortDict={}
|
||||||
|
print("读取港口归属文件")
|
||||||
|
for sumMJPortfilepath in tqdm(sumMJPortPaths):
|
||||||
|
sumMJPortDict=read_MJPortFile(sumMJPortfilepath,sumMJPortDict)
|
||||||
|
|
||||||
|
labeltxtPaths=find_label_files_pathlib(infolderpath)
|
||||||
|
|
||||||
|
JportLabel=os.path.join(outfolderpath,'军港')
|
||||||
|
MportLabel=os.path.join(outfolderpath,'民港')
|
||||||
|
MJportLabel=os.path.join(outfolderpath,'混合港')
|
||||||
|
NoportLabel=os.path.join(outfolderpath,'无港口')
|
||||||
|
|
||||||
|
existOrCreate(JportLabel)
|
||||||
|
existOrCreate(MportLabel)
|
||||||
|
existOrCreate(MJportLabel)
|
||||||
|
existOrCreate(NoportLabel)
|
||||||
|
|
||||||
|
# 软件
|
||||||
|
for labeltxtpath in tqdm(labeltxtPaths):
|
||||||
|
rootname=Path(labeltxtpath).stem
|
||||||
|
tiffpath=labeltxtpath.replace(".txt",".tif")
|
||||||
|
if not os.path.exists(tiffpath):
|
||||||
|
tiffpath=labeltxtpath.replace(".txt",".tiff")
|
||||||
|
if not os.path.exists(tiffpath):
|
||||||
|
print("error not fount: ",tiffpath)
|
||||||
|
rootname=rootname.replace("_image.txt","").replace("_image","")
|
||||||
|
idx=rootname.rfind("_")
|
||||||
|
rootname=rootname[:idx]
|
||||||
|
trgpath=None
|
||||||
|
|
||||||
|
if rootname in sumMJPortDict:
|
||||||
|
clsname=sumMJPortDict[rootname]
|
||||||
|
if MLCName == clsname: # M
|
||||||
|
trgpath=MportLabel
|
||||||
|
elif JLCName == clsname: # J
|
||||||
|
trgpath=JportLabel
|
||||||
|
elif MJLCName == clsname: # JM 混合
|
||||||
|
trgpath=MJportLabel
|
||||||
|
elif NOLCName == clsname: # 没有港口
|
||||||
|
trgpath=NoportLabel
|
||||||
|
clsname="MLC"
|
||||||
|
else:
|
||||||
|
print("error: ", Path(labeltxtpath).stem)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# shutil.copy(labeltxtpath, os.path.join(trgpath, os.path.basename(labeltxtpath)))
|
||||||
|
newlabelpath=os.path.join(trgpath, os.path.basename(labeltxtpath))
|
||||||
|
dotametas=readDotaFile(labeltxtpath)
|
||||||
|
for dotaid in range(len(dotametas)):
|
||||||
|
dotametas[dotaid].clsname=clsname
|
||||||
|
writerDotaFile(dotametas,newlabelpath)
|
||||||
|
shutil.copy(tiffpath, os.path.join(trgpath, os.path.basename(tiffpath)))
|
||||||
|
else:
|
||||||
|
print("error: ", Path(labeltxtpath).stem)
|
||||||
|
|
||||||
|
return True
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def getParams():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-s','--srcfolder',type=str,default=r'D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口', help='输入shapefile文件')
|
||||||
|
parser.add_argument('-i','--inlabelfolder',type=str,default=r'R:\TYSAR-德清院\D-切片成果\TYSAR-条带模式(SM)\港口\切片结果整理', help='输入shapefile文件')
|
||||||
|
parser.add_argument('-o', '--outfolder',type=str,default=r'R:\TYSAR-德清院\D-切片成果\TYSAR-条带模式(SM)\港口\舰船')
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
parser = getParams()
|
||||||
|
srcfolder=parser.srcfolder
|
||||||
|
infolder=parser.inlabelfolder
|
||||||
|
outfolder=parser.outfolder
|
||||||
|
print('srcfolder=',srcfolder)
|
||||||
|
print('infolder=',infolder)
|
||||||
|
print('outfolder=',outfolder)
|
||||||
|
SpliteProcess(srcfolder,infolder,outfolder)
|
||||||
|
exit(2)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
exit(3)
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
from glob import glob
|
||||||
|
from pathlib import Path
|
||||||
|
from multiprocessing import Pool
|
||||||
|
import hashlib # md5
|
||||||
|
import time
|
||||||
|
import shutil
|
||||||
|
import datetime
|
||||||
|
########################################################
|
||||||
|
# 函数区
|
||||||
|
########################################################
|
||||||
|
|
||||||
|
spacetySliceEnvPathExEPath=r"d:\ProgramData\anaconda3\envs\spacetySliceEnv\python.exe"
|
||||||
|
|
||||||
|
logPath=r"R:\TYSAR-德清院\A-预处理-未标注\A0-算法版本\AA\SpacetySliceDataTools\log\process.log"
|
||||||
|
|
||||||
|
|
||||||
|
def existOrCreate(dirpath):
|
||||||
|
if not os.path.exists(dirpath):
|
||||||
|
os.makedirs(dirpath)
|
||||||
|
|
||||||
|
def moveDir(srcfolderPath,targetfolderPath):
|
||||||
|
try:
|
||||||
|
shutil.copytree(srcfolderPath,targetfolderPath,dirs_exist_ok=True)
|
||||||
|
print("sucess: copy ", srcfolderPath,targetfolderPath )
|
||||||
|
shutil.rmtree(srcfolderPath)
|
||||||
|
print("sucess: rmtree ", srcfolderPath)
|
||||||
|
return "sucess: copy and rmtree from {} to {}".format(srcfolderPath,targetfolderPath),True
|
||||||
|
except Exception as e:
|
||||||
|
print("failed: copy ", srcfolderPath, targetfolderPath)
|
||||||
|
return "failed: copy and rmtree from {} to {}".format(srcfolderPath,targetfolderPath),False
|
||||||
|
|
||||||
|
def writeoutlog(logPath,cmdtxt):
|
||||||
|
with open(logPath,'a',encoding="utf-8") as f:
|
||||||
|
f.write(cmdtxt)
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
def preProcessTiFF(tiffpath,txtpath,preFolderPath):
|
||||||
|
|
||||||
|
file_path = Path(tiffpath)
|
||||||
|
directory_path = str(file_path.resolve().parent.name)
|
||||||
|
rootname=Path(tiffpath).stem
|
||||||
|
outpngpath=os.path.join(preFolderPath,"I"+directory_path+"_"+rootname+'.png')
|
||||||
|
programpath=r"R:\TYSAR-德清院\A-预处理-未标注\A0-算法版本\AA\SpacetySliceDataTools\generatorRasterSlicesTools\SpacetyTIFFDataStretch2PNG_AC.py"
|
||||||
|
|
||||||
|
# cmdtxt=r"{} {} -i {} -o {} --filemode --SquareRoot".format(spacetySliceEnvPathExEPath,programpath,tiffpath,outpngpath)
|
||||||
|
cmdtxt=r"{} {} -i {} -p {} -o {} --slicemode --SquareRoot".format(
|
||||||
|
spacetySliceEnvPathExEPath,programpath,
|
||||||
|
tiffpath,
|
||||||
|
txtpath,
|
||||||
|
preFolderPath
|
||||||
|
) # 直接切片
|
||||||
|
if os.system(cmdtxt) ==2:
|
||||||
|
print("sucess:",cmdtxt)
|
||||||
|
writeoutlog(logPath, "sucess: {}\n".format(cmdtxt))
|
||||||
|
return 2
|
||||||
|
else:
|
||||||
|
print("failed:",cmdtxt)
|
||||||
|
writeoutlog(logPath, "failed: {}\n".format(cmdtxt))
|
||||||
|
return 3
|
||||||
|
|
||||||
|
|
||||||
|
def processMJPort(srcFolderPath,outMJPortSumTxtPath,outMJPortFolderPath,MLCShapeFilePath,JLCShapeFilePath,MJLCShapeFilePath):
|
||||||
|
programpath = r"R:\TYSAR-德清院\A-预处理-未标注\A0-算法版本\AA\SpacetySliceDataTools\generatorRasterSlicesTools\SplitShipPortRasterTools_AC.py"
|
||||||
|
cmdtxt=r"{} {} -s {} -o {} -f {} -m {} -j {} -jm {}".format(
|
||||||
|
spacetySliceEnvPathExEPath,programpath,
|
||||||
|
srcFolderPath,outMJPortSumTxtPath,outMJPortFolderPath,
|
||||||
|
MLCShapeFilePath, JLCShapeFilePath, MJLCShapeFilePath
|
||||||
|
)
|
||||||
|
if os.system(cmdtxt) ==2:
|
||||||
|
print("sucess:",cmdtxt)
|
||||||
|
writeoutlog(logPath, "sucess: {}\n".format(cmdtxt))
|
||||||
|
# return "sucess: {}".format(cmdtxt)
|
||||||
|
return 2
|
||||||
|
else:
|
||||||
|
print("failed:",cmdtxt)
|
||||||
|
writeoutlog(logPath, "failed: {}\n".format(cmdtxt))
|
||||||
|
# return "failed: {}".format(cmdtxt)
|
||||||
|
return 3
|
||||||
|
|
||||||
|
|
||||||
|
def preProcessShipPortTools(srcFolderPath,targetFolderPath,outTargetFolderPath):
|
||||||
|
writeoutlog(logPath, "====================================================================================\n")
|
||||||
|
writeoutlog(logPath, "time: {}".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
|
||||||
|
writeoutlog(logPath, "srcFolderPath: {}".format(srcFolderPath))
|
||||||
|
writeoutlog(logPath, "targetFolderPath: {}".format(targetFolderPath))
|
||||||
|
writeoutlog(logPath, "process start \n")
|
||||||
|
#
|
||||||
|
# # 文件接口创建
|
||||||
|
# MPortFolder=os.path.join(targetFolderPath,"AC-图像预处理","民港口")
|
||||||
|
# JPortFolder=os.path.join(targetFolderPath,"AC-图像预处理","军港口")
|
||||||
|
# MJPortFolder=os.path.join(targetFolderPath,"AC-图像预处理","混合港口")
|
||||||
|
# NoPortFolder=os.path.join(targetFolderPath,"AC-图像预处理","无港口")
|
||||||
|
#
|
||||||
|
# existOrCreate(MPortFolder)
|
||||||
|
# existOrCreate(JPortFolder)
|
||||||
|
# existOrCreate(MJPortFolder)
|
||||||
|
# existOrCreate(NoPortFolder)
|
||||||
|
|
||||||
|
outMJPortSumTxtPath=os.path.join(targetFolderPath,"AC-图像预处理","sumMJPort.txt")
|
||||||
|
outMJPortFolderPath=os.path.join(targetFolderPath,"AC-图像预处理","sumMJPortFolder")
|
||||||
|
|
||||||
|
existOrCreate(outMJPortFolderPath)
|
||||||
|
|
||||||
|
MLCShapeFilePath=r"D:\TYSAR-德清院\目标点位信息更新\0828目标点位\港口(民船).shp"
|
||||||
|
JLCShapeFilePath=r"D:\TYSAR-德清院\目标点位信息更新\0828目标点位\军港.shp"
|
||||||
|
MJLCShapeFilePath=r"D:\TYSAR-德清院\目标点位信息更新\0828目标点位\军民一体港口.shp"
|
||||||
|
|
||||||
|
processMJPortflag=processMJPort(srcFolderPath,outMJPortSumTxtPath,outMJPortFolderPath,MLCShapeFilePath,JLCShapeFilePath,MJLCShapeFilePath)
|
||||||
|
|
||||||
|
writeoutlog(logPath, "\nprocess finished \n")
|
||||||
|
# moverTip,moveflag=moveDir(targetFolderPath, outTargetFolderPath)
|
||||||
|
# writeoutlog(logPath, moverTip)
|
||||||
|
writeoutlog(logPath, "====================================================================================\n")
|
||||||
|
# if moveflag:
|
||||||
|
# pass
|
||||||
|
# else:
|
||||||
|
# exit(3)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
# 20250813-不分类 条带模式
|
||||||
|
srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250813-不分类\0-原图"
|
||||||
|
preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250813-不分类\A-预处理\AB-图像预处理"
|
||||||
|
targetfolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250813-不分类\A-预处理\AB-图像预处理"
|
||||||
|
preProcessShipPortTools(srcFolderPath, preFolderPath, targetfolderPath)
|
||||||
|
#
|
||||||
|
# 20250818 条带模式
|
||||||
|
srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250818-不分类\0-原图"
|
||||||
|
preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250818-不分类\A-预处理\AB-图像预处理"
|
||||||
|
targetfolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250818-不分类\A-预处理\AB-图像预处理"
|
||||||
|
preProcessShipPortTools(srcFolderPath, preFolderPath,targetfolderPath)
|
||||||
|
#
|
||||||
|
# 20250826-不分类 条带模式
|
||||||
|
srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\0-原图"
|
||||||
|
preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\A-预处理"
|
||||||
|
targetfolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\A-预处理"
|
||||||
|
preProcessShipPortTools(srcFolderPath, preFolderPath,targetfolderPath)
|
||||||
|
#
|
||||||
|
# 20250903-不分类条带模式
|
||||||
|
srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\0-原图"
|
||||||
|
preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\A-预处理"
|
||||||
|
targetfolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\A-预处理"
|
||||||
|
preProcessShipPortTools(srcFolderPath, preFolderPath,targetfolderPath)
|
||||||
|
#
|
||||||
|
# 20250910-不分类 条带模式
|
||||||
|
srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250910-不分类\0-原图"
|
||||||
|
preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250910-不分类\A-预处理"
|
||||||
|
targetfolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250910-不分类\A-预处理"
|
||||||
|
preProcessShipPortTools(srcFolderPath, preFolderPath,targetfolderPath)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
from glob import glob
|
||||||
|
from pathlib import Path
|
||||||
|
from multiprocessing import Pool
|
||||||
|
import hashlib # md5
|
||||||
|
import time
|
||||||
|
import shutil
|
||||||
|
import datetime
|
||||||
|
########################################################
|
||||||
|
# 函数区
|
||||||
|
########################################################
|
||||||
|
|
||||||
|
spacetySliceEnvPathExEPath=r"d:\ProgramData\anaconda3\envs\spacetySliceEnv\python.exe"
|
||||||
|
|
||||||
|
logPath=r"R:\TYSAR-德清院\A-预处理-未标注\A0-算法版本\AA\SpacetySliceDataTools\log\process.log"
|
||||||
|
|
||||||
|
|
||||||
|
def existOrCreate(dirpath):
|
||||||
|
if not os.path.exists(dirpath):
|
||||||
|
os.makedirs(dirpath)
|
||||||
|
|
||||||
|
def moveDir(srcfolderPath,targetfolderPath):
|
||||||
|
try:
|
||||||
|
shutil.copytree(srcfolderPath,targetfolderPath,dirs_exist_ok=True)
|
||||||
|
print("sucess: copy ", srcfolderPath,targetfolderPath )
|
||||||
|
shutil.rmtree(srcfolderPath)
|
||||||
|
print("sucess: rmtree ", srcfolderPath)
|
||||||
|
return "sucess: copy and rmtree from {} to {}".format(srcfolderPath,targetfolderPath),True
|
||||||
|
except Exception as e:
|
||||||
|
print("failed: copy ", srcfolderPath, targetfolderPath)
|
||||||
|
return "failed: copy and rmtree from {} to {}".format(srcfolderPath,targetfolderPath),False
|
||||||
|
|
||||||
|
def writeoutlog(logPath,cmdtxt):
|
||||||
|
with open(logPath,'a',encoding="utf-8") as f:
|
||||||
|
f.write(cmdtxt)
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
def preProcessTiFF(tiffpath,txtpath,preFolderPath):
|
||||||
|
|
||||||
|
file_path = Path(tiffpath)
|
||||||
|
directory_path = str(file_path.resolve().parent.name)
|
||||||
|
rootname=Path(tiffpath).stem
|
||||||
|
outpngpath=os.path.join(preFolderPath,"I"+directory_path+"_"+rootname+'.png')
|
||||||
|
programpath=r"R:\TYSAR-德清院\A-预处理-未标注\A0-算法版本\AA\SpacetySliceDataTools\generatorRasterSlicesTools\SpacetyTIFFDataStretch2PNG_AC.py"
|
||||||
|
|
||||||
|
# cmdtxt=r"{} {} -i {} -o {} --filemode --SquareRoot".format(spacetySliceEnvPathExEPath,programpath,tiffpath,outpngpath)
|
||||||
|
cmdtxt=r"{} {} -i {} -p {} -o {} --slicemode --SquareRoot".format(
|
||||||
|
spacetySliceEnvPathExEPath,programpath,
|
||||||
|
tiffpath,
|
||||||
|
txtpath,
|
||||||
|
preFolderPath
|
||||||
|
) # 直接切片
|
||||||
|
if os.system(cmdtxt) ==2:
|
||||||
|
print("sucess:",cmdtxt)
|
||||||
|
writeoutlog(logPath, "sucess: {}\n".format(cmdtxt))
|
||||||
|
return "sucess: {}\n".format(cmdtxt)
|
||||||
|
else:
|
||||||
|
print("failed:",cmdtxt)
|
||||||
|
writeoutlog(logPath, "failed: {}\n".format(cmdtxt))
|
||||||
|
return "failed: {}\n".format(cmdtxt)
|
||||||
|
|
||||||
|
|
||||||
|
def processMJPort(srcFolderPath,outMJPortSumTxtPath,outMJPortFolderPath,MLCShapeFilePath,JLCShapeFilePath,MJLCShapeFilePath):
|
||||||
|
programpath = r"R:\TYSAR-德清院\A-预处理-未标注\A0-算法版本\AA\SpacetySliceDataTools\generatorRasterSlicesTools\SplitShipPortRasterTools_AC.py"
|
||||||
|
cmdtxt=r"{} {} -s {} -o {} -f {} -m {} -j {} -jm {}".format(
|
||||||
|
spacetySliceEnvPathExEPath,programpath,
|
||||||
|
srcFolderPath,outMJPortSumTxtPath,outMJPortFolderPath,
|
||||||
|
MLCShapeFilePath, JLCShapeFilePath, MJLCShapeFilePath
|
||||||
|
)
|
||||||
|
if os.system(cmdtxt) ==2:
|
||||||
|
print("sucess:",cmdtxt)
|
||||||
|
writeoutlog(logPath, "sucess: {}\n".format(cmdtxt))
|
||||||
|
# return "sucess: {}".format(cmdtxt)
|
||||||
|
return 2
|
||||||
|
else:
|
||||||
|
print("failed:",cmdtxt)
|
||||||
|
writeoutlog(logPath, "failed: {}\n".format(cmdtxt))
|
||||||
|
# return "failed: {}".format(cmdtxt)
|
||||||
|
return 3
|
||||||
|
|
||||||
|
|
||||||
|
def preProcessShipPortTools(srcFolderPath,targetFolderPath,outTargetFolderPath):
|
||||||
|
writeoutlog(logPath, "====================================================================================\n")
|
||||||
|
writeoutlog(logPath, "time: {}".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
|
||||||
|
writeoutlog(logPath, "srcFolderPath: {}".format(srcFolderPath))
|
||||||
|
writeoutlog(logPath, "targetFolderPath: {}".format(targetFolderPath))
|
||||||
|
writeoutlog(logPath, "process start \n")
|
||||||
|
|
||||||
|
# 文件接口创建
|
||||||
|
MPortFolder=os.path.join(targetFolderPath,"AC-图像预处理","民港口")
|
||||||
|
JPortFolder=os.path.join(targetFolderPath,"AC-图像预处理","军港口")
|
||||||
|
MJPortFolder=os.path.join(targetFolderPath,"AC-图像预处理","混合港口")
|
||||||
|
NoPortFolder=os.path.join(targetFolderPath,"AC-图像预处理","无港口")
|
||||||
|
|
||||||
|
existOrCreate(MPortFolder)
|
||||||
|
existOrCreate(JPortFolder)
|
||||||
|
existOrCreate(MJPortFolder)
|
||||||
|
existOrCreate(NoPortFolder)
|
||||||
|
|
||||||
|
outMJPortSumTxtPath=os.path.join(targetFolderPath,"AC-图像预处理","sumMJPort.txt")
|
||||||
|
outMJPortFolderPath=os.path.join(targetFolderPath,"AC-图像预处理","sumMJPortFolder")
|
||||||
|
|
||||||
|
existOrCreate(outMJPortFolderPath)
|
||||||
|
|
||||||
|
MLCShapeFilePath=r"D:\TYSAR-德清院\目标点位信息更新\0828目标点位\港口(民船).shp"
|
||||||
|
JLCShapeFilePath=r"D:\TYSAR-德清院\目标点位信息更新\0828目标点位\军港.shp" # 数据BM,不公开
|
||||||
|
MJLCShapeFilePath=r"D:\TYSAR-德清院\目标点位信息更新\0828目标点位\军民一体港口.shp"
|
||||||
|
processMJPortflag=2
|
||||||
|
# processMJPortflag=processMJPort(srcFolderPath,outMJPortSumTxtPath,outMJPortFolderPath,MLCShapeFilePath,JLCShapeFilePath,MJLCShapeFilePath)
|
||||||
|
# 港口归属
|
||||||
|
if processMJPortflag==2:
|
||||||
|
# 逐行处理
|
||||||
|
MJlines=None
|
||||||
|
with open(outMJPortSumTxtPath,"r",encoding="utf-8") as f:
|
||||||
|
MJlines=f.readlines()
|
||||||
|
|
||||||
|
MLCName = "MLC" # M
|
||||||
|
JLCName = "JLC" # J
|
||||||
|
MJLCName = "MJLC" # JM 混合
|
||||||
|
NOLCName = "NOLC" # 没有港口
|
||||||
|
|
||||||
|
async_results = []
|
||||||
|
with Pool(processes=6) as pool:
|
||||||
|
for linestr in MJlines:
|
||||||
|
if len(linestr)>3:
|
||||||
|
clsname=linestr.split("\t\t")[0]
|
||||||
|
tiffpath=linestr.split("\t\t")[1].replace("\n","")
|
||||||
|
rootname=Path(tiffpath).stem
|
||||||
|
portTxtpath = os.path.join(outMJPortFolderPath, rootname + ".txt")
|
||||||
|
tarPortFolder=None
|
||||||
|
if clsname==MLCName:
|
||||||
|
tarPortFolder=MPortFolder
|
||||||
|
elif clsname==JLCName:
|
||||||
|
tarPortFolder=JPortFolder
|
||||||
|
elif clsname==MJLCName:
|
||||||
|
tarPortFolder=MJPortFolder
|
||||||
|
elif clsname==NOLCName:
|
||||||
|
tarPortFolder=NoPortFolder
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
async_results.append(preProcessTiFF(tiffpath,portTxtpath,tarPortFolder))
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
# 处理分块
|
||||||
|
for pidx in range(len(async_results)):
|
||||||
|
async_result=async_results[pidx]
|
||||||
|
print("{}/{}".format(pidx+1,len(async_results)))
|
||||||
|
# writeoutlog(logPath,"{}/{}".format(pidx+1,len(async_results),async_result.get()))
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
writeoutlog(logPath, "\nprocess finished \n")
|
||||||
|
# moverTip,moveflag=moveDir(targetFolderPath, outTargetFolderPath)
|
||||||
|
# writeoutlog(logPath, moverTip)
|
||||||
|
writeoutlog(logPath, "====================================================================================\n")
|
||||||
|
# if moveflag:
|
||||||
|
# pass
|
||||||
|
# else:
|
||||||
|
# exit(3)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
# 20250813-不分类 条带模式
|
||||||
|
# srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250813-不分类\0-原图"
|
||||||
|
# preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250813-不分类\A-预处理\AB-图像预处理"
|
||||||
|
# targetfolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250813-不分类\A-预处理\AB-图像预处理"
|
||||||
|
# preProcessShipPortTools(srcFolderPath, preFolderPath, targetfolderPath,logPath)
|
||||||
|
#
|
||||||
|
# # 20250818 条带模式
|
||||||
|
# srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250818-不分类\0-原图"
|
||||||
|
# preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250818-不分类\A-预处理\AB-图像预处理"
|
||||||
|
# targetfolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250818-不分类\A-预处理\AB-图像预处理"
|
||||||
|
# preProcessShipPortTools(srcFolderPath, preFolderPath,targetfolderPath, logPath)
|
||||||
|
#
|
||||||
|
# 20250826-不分类 条带模式
|
||||||
|
# srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\0-原图"
|
||||||
|
# preFolderPath = r"D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\A-预处理"
|
||||||
|
# targetfolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\A-预处理"
|
||||||
|
# preProcessShipPortTools(srcFolderPath, preFolderPath, targetfolderPath)
|
||||||
|
|
||||||
|
# 20250930-不分类 条带模式
|
||||||
|
srcFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\航道\20250930-不分类\0-原图"
|
||||||
|
preFolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\航道\20250930-不分类\A-预处理2"
|
||||||
|
targetfolderPath = r"R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250826-不分类\A-预处理"
|
||||||
|
preProcessShipPortTools(srcFolderPath, preFolderPath, targetfolderPath)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,621 @@
|
||||||
|
"""
|
||||||
|
|
||||||
|
2025.09.16 切片增加后缀 _image.png _image.tiff
|
||||||
|
2025.09.22 增加港口切片要求
|
||||||
|
|
||||||
|
"""
|
||||||
|
from osgeo import ogr, gdal
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import numpy as np
|
||||||
|
from PIL import Image
|
||||||
|
import math
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
portsliceSize=5000
|
||||||
|
shipsliceSize=1024
|
||||||
|
BlockOverLayer=0.25
|
||||||
|
|
||||||
|
def existOrCreate(dirpath):
|
||||||
|
if not os.path.exists(dirpath):
|
||||||
|
os.makedirs(dirpath)
|
||||||
|
|
||||||
|
|
||||||
|
def get_filename_without_ext(path):
|
||||||
|
base_name = os.path.basename(path)
|
||||||
|
if '.' not in base_name or base_name.startswith('.'):
|
||||||
|
return base_name
|
||||||
|
return base_name.rsplit('.', 1)[0]
|
||||||
|
|
||||||
|
def read_tif(path):
|
||||||
|
dataset = gdal.Open(path) # 打开TIF文件
|
||||||
|
if dataset is None:
|
||||||
|
print("无法打开文件")
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
cols = dataset.RasterXSize # 图像宽度
|
||||||
|
rows = dataset.RasterYSize # 图像高度
|
||||||
|
bands = dataset.RasterCount
|
||||||
|
im_proj = dataset.GetProjection() # 获取投影信息
|
||||||
|
im_Geotrans = dataset.GetGeoTransform() # 获取仿射变换信息
|
||||||
|
im_data = dataset.ReadAsArray(0, 0, cols, rows) # 读取栅格数据为NumPy数组
|
||||||
|
print("行数:", rows)
|
||||||
|
print("列数:", cols)
|
||||||
|
print("波段:", bands)
|
||||||
|
del dataset # 关闭数据集
|
||||||
|
return im_proj, im_Geotrans, im_data
|
||||||
|
|
||||||
|
def write_envi(im_data, im_geotrans, im_proj, output_path):
|
||||||
|
"""
|
||||||
|
将数组数据写入ENVI格式文件
|
||||||
|
:param im_data: 输入的numpy数组(2D或3D)
|
||||||
|
:param im_geotrans: 仿射变换参数(6元组)
|
||||||
|
:param im_proj: 投影信息(WKT字符串)
|
||||||
|
:param output_path: 输出文件路径(无需扩展名,会自动生成.dat和.hdr)
|
||||||
|
"""
|
||||||
|
im_bands = 1
|
||||||
|
im_height, im_width = im_data.shape
|
||||||
|
# 创建ENVI格式驱动
|
||||||
|
driver = gdal.GetDriverByName("GTiff")
|
||||||
|
dataset = driver.Create(output_path, im_width, im_height, 1, gdal.GDT_Byte)
|
||||||
|
|
||||||
|
if dataset is not None:
|
||||||
|
dataset.SetGeoTransform(im_geotrans) # 设置地理变换参数
|
||||||
|
dataset.SetProjection(im_proj) # 设置投影
|
||||||
|
|
||||||
|
dataset.GetRasterBand(1).WriteArray(im_data)
|
||||||
|
|
||||||
|
dataset.FlushCache() # 确保数据写入磁盘
|
||||||
|
dataset = None # 关闭文件
|
||||||
|
|
||||||
|
|
||||||
|
def write_allExtend(im_data, im_geotrans, im_proj, output_path):
|
||||||
|
"""
|
||||||
|
将数组数据写入ENVI格式文件
|
||||||
|
:param im_data: 输入的numpy数组(2D或3D)
|
||||||
|
:param im_geotrans: 仿射变换参数(6元组)
|
||||||
|
:param im_proj: 投影信息(WKT字符串)
|
||||||
|
:param output_path: 输出文件路径(无需扩展名,会自动生成.dat和.hdr)
|
||||||
|
"""
|
||||||
|
im_bands = 1
|
||||||
|
im_height, im_width = im_data.shape
|
||||||
|
|
||||||
|
create_options=[
|
||||||
|
"COMPRESS=DEFLATE",
|
||||||
|
"PREDICTOR=2",
|
||||||
|
"ZLEVEL=6",
|
||||||
|
"TILED=YES",
|
||||||
|
]
|
||||||
|
|
||||||
|
# 创建ENVI格式驱动
|
||||||
|
driver = gdal.GetDriverByName("GTiff")
|
||||||
|
dataset = driver.Create(output_path, im_width, im_height, 1, gdal.GDT_Byte,options=create_options)
|
||||||
|
|
||||||
|
if dataset is not None:
|
||||||
|
dataset.SetGeoTransform(im_geotrans) # 设置地理变换参数
|
||||||
|
dataset.SetProjection(im_proj) # 设置投影
|
||||||
|
|
||||||
|
dataset.GetRasterBand(1).WriteArray(im_data)
|
||||||
|
|
||||||
|
dataset.FlushCache() # 确保数据写入磁盘
|
||||||
|
dataset = None # 关闭文件
|
||||||
|
|
||||||
|
|
||||||
|
def write_tiff(im_data, im_geotrans, im_proj, output_path):
|
||||||
|
"""
|
||||||
|
将数组数据写入ENVI格式文件
|
||||||
|
:param im_data: 输入的numpy数组(2D或3D)
|
||||||
|
:param im_geotrans: 仿射变换参数(6元组)
|
||||||
|
:param im_proj: 投影信息(WKT字符串)
|
||||||
|
:param output_path: 输出文件路径(无需扩展名,会自动生成.dat和.hdr)
|
||||||
|
"""
|
||||||
|
im_bands = 1
|
||||||
|
im_height, im_width = im_data.shape
|
||||||
|
# 创建ENVI格式驱动
|
||||||
|
driver = gdal.GetDriverByName("GTiff")
|
||||||
|
dataset = driver.Create(output_path, im_width, im_height, 1, gdal.GDT_Float32)
|
||||||
|
|
||||||
|
if dataset is not None:
|
||||||
|
dataset.SetGeoTransform(im_geotrans) # 设置地理变换参数
|
||||||
|
dataset.SetProjection(im_proj) # 设置投影
|
||||||
|
|
||||||
|
dataset.GetRasterBand(1).WriteArray(im_data)
|
||||||
|
|
||||||
|
dataset.FlushCache() # 确保数据写入磁盘
|
||||||
|
dataset = None # 关闭文件
|
||||||
|
|
||||||
|
|
||||||
|
def Strech_linear(im_data):
|
||||||
|
im_data_dB=10*np.log10(im_data)
|
||||||
|
immask=np.isfinite(im_data_dB)
|
||||||
|
infmask = np.isinf(im_data_dB)
|
||||||
|
imvail_data=im_data[immask]
|
||||||
|
im_data_dB=0
|
||||||
|
|
||||||
|
minvalue=np.nanmin(imvail_data)
|
||||||
|
maxvalue=np.nanmax(imvail_data)
|
||||||
|
|
||||||
|
infmask = np.isinf(im_data_dB)
|
||||||
|
im_data[infmask] = minvalue-100
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254+1
|
||||||
|
im_data=np.clip(im_data,0,255)
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
def Strech_linear1(im_data):
|
||||||
|
im_data_dB = 10 * np.log10(im_data)
|
||||||
|
immask = np.isfinite(im_data_dB)
|
||||||
|
infmask = np.isinf(im_data_dB)
|
||||||
|
imvail_data = im_data[immask]
|
||||||
|
im_data_dB=0
|
||||||
|
|
||||||
|
minvalue=np.percentile(imvail_data,1)
|
||||||
|
maxvalue = np.percentile(imvail_data, 99)
|
||||||
|
|
||||||
|
|
||||||
|
im_data[infmask] = minvalue - 100
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254 + 1
|
||||||
|
im_data = np.clip(im_data, 0, 255)
|
||||||
|
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
|
||||||
|
def Strech_linear2(im_data):
|
||||||
|
im_data_dB = 10 * np.log10(im_data)
|
||||||
|
immask = np.isfinite(im_data_dB)
|
||||||
|
infmask = np.isinf(im_data_dB)
|
||||||
|
imvail_data = im_data[immask]
|
||||||
|
im_data_dB = 0
|
||||||
|
|
||||||
|
minvalue = np.percentile(imvail_data, 2)
|
||||||
|
maxvalue = np.percentile(imvail_data, 98)
|
||||||
|
|
||||||
|
im_data[infmask] = minvalue - 100
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254 + 1
|
||||||
|
im_data = np.clip(im_data, 0, 255)
|
||||||
|
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
def Strech_linear5(im_data):
|
||||||
|
im_data_dB = 10 * np.log10(im_data)
|
||||||
|
immask = np.isfinite(im_data_dB)
|
||||||
|
infmask = np.isinf(im_data_dB)
|
||||||
|
imvail_data = im_data[immask]
|
||||||
|
im_data_dB = 0
|
||||||
|
|
||||||
|
minvalue = np.percentile(imvail_data, 5)
|
||||||
|
maxvalue = np.percentile(imvail_data, 95)
|
||||||
|
|
||||||
|
im_data[infmask] = minvalue - 100
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254 + 1
|
||||||
|
im_data = np.clip(im_data, 0, 255)
|
||||||
|
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
def Strech_SquareRoot(im_data):
|
||||||
|
# 判断是否为dB
|
||||||
|
# immask = np.isfinite(im_data)
|
||||||
|
# imvail_data = im_data[immask]
|
||||||
|
# minvalue = np.percentile(imvail_data,30)
|
||||||
|
# if minvalue<0 :
|
||||||
|
# im_data=np.power(10.0,im_data/10.0)
|
||||||
|
|
||||||
|
im_data=np.sqrt(im_data)
|
||||||
|
immask = np.isfinite(im_data)
|
||||||
|
imvail_data = im_data[immask]
|
||||||
|
|
||||||
|
minvalue=np.nanmin(imvail_data)
|
||||||
|
maxvalue=np.nanmax(imvail_data)
|
||||||
|
minvalue_01Prec = np.percentile(imvail_data, 2) # 20250904 1%拉伸
|
||||||
|
maxvalue_999Prec = np.percentile(imvail_data, 98)
|
||||||
|
print('sqrt root min - max ', minvalue,maxvalue)
|
||||||
|
if (maxvalue-minvalue)/(maxvalue_999Prec-minvalue_01Prec)>3: # 表示 拉伸之后,像素值绝大部分很有可能集中在 80
|
||||||
|
minvalue=minvalue_01Prec
|
||||||
|
maxvalue=maxvalue_999Prec
|
||||||
|
print('sqrt root min(0.1) - max(99.9) ', minvalue, maxvalue)
|
||||||
|
|
||||||
|
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254 + 1
|
||||||
|
im_data = np.clip(im_data, 0, 255)
|
||||||
|
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
def DataStrech(im_data,strechmethod):
|
||||||
|
# [,"Linear1","Linear2","Linear5","SquareRoot"]
|
||||||
|
if strechmethod == "Linear" :
|
||||||
|
return Strech_linear(im_data)
|
||||||
|
elif strechmethod == "Linear1":
|
||||||
|
return Strech_linear1(im_data)
|
||||||
|
elif strechmethod == "Linear2":
|
||||||
|
return Strech_linear2(im_data)
|
||||||
|
elif strechmethod == "Linear5":
|
||||||
|
return Strech_linear5(im_data)
|
||||||
|
elif strechmethod == "SquareRoot":
|
||||||
|
return Strech_SquareRoot(im_data)
|
||||||
|
else:
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 文件模式
|
||||||
|
def stretchProcess(infilepath,outfilepath,strechmethod):
|
||||||
|
im_proj, im_Geotrans, im_data=read_tif(infilepath)
|
||||||
|
envifilepath=get_filename_without_ext(outfilepath)+".bin"
|
||||||
|
envifilepath=os.path.join(os.path.dirname(outfilepath),envifilepath)
|
||||||
|
im_data = DataStrech(im_data,strechmethod)
|
||||||
|
im_data = im_data.astype(np.uint8)
|
||||||
|
write_envi(im_data,im_Geotrans,im_proj,envifilepath)
|
||||||
|
Image.fromarray(im_data).save(outfilepath,compress_level=0)
|
||||||
|
print("图像拉伸处理结束")
|
||||||
|
|
||||||
|
|
||||||
|
def getsliceGeotrans(GeoTransform,Xpixel,Ypixel):
|
||||||
|
XGeo = GeoTransform[0]+GeoTransform[1]*Xpixel+GeoTransform[2]*Ypixel
|
||||||
|
YGeo = GeoTransform[3]+GeoTransform[4]*Xpixel+GeoTransform[5]*Ypixel
|
||||||
|
result=[
|
||||||
|
XGeo,GeoTransform[1],GeoTransform[2],
|
||||||
|
YGeo,GeoTransform[4],GeoTransform[5]
|
||||||
|
]
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def is_all_same(lst):
|
||||||
|
arr = np.array(lst)
|
||||||
|
# arr_num=arr.size
|
||||||
|
sum_data=np.sum(arr != arr[0])
|
||||||
|
return sum_data<400
|
||||||
|
|
||||||
|
def getNextSliceNumber(n,sliceSize,overlap=0.25):
|
||||||
|
step=int(sliceSize*(1-overlap))+1
|
||||||
|
ti = list(range(0, n, step))
|
||||||
|
newN= n if ti[-1]+1024 < n else ti[-1]+1024
|
||||||
|
# 评价重叠率
|
||||||
|
movelayer=[]
|
||||||
|
for i in range(len(ti)-1):
|
||||||
|
movelayer.append((ti[i] + 1024 - ti[i + 1]) / 1024 * 100.0)
|
||||||
|
print("重叠率:",movelayer)
|
||||||
|
return newN,ti
|
||||||
|
|
||||||
|
def sliceShipDataset(rootname,im_data,src_im_data, im_Geotrans, im_proj, outfolder):
|
||||||
|
binfolder=os.path.join(outfolder,"舰船","unit8binfolder")
|
||||||
|
pngfolder=os.path.join(outfolder,"舰船","pngfolder")
|
||||||
|
tifffolder=os.path.join(outfolder,"舰船","tifffolder")
|
||||||
|
|
||||||
|
|
||||||
|
h,w=im_data.shape
|
||||||
|
nextH,ht=getNextSliceNumber(h,shipsliceSize,BlockOverLayer)
|
||||||
|
nextW,wt=getNextSliceNumber(w,shipsliceSize,BlockOverLayer)
|
||||||
|
padH=nextH-h
|
||||||
|
padW=nextW-w
|
||||||
|
im_data=np.pad(im_data,((0,padH),(0,padW)),mode='constant',constant_values=0)
|
||||||
|
src_im_data=np.pad(src_im_data,((0,padH),(0,padW)),mode='constant',constant_values=0)
|
||||||
|
slice_ID=0
|
||||||
|
for hi in ht:
|
||||||
|
for wi in wt:
|
||||||
|
geotrans_temp=getsliceGeotrans(im_Geotrans,wi,hi)
|
||||||
|
im_data_temp=im_data[hi:hi+shipsliceSize,wi:wi+shipsliceSize]
|
||||||
|
src_im_data_temp=src_im_data[hi:hi+shipsliceSize,wi:wi+shipsliceSize]
|
||||||
|
slice_ID = slice_ID + 1
|
||||||
|
if not is_all_same(im_data_temp):
|
||||||
|
sliceBinPath=os.path.join(binfolder, rootname+"_"+str(slice_ID).zfill(4)+"_image.tiff")
|
||||||
|
slicepngPath=os.path.join(pngfolder, rootname+"_"+str(slice_ID).zfill(4)+"_image.png")
|
||||||
|
slicesrctiffPath=os.path.join(tifffolder, rootname+"_"+str(slice_ID).zfill(4)+"_image.tiff")
|
||||||
|
|
||||||
|
write_tiff(src_im_data_temp, geotrans_temp, im_proj, slicesrctiffPath)
|
||||||
|
write_envi(im_data_temp,geotrans_temp,im_proj,sliceBinPath)
|
||||||
|
Image.fromarray(im_data_temp).save(slicepngPath,compress_level=0)
|
||||||
|
|
||||||
|
print("图像切片结束")
|
||||||
|
return slice_ID
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def ishasPort(im_Geotrans,im_data,MLCPoints,JLCPoints,MJLCPoints):
|
||||||
|
LCpoints=MLCPoints+JLCPoints+MJLCPoints
|
||||||
|
# 获取范围
|
||||||
|
rows=im_data.shape[0]
|
||||||
|
cols=im_data.shape[1]
|
||||||
|
x1=im_Geotrans[0]+im_Geotrans[1]*0
|
||||||
|
x2=im_Geotrans[0]+im_Geotrans[1]*cols
|
||||||
|
|
||||||
|
y1=im_Geotrans[3]+im_Geotrans[5]*0
|
||||||
|
y2=im_Geotrans[3]+im_Geotrans[5]*rows
|
||||||
|
|
||||||
|
xmin=min(x1,x2)
|
||||||
|
xmax=max(x1,x2)
|
||||||
|
ymin=min(y1,y2)
|
||||||
|
ymax=max(y1,y2)
|
||||||
|
# 数据处理
|
||||||
|
for p in LCpoints:
|
||||||
|
x_in_range = (p[0] >= xmin) & (p[0]<= xmax)
|
||||||
|
y_in_range = (p[1] >= ymin) & (p[1] <= ymax)
|
||||||
|
within_rect_indices_mask = x_in_range & y_in_range
|
||||||
|
if within_rect_indices_mask:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def slicePortDataset(rootname,im_data,src_im_data, im_Geotrans, im_proj, outfolder,slice_ID,portfilestr):
|
||||||
|
# 读取portfilestr 中文件
|
||||||
|
MLCPoints=[]
|
||||||
|
JLCPoints=[]
|
||||||
|
MJLCPoints=[]
|
||||||
|
portfilelines=[]
|
||||||
|
with open(portfilestr,"r",encoding="utf-8") as portfile:
|
||||||
|
portfilelines=portfile.readlines()
|
||||||
|
for line in portfilelines:
|
||||||
|
if(len(line)>3):
|
||||||
|
linemetas=line.split("\t\t")
|
||||||
|
clsname=linemetas[0]
|
||||||
|
pointstr=linemetas[1]
|
||||||
|
pointx=float(pointstr.split(",")[0]) # PX
|
||||||
|
pointy=float(pointstr.split(",")[1]) # Py
|
||||||
|
if clsname=="JLC":
|
||||||
|
JLCPoints.append([pointx,pointy])
|
||||||
|
elif clsname=="MJLC":
|
||||||
|
MJLCPoints.append([pointx,pointy])
|
||||||
|
elif clsname=="MLC":
|
||||||
|
MLCPoints.append([pointx,pointy])
|
||||||
|
# 处理文件脚本
|
||||||
|
if len(MLCPoints)==0 and len(JLCPoints)==0 and len(MJLCPoints)==0:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
# 切片主流程
|
||||||
|
binfolder=os.path.join(outfolder,"港口","unit8binfolder")
|
||||||
|
pngfolder=os.path.join(outfolder,"港口","pngfolder")
|
||||||
|
tifffolder=os.path.join(outfolder,"港口","tifffolder")
|
||||||
|
|
||||||
|
for P in JLCPoints:
|
||||||
|
Px=P[0]
|
||||||
|
Py=P[1]
|
||||||
|
Sx=P[0]-portsliceSize/2
|
||||||
|
Sy=P[1]-portsliceSize/2
|
||||||
|
wi=Sx if Sx>0 else 0
|
||||||
|
hi=Sy if Sy>0 else 0
|
||||||
|
slice_ID = slice_ID + 1
|
||||||
|
im_data_temp = im_data[hi:hi + portsliceSize, wi:wi + portsliceSize]
|
||||||
|
src_im_data_temp = src_im_data[hi:hi + portsliceSize, wi:wi + portsliceSize]
|
||||||
|
|
||||||
|
sliceBinPath = os.path.join(binfolder, rootname + "_" + str(slice_ID).zfill(4) + "_image.tiff")
|
||||||
|
slicepngPath = os.path.join(pngfolder, rootname + "_" + str(slice_ID).zfill(4) + "_image.png")
|
||||||
|
slicesrctiffPath = os.path.join(tifffolder, rootname + "_" + str(slice_ID).zfill(4) + "_image.tiff")
|
||||||
|
|
||||||
|
geotrans_temp = getsliceGeotrans(im_Geotrans, wi, hi)
|
||||||
|
write_tiff(src_im_data_temp, geotrans_temp, im_proj, slicesrctiffPath)
|
||||||
|
write_envi(im_data_temp, geotrans_temp, im_proj, sliceBinPath)
|
||||||
|
Image.fromarray(im_data_temp).save(slicepngPath, compress_level=4)
|
||||||
|
|
||||||
|
for P in MJLCPoints:
|
||||||
|
Px = P[0]
|
||||||
|
Py = P[1]
|
||||||
|
Sx = P[0] - portsliceSize / 2
|
||||||
|
Sy = P[1] - portsliceSize / 2
|
||||||
|
wi = Sx if Sx > 0 else 0
|
||||||
|
hi = Sy if Sy > 0 else 0
|
||||||
|
slice_ID = slice_ID + 1
|
||||||
|
im_data_temp = im_data[hi:hi + portsliceSize, wi:wi + portsliceSize]
|
||||||
|
src_im_data_temp = src_im_data[hi:hi + portsliceSize, wi:wi + portsliceSize]
|
||||||
|
|
||||||
|
sliceBinPath = os.path.join(binfolder, rootname + "_" + str(slice_ID).zfill(4) + "_image.tiff")
|
||||||
|
slicepngPath = os.path.join(pngfolder, rootname + "_" + str(slice_ID).zfill(4) + "_image.png")
|
||||||
|
slicesrctiffPath = os.path.join(tifffolder, rootname + "_" + str(slice_ID).zfill(4) + "_image.tiff")
|
||||||
|
|
||||||
|
geotrans_temp = getsliceGeotrans(im_Geotrans, wi, hi)
|
||||||
|
write_tiff(src_im_data_temp, geotrans_temp, im_proj, slicesrctiffPath)
|
||||||
|
write_envi(im_data_temp, geotrans_temp, im_proj, sliceBinPath)
|
||||||
|
Image.fromarray(im_data_temp).save(slicepngPath, compress_level=4)
|
||||||
|
|
||||||
|
for P in MLCPoints:
|
||||||
|
Px = P[0]
|
||||||
|
Py = P[1]
|
||||||
|
Sx = P[0] - portsliceSize / 2
|
||||||
|
Sy = P[1] - portsliceSize / 2
|
||||||
|
wi = Sx if Sx > 0 else 0
|
||||||
|
hi = Sy if Sy > 0 else 0
|
||||||
|
slice_ID = slice_ID + 1
|
||||||
|
im_data_temp = im_data[hi:hi + portsliceSize, wi:wi + portsliceSize]
|
||||||
|
src_im_data_temp = src_im_data[hi:hi + portsliceSize, wi:wi + portsliceSize]
|
||||||
|
|
||||||
|
sliceBinPath = os.path.join(binfolder, rootname + "_" + str(slice_ID).zfill(4) + "_image.tiff")
|
||||||
|
slicepngPath = os.path.join(pngfolder, rootname + "_" + str(slice_ID).zfill(4) + "_image.png")
|
||||||
|
slicesrctiffPath = os.path.join(tifffolder, rootname + "_" + str(slice_ID).zfill(4) + "_image.tiff")
|
||||||
|
|
||||||
|
geotrans_temp = getsliceGeotrans(im_Geotrans, wi, hi)
|
||||||
|
write_tiff(src_im_data_temp, geotrans_temp, im_proj, slicesrctiffPath)
|
||||||
|
write_envi(im_data_temp, geotrans_temp, im_proj, sliceBinPath)
|
||||||
|
Image.fromarray(im_data_temp).save(slicepngPath, compress_level=4)
|
||||||
|
|
||||||
|
print("图像切片结束")
|
||||||
|
return slice_ID
|
||||||
|
|
||||||
|
def sliceLabelPortDataset(rootname,im_data,src_im_data, im_Geotrans, im_proj, outfolder,slice_ID,portfilestr):
|
||||||
|
# 读取portfilestr 中文件
|
||||||
|
MLCPoints=[]
|
||||||
|
JLCPoints=[]
|
||||||
|
MJLCPoints=[]
|
||||||
|
with open(portfilestr,"r",encoding="utf-8") as portfile:
|
||||||
|
for line in portfile.readlines():
|
||||||
|
if(len(line)>3):
|
||||||
|
linemetas=line.split("\t\t")
|
||||||
|
clsname=linemetas[0]
|
||||||
|
pointstr=linemetas[1]
|
||||||
|
pointx=float(pointstr.split(",")[0])
|
||||||
|
pointy=float(pointstr.split(",")[1])
|
||||||
|
if clsname=="JLC":
|
||||||
|
JLCPoints.append([pointx,pointy])
|
||||||
|
elif clsname=="MJLC":
|
||||||
|
MJLCPoints.append([pointx,pointy])
|
||||||
|
elif clsname=="MLC":
|
||||||
|
MLCPoints.append([pointx,pointy])
|
||||||
|
# 处理文件脚本
|
||||||
|
if len(MLCPoints)==0 and len(JLCPoints)==0 and len(MJLCPoints)==0:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
# 切片主流程
|
||||||
|
portuint8Tifffolder=os.path.join(outfolder,"港口","unit8tiff")
|
||||||
|
portlabelfolder=os.path.join(outfolder,"港口","MLCLabels")
|
||||||
|
unit8tiffPath=os.path.join(portuint8Tifffolder,"{}_uint8.tiff".format(rootname))
|
||||||
|
uint8labelPath=os.path.join(portlabelfolder,"{}_uint8.csv".format(rootname))
|
||||||
|
write_envi(im_data,im_Geotrans,im_proj,unit8tiffPath)
|
||||||
|
with open(portfilestr,"r",encoding="utf-8") as portfile:
|
||||||
|
with open(uint8labelPath, "w", encoding="utf-8") as labelfile:
|
||||||
|
for line in portfile.readlines():
|
||||||
|
if (len(line) > 3):
|
||||||
|
linemetas = line.split("\t\t")
|
||||||
|
clsname = linemetas[0]
|
||||||
|
pointstr = linemetas[1]
|
||||||
|
pointx = float(pointstr.split(",")[0])
|
||||||
|
pointy = float(pointstr.split(",")[1])
|
||||||
|
labelfile.write("{},{},{}\n".format(pointx,pointy,clsname))
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def stretchSliceProcess(infilepath, outfolder,portfilestr, strechmethod):
|
||||||
|
shipbinfolder=os.path.join(outfolder,"舰船","unit8binfolder")
|
||||||
|
shippngfolder=os.path.join(outfolder,"舰船","pngfolder")
|
||||||
|
shiptifffolder=os.path.join(outfolder,"舰船","tifffolder")
|
||||||
|
allpngfolder = os.path.join(outfolder, "allpngfolder")
|
||||||
|
|
||||||
|
portbinfolder=os.path.join(outfolder,"港口","unit8binfolder")
|
||||||
|
portpngfolder=os.path.join(outfolder,"港口","pngfolder")
|
||||||
|
porttifffolder=os.path.join(outfolder,"港口","tifffolder")
|
||||||
|
|
||||||
|
portuint8Tifffolder=os.path.join(outfolder,"港口","unit8tiff")
|
||||||
|
portlabelfolder=os.path.join(outfolder,"港口","PortLabels")
|
||||||
|
|
||||||
|
existOrCreate(shipbinfolder)
|
||||||
|
existOrCreate(shippngfolder)
|
||||||
|
existOrCreate(shiptifffolder)
|
||||||
|
existOrCreate(allpngfolder)
|
||||||
|
existOrCreate(portbinfolder)
|
||||||
|
existOrCreate(portpngfolder)
|
||||||
|
existOrCreate(porttifffolder)
|
||||||
|
existOrCreate(portuint8Tifffolder)
|
||||||
|
existOrCreate(portlabelfolder)
|
||||||
|
|
||||||
|
|
||||||
|
im_proj, im_Geotrans, im_data=read_tif(infilepath)
|
||||||
|
src_im_data=im_data*1.0
|
||||||
|
im_data = DataStrech(im_data,strechmethod) # 拉伸
|
||||||
|
im_data = im_data.astype(np.uint8)
|
||||||
|
rootname=Path(infilepath).stem
|
||||||
|
allImagePath=os.path.join(allpngfolder, rootname+"_all.png")
|
||||||
|
Image.fromarray(im_data).save(allImagePath,compress_level=9)
|
||||||
|
# write_allExtend(im_data, im_Geotrans, im_proj, allImagePath)
|
||||||
|
slice_ID=0
|
||||||
|
slice_ID=sliceShipDataset(rootname,im_data, src_im_data,im_Geotrans, im_proj, outfolder) # 舰船切片
|
||||||
|
slice_ID=slice_ID+1
|
||||||
|
if os.path.exists(portfilestr):
|
||||||
|
print("存在港口文件")
|
||||||
|
slice_ID=slicePortDataset(rootname,im_data, src_im_data,im_Geotrans, im_proj, outfolder,slice_ID,portfilestr)
|
||||||
|
# slice_ID=sliceLabelPortDataset(rootname,im_data, src_im_data,im_Geotrans, im_proj, outfolder,slice_ID,portfilestr) # 港口拉伸
|
||||||
|
print("图像切片与拉伸完成")
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def getParams():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-i','--infile',type=str,default=r"F:\天仪SAR卫星数据集\舰船数据\bc2-sp-org-vv-20250205t032055-021998-000036-0055ee-01.tiff", help='输入shapefile文件')
|
||||||
|
parser.add_argument('-p', '--portfile',type=str,default=r"F:\天仪SAR卫星数据集\舰船数据\bc2-sp-org-vv-20250205t032055-021998-000036-0055ee-01.txt", help='输出geojson文件')
|
||||||
|
parser.add_argument('-o', '--outfile',type=str,default=r"F:\天仪SAR卫星数据集\舰船数据\切片结果", help='输出geojson文件')
|
||||||
|
group = parser.add_mutually_exclusive_group()
|
||||||
|
group.add_argument(
|
||||||
|
'--filemode',
|
||||||
|
action='store_const',
|
||||||
|
const='filemode',
|
||||||
|
dest='mode',
|
||||||
|
help='文件模式'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--slicemode',
|
||||||
|
action='store_const',
|
||||||
|
const='slicemode',
|
||||||
|
dest='mode',
|
||||||
|
help='切片模式'
|
||||||
|
)
|
||||||
|
parser.set_defaults(mode='slicemode')
|
||||||
|
group = parser.add_mutually_exclusive_group()
|
||||||
|
group.add_argument(
|
||||||
|
'--Linear',
|
||||||
|
action='store_const',
|
||||||
|
const='Linear',
|
||||||
|
dest='method',
|
||||||
|
help='线性拉伸'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--Linear1prec',
|
||||||
|
action='store_const',
|
||||||
|
const='Linear1',
|
||||||
|
dest='method',
|
||||||
|
help='1%线性拉伸'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--Linear2prec',
|
||||||
|
action='store_const',
|
||||||
|
const='Linear2',
|
||||||
|
dest='method',
|
||||||
|
help='2%线性拉伸'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--Linear5prec',
|
||||||
|
action='store_const',
|
||||||
|
const='Linear5',
|
||||||
|
dest='method',
|
||||||
|
help='5%线性拉伸'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--SquareRoot',
|
||||||
|
action='store_const',
|
||||||
|
const='SquareRoot',
|
||||||
|
dest='method',
|
||||||
|
help='平方根拉伸'
|
||||||
|
)
|
||||||
|
parser.set_defaults(method='SquareRoot')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
parser = getParams()
|
||||||
|
intiffPath=parser.infile
|
||||||
|
modestr=parser.mode
|
||||||
|
methodstr = parser.method
|
||||||
|
|
||||||
|
if modestr == "filemode":
|
||||||
|
outbinPath = parser.outfile
|
||||||
|
print('infile=', intiffPath)
|
||||||
|
print('outfile=', outbinPath)
|
||||||
|
print('method=', methodstr)
|
||||||
|
stretchProcess(intiffPath, outbinPath, methodstr)
|
||||||
|
elif modestr == "slicemode":
|
||||||
|
outfolder = parser.outfile
|
||||||
|
portfilestr = parser.portfile
|
||||||
|
print('infile=', intiffPath)
|
||||||
|
print('outfolder=', outfolder)
|
||||||
|
print('method=', methodstr)
|
||||||
|
print('portfile=', portfilestr)
|
||||||
|
stretchSliceProcess(intiffPath, outfolder,portfilestr, methodstr)
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
print("模式错误")
|
||||||
|
exit(2)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
exit(3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,301 @@
|
||||||
|
from osgeo import ogr
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
from osgeo import ogr, gdal
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import numpy as np
|
||||||
|
from scipy.spatial import KDTree
|
||||||
|
from tools.DotaOperator import DotaObj,readDotaFile,writerDotaFile,createDota
|
||||||
|
from glob import glob
|
||||||
|
from pathlib import Path
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
"""
|
||||||
|
1. 港口,5000x5000,军港与民港切片,
|
||||||
|
a. 预标注框给他们
|
||||||
|
b. 重叠率25%重复
|
||||||
|
c. 军民2000m 以内,影像抽出来
|
||||||
|
d. 原影像如果只有 1 个港口,-》 港口类型
|
||||||
|
多 个港口,-》 远近,如果港口距离1000m ,单独拉出来
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
MLCName="MLC" # M
|
||||||
|
JLCName="JLC" # J
|
||||||
|
MJLCName="MJLC" # JM 混合
|
||||||
|
NOLCName="NOLC" # 没有港口
|
||||||
|
|
||||||
|
def find_tif_files_pathlib(directory):
|
||||||
|
path = Path(directory)
|
||||||
|
# 使用rglob递归匹配所有.tif和.tiff文件
|
||||||
|
tif_files = list(path.rglob('*.tiff'))+list(path.rglob('*.tif'))
|
||||||
|
# 将Path对象转换为字符串路径
|
||||||
|
return [str(file) for file in tif_files]
|
||||||
|
|
||||||
|
|
||||||
|
def find_srcPath(srcFolder):
|
||||||
|
root_path = Path(srcFolder)
|
||||||
|
target_path = [folderpath for folderpath in root_path.rglob("*") if folderpath.is_dir() and folderpath.name=="0-原图"]
|
||||||
|
tiff_files = []
|
||||||
|
for folderpath in target_path:
|
||||||
|
tiff_files=tiff_files+find_tif_files_pathlib(folderpath)
|
||||||
|
|
||||||
|
tiff_dict={}
|
||||||
|
for filepath in tiff_files:
|
||||||
|
rootname=Path(filepath).stem
|
||||||
|
tiff_dict[rootname]=filepath
|
||||||
|
|
||||||
|
return tiff_dict
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def read_tifInfo(path):
|
||||||
|
dataset = gdal.Open(path) # 打开TIF文件
|
||||||
|
if dataset is None:
|
||||||
|
print("无法打开文件,读取文件信息")
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
cols = dataset.RasterXSize # 图像宽度
|
||||||
|
rows = dataset.RasterYSize # 图像高度
|
||||||
|
bands = dataset.RasterCount
|
||||||
|
im_proj = dataset.GetProjection() # 获取投影信息
|
||||||
|
im_Geotrans = dataset.GetGeoTransform() # 获取仿射变换信息
|
||||||
|
# im_data = dataset.ReadAsArray(0, 0, cols, rows) # 读取栅格数据为NumPy数组
|
||||||
|
print("行数:", rows)
|
||||||
|
print("列数:", cols)
|
||||||
|
print("波段:", bands)
|
||||||
|
x1=im_Geotrans[0]+im_Geotrans[1]*0
|
||||||
|
x2=im_Geotrans[0]+im_Geotrans[1]*cols
|
||||||
|
|
||||||
|
y1=im_Geotrans[3]+im_Geotrans[5]*0
|
||||||
|
y2=im_Geotrans[3]+im_Geotrans[5]*rows
|
||||||
|
|
||||||
|
xmin=min(x1,x2)
|
||||||
|
xmax=max(x1,x2)
|
||||||
|
ymin=min(y1,y2)
|
||||||
|
ymax=max(y1,y2)
|
||||||
|
|
||||||
|
geoExtend=[xmin,ymin,xmax,ymax]
|
||||||
|
del dataset # 关闭数据集
|
||||||
|
return im_proj, im_Geotrans,geoExtend
|
||||||
|
|
||||||
|
def getshapefileInfo(shp_path):
|
||||||
|
"""
|
||||||
|
将Shapefile转换为DOTA格式
|
||||||
|
:param shp_path: Shapefile文件路径
|
||||||
|
"""
|
||||||
|
|
||||||
|
geom_points=[]
|
||||||
|
|
||||||
|
print("shapefile: ",shp_path)
|
||||||
|
|
||||||
|
# 注册所有驱动
|
||||||
|
ogr.RegisterAll()
|
||||||
|
|
||||||
|
# 打开Shapefile文件
|
||||||
|
driver = ogr.GetDriverByName('ESRI Shapefile')
|
||||||
|
datasource = driver.Open(shp_path, 0)
|
||||||
|
if datasource is None:
|
||||||
|
print("无法打开Shapefile文件")
|
||||||
|
return
|
||||||
|
|
||||||
|
print("layer count: ",datasource.GetLayerCount())
|
||||||
|
for layerid in range(datasource.GetLayerCount()):
|
||||||
|
print("layer id: ",layerid)
|
||||||
|
# 获取图层
|
||||||
|
layer = datasource.GetLayer(layerid)
|
||||||
|
layer_defn=layer.GetLayerDefn()
|
||||||
|
field_count=layer_defn.GetFieldCount()
|
||||||
|
|
||||||
|
print("field_count:", field_count)
|
||||||
|
for i in range (field_count):
|
||||||
|
field_defn=layer_defn.GetFieldDefn(i)
|
||||||
|
field_name=field_defn.GetName()
|
||||||
|
field_type=field_defn.GetType()
|
||||||
|
field_type_name=field_defn.GetFieldTypeName(field_type)
|
||||||
|
print("field_name:", field_name, field_type_name, field_type_name)
|
||||||
|
|
||||||
|
for feature in layer:
|
||||||
|
geom = feature.GetGeometryRef()
|
||||||
|
if geom.GetGeometryName() == 'POINT':
|
||||||
|
x=geom.GetX()
|
||||||
|
y=geom.GetY()
|
||||||
|
geom_points.append([x,y])
|
||||||
|
return np.array(geom_points)
|
||||||
|
|
||||||
|
|
||||||
|
def getTiffsInfo(tiffnames,folderpath):
|
||||||
|
"""
|
||||||
|
获取所有影像的几何信息
|
||||||
|
Args:
|
||||||
|
tiff_paths: tiff列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
tiffdict={}
|
||||||
|
for tiff_name in tiffnames:
|
||||||
|
if tiff_name.endswith(".tiff"):
|
||||||
|
tiff_path=os.path.join(folderpath,tiff_name)
|
||||||
|
im_proj, im_Geotrans, geoExtend=read_tifInfo(tiff_path)
|
||||||
|
tiffdict[tiff_name]={"geoExtend":geoExtend,"geoTrans":im_Geotrans,"imProj":im_proj}
|
||||||
|
return tiffdict
|
||||||
|
|
||||||
|
|
||||||
|
def getMJSignal(tiffpath,shipPortTree,outfolderPath):
|
||||||
|
rootname=Path(tiffpath).stem
|
||||||
|
portTxtpath=os.path.join(outfolderPath,rootname+".txt")
|
||||||
|
im_proj, im_Geotrans, geoExtend = read_tifInfo(tiffpath) # geoExtend : [xmin,ymin,xmax,ymax]
|
||||||
|
[xmin, ymin, xmax, ymax]=geoExtend
|
||||||
|
center_x = (xmin + xmax) / 2.0
|
||||||
|
center_y = (ymin + ymax) / 2.0
|
||||||
|
center_point = [center_x, center_y]
|
||||||
|
# 2. 计算能够覆盖整个矩形区域的最小半径(中心点到任一角点的最大距离)
|
||||||
|
radius_to_corner = np.sqrt((xmax - center_x) ** 2 + (ymax - center_y) ** 2)
|
||||||
|
|
||||||
|
MLCFlag=False
|
||||||
|
JLCFlag=False
|
||||||
|
## MLC
|
||||||
|
if MLCName in shipPortTree and not shipPortTree[MLCName] is None:
|
||||||
|
# 3. 使用 query_ball_point 查找以中心点为圆心,radius_to_corner 为半径的圆内的所有点的索引
|
||||||
|
potential_indices = shipPortTree[MLCName].query_ball_point(center_point, r=radius_to_corner)
|
||||||
|
|
||||||
|
# 4. 获取这些潜在点的实际坐标
|
||||||
|
# 假设你的 KDTree 是从 data_points 构建的:MLCTree = KDTree(data_points)
|
||||||
|
potential_points = shipPortTree[MLCName].data[potential_indices] # 这是所有潜在点的坐标数组
|
||||||
|
|
||||||
|
# 5. 进行精确的矩形范围过滤
|
||||||
|
# 条件判断:x 坐标在 xmin 和 xmax 之间,且 y 坐标在 ymin 和 ymax 之间
|
||||||
|
x_in_range = (potential_points[:, 0] >= xmin) & (potential_points[:, 0] <= xmax)
|
||||||
|
y_in_range = (potential_points[:, 1] >= ymin) & (potential_points[:, 1] <= ymax)
|
||||||
|
within_rect_indices_mask = x_in_range & y_in_range
|
||||||
|
|
||||||
|
# 6. 获取最终在矩形范围内的点的坐标(在原始 data_points 中的索引是 potential_indices[within_rect_indices_mask])
|
||||||
|
final_points = potential_points[within_rect_indices_mask]
|
||||||
|
|
||||||
|
# final_points 就是你要的矩形范围内的点
|
||||||
|
# 如果你需要的是这些点在原始数据中的索引,而不是坐标本身:
|
||||||
|
final_indices = np.array(potential_indices)[within_rect_indices_mask]
|
||||||
|
if final_points.shape[0]>0:
|
||||||
|
MLCFlag=True
|
||||||
|
with open(portTxtpath,"w",encoding="utf-8") as f:
|
||||||
|
for i in range(final_points.shape[0]):
|
||||||
|
f.write("{}\t\t{},{}\n".format("MLC",final_points[i,0],final_points[i,1]))
|
||||||
|
pass
|
||||||
|
if JLCName in shipPortTree and not shipPortTree[JLCName] is None:
|
||||||
|
# 3. 使用 query_ball_point 查找以中心点为圆心,radius_to_corner 为半径的圆内的所有点的索引
|
||||||
|
potential_indices = shipPortTree[JLCName].query_ball_point(center_point, r=radius_to_corner)
|
||||||
|
|
||||||
|
# 4. 获取这些潜在点的实际坐标
|
||||||
|
# 假设你的 KDTree 是从 data_points 构建的:MLCTree = KDTree(data_points)
|
||||||
|
potential_points = shipPortTree[JLCName].data[potential_indices] # 这是所有潜在点的坐标数组
|
||||||
|
|
||||||
|
# 5. 进行精确的矩形范围过滤
|
||||||
|
# 条件判断:x 坐标在 xmin 和 xmax 之间,且 y 坐标在 ymin 和 ymax 之间
|
||||||
|
x_in_range = (potential_points[:, 0] >= xmin) & (potential_points[:, 0] <= xmax)
|
||||||
|
y_in_range = (potential_points[:, 1] >= ymin) & (potential_points[:, 1] <= ymax)
|
||||||
|
within_rect_indices_mask = x_in_range & y_in_range
|
||||||
|
|
||||||
|
# 6. 获取最终在矩形范围内的点的坐标(在原始 data_points 中的索引是 potential_indices[within_rect_indices_mask])
|
||||||
|
final_points = potential_points[within_rect_indices_mask]
|
||||||
|
|
||||||
|
# final_points 就是你要的矩形范围内的点
|
||||||
|
# 如果你需要的是这些点在原始数据中的索引,而不是坐标本身:
|
||||||
|
final_indices = np.array(potential_indices)[within_rect_indices_mask]
|
||||||
|
if final_points.shape[0]>0:
|
||||||
|
JLCFlag=True
|
||||||
|
with open(portTxtpath,"a",encoding="utf-8") as f:
|
||||||
|
for i in range(final_points.shape[0]):
|
||||||
|
f.write("{}\t\t{},{}\n".format("JLC",final_points[i,0],final_points[i,1]))
|
||||||
|
pass
|
||||||
|
# 处理软件
|
||||||
|
return MLCFlag,JLCFlag
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getTiffInPort(shipPortTree,srcFolderPath_0img,outTiffInfoFilePath,outfolderPath):
|
||||||
|
tiffpaths=find_tif_files_pathlib(srcFolderPath_0img)
|
||||||
|
tiffLCPort={
|
||||||
|
MLCName:[],
|
||||||
|
JLCName:[],
|
||||||
|
MJLCName:[],
|
||||||
|
NOLCName:[]
|
||||||
|
}
|
||||||
|
for tiffpath in tiffpaths:
|
||||||
|
MLCFlag,JLCFlag=getMJSignal(tiffpath,shipPortTree,outfolderPath)
|
||||||
|
|
||||||
|
if MLCFlag and JLCFlag:
|
||||||
|
tiffLCPort[MJLCName].append(tiffpath)
|
||||||
|
elif MLCFlag:
|
||||||
|
tiffLCPort[MLCName].append(tiffpath)
|
||||||
|
elif JLCFlag:
|
||||||
|
tiffLCPort[JLCName].append(tiffpath)
|
||||||
|
else:
|
||||||
|
tiffLCPort[NOLCName].append(tiffpath)
|
||||||
|
|
||||||
|
# 输出文件
|
||||||
|
with open(outTiffInfoFilePath,'w',encoding="utf-8") as f:
|
||||||
|
for k in tiffLCPort:
|
||||||
|
for tiffpath in tiffLCPort[k]:
|
||||||
|
f.write("{}\t\t{}\n".format(k,tiffpath))
|
||||||
|
|
||||||
|
|
||||||
|
def SpliteProcess(srcfolderpath,outfolderPath,outfilepath,MLCPath,JLCPath,JMLCPath):
|
||||||
|
shipPort={
|
||||||
|
MLCName:getshapefileInfo(MLCPath),
|
||||||
|
JLCName:getshapefileInfo(JLCPath),
|
||||||
|
# "JMLC":getshapefileInfo(JMLCPath), # 舰船不区分 居民一体
|
||||||
|
}
|
||||||
|
|
||||||
|
shipPortTree={
|
||||||
|
MLCName:KDTree(shipPort[MLCName]),
|
||||||
|
JLCName:KDTree(shipPort[JLCName]),
|
||||||
|
# "JMLC":KDTree(shipPort["JMLC"]),
|
||||||
|
}
|
||||||
|
srcFolderPath_0img=os.path.join(srcfolderpath) # 0-原图 文件路径
|
||||||
|
getTiffInPort(shipPortTree, srcFolderPath_0img, outfilepath,outfolderPath)
|
||||||
|
return True
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def getParams():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-s','--srcfolder',type=str,default=r'R:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类', help='输入shapefile文件')
|
||||||
|
parser.add_argument('-o', '--outfilepath',type=str,default=r'D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\A-预处理\JMPort.txt', help='输出geojson文件')
|
||||||
|
parser.add_argument('-f', '--folderOutpath',type=str,help=r'PortfolderOutpath', default=r'D:\TYSAR-德清院\TYSAR-条带模式(SM)\港口\20250903-不分类\A-预处理\PortPoints')
|
||||||
|
parser.add_argument('-m', '--mLC',type=str,help=r'MLC', default=r'D:\TYSAR-德清院\目标点位信息更新\0828目标点位\港口(民船).shp')
|
||||||
|
parser.add_argument('-j', '--jLC',type=str,help=r'JLC' ,default=r'D:\TYSAR-德清院\目标点位信息更新\0828目标点位\军港.shp')
|
||||||
|
parser.add_argument('-jm', '--jmlc',type=str,help=r'JMLC', default=r'D:\TYSAR-德清院\目标点位信息更新\0828目标点位\军民一体港口.shp')
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
parser = getParams()
|
||||||
|
srcfolder=parser.srcfolder
|
||||||
|
outfilepath=parser.outfilepath
|
||||||
|
folderOutpath=parser.folderOutpath
|
||||||
|
mLCPath=parser.mLC
|
||||||
|
jLCPath=parser.jLC
|
||||||
|
jmLCPath=parser.jmlc
|
||||||
|
print('srcfolder=',srcfolder)
|
||||||
|
print('outfile=',outfilepath)
|
||||||
|
print('outfolder=',folderOutpath)
|
||||||
|
print('mLCPath=',mLCPath)
|
||||||
|
print('jLCPath=',jLCPath)
|
||||||
|
print('jmLCPath=',jmLCPath)
|
||||||
|
SpliteProcess(srcfolder,folderOutpath,outfilepath,mLCPath,jLCPath,jmLCPath)
|
||||||
|
exit(2)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
exit(3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
d:\ProgramData\anaconda3\envs\spacetySliceEnv\python.exe "R:\TYSAR-德清院\A-预处理-未标注\A0-算法版本\AA\SpacetySliceDataTools\generatorRasterSlicesTools\SplitShipPortRasterTools_AC.py" -s "R:\TYSAR-德清院\TYSAR-条带模式(SM)\航道\20250930-不分类\0-原图" -o "R:\TYSAR-德清院\TYSAR-条带模式(SM)\航道\20250930-不分类\A-预处理\AC-图像预处理\sumMJPort.txt" -f "R:\TYSAR-德清院\TYSAR-条带模式(SM)\航道\20250930-不分类\A-预处理\AC-图像预处理\sumMJPortFolder" -m "D:\TYSAR-德清院\目标点位信息更新\0828目标点位\港口(民船).shp" -j "D:\TYSAR-德清院\目标点位信息更新\0828目标点位\军港.shp" -jm "D:\TYSAR-德清院\目标点位信息更新\0828目标点位\军民一体港口.shp"
|
||||||
|
|
@ -0,0 +1,407 @@
|
||||||
|
"""
|
||||||
|
|
||||||
|
2025.09.16 切片增加后缀 _image.png _image.tiff
|
||||||
|
2025.09.22 增加港口切片要求
|
||||||
|
|
||||||
|
"""
|
||||||
|
from osgeo import ogr, gdal
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import numpy as np
|
||||||
|
from PIL import Image
|
||||||
|
import math
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sliceSize=1024
|
||||||
|
BlockOverLayer=0.25
|
||||||
|
|
||||||
|
def get_filename_without_ext(path):
|
||||||
|
base_name = os.path.basename(path)
|
||||||
|
if '.' not in base_name or base_name.startswith('.'):
|
||||||
|
return base_name
|
||||||
|
return base_name.rsplit('.', 1)[0]
|
||||||
|
|
||||||
|
def read_tif(path):
|
||||||
|
dataset = gdal.Open(path) # 打开TIF文件
|
||||||
|
if dataset is None:
|
||||||
|
print("无法打开文件")
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
cols = dataset.RasterXSize # 图像宽度
|
||||||
|
rows = dataset.RasterYSize # 图像高度
|
||||||
|
bands = dataset.RasterCount
|
||||||
|
im_proj = dataset.GetProjection() # 获取投影信息
|
||||||
|
im_Geotrans = dataset.GetGeoTransform() # 获取仿射变换信息
|
||||||
|
im_data = dataset.ReadAsArray(0, 0, cols, rows) # 读取栅格数据为NumPy数组
|
||||||
|
print("行数:", rows)
|
||||||
|
print("列数:", cols)
|
||||||
|
print("波段:", bands)
|
||||||
|
del dataset # 关闭数据集
|
||||||
|
return im_proj, im_Geotrans, im_data
|
||||||
|
|
||||||
|
def write_envi(im_data, im_geotrans, im_proj, output_path):
|
||||||
|
"""
|
||||||
|
将数组数据写入ENVI格式文件
|
||||||
|
:param im_data: 输入的numpy数组(2D或3D)
|
||||||
|
:param im_geotrans: 仿射变换参数(6元组)
|
||||||
|
:param im_proj: 投影信息(WKT字符串)
|
||||||
|
:param output_path: 输出文件路径(无需扩展名,会自动生成.dat和.hdr)
|
||||||
|
"""
|
||||||
|
im_bands = 1
|
||||||
|
im_height, im_width = im_data.shape
|
||||||
|
# 创建ENVI格式驱动
|
||||||
|
driver = gdal.GetDriverByName("GTiff")
|
||||||
|
dataset = driver.Create(output_path, im_width, im_height, 1, gdal.GDT_Byte)
|
||||||
|
|
||||||
|
if dataset is not None:
|
||||||
|
dataset.SetGeoTransform(im_geotrans) # 设置地理变换参数
|
||||||
|
dataset.SetProjection(im_proj) # 设置投影
|
||||||
|
|
||||||
|
dataset.GetRasterBand(1).WriteArray(im_data)
|
||||||
|
|
||||||
|
dataset.FlushCache() # 确保数据写入磁盘
|
||||||
|
dataset = None # 关闭文件
|
||||||
|
|
||||||
|
|
||||||
|
def write_tiff(im_data, im_geotrans, im_proj, output_path):
|
||||||
|
"""
|
||||||
|
将数组数据写入ENVI格式文件
|
||||||
|
:param im_data: 输入的numpy数组(2D或3D)
|
||||||
|
:param im_geotrans: 仿射变换参数(6元组)
|
||||||
|
:param im_proj: 投影信息(WKT字符串)
|
||||||
|
:param output_path: 输出文件路径(无需扩展名,会自动生成.dat和.hdr)
|
||||||
|
"""
|
||||||
|
im_bands = 1
|
||||||
|
im_height, im_width = im_data.shape
|
||||||
|
# 创建ENVI格式驱动
|
||||||
|
driver = gdal.GetDriverByName("GTiff")
|
||||||
|
dataset = driver.Create(output_path, im_width, im_height, 1, gdal.GDT_Float32)
|
||||||
|
|
||||||
|
if dataset is not None:
|
||||||
|
dataset.SetGeoTransform(im_geotrans) # 设置地理变换参数
|
||||||
|
dataset.SetProjection(im_proj) # 设置投影
|
||||||
|
|
||||||
|
dataset.GetRasterBand(1).WriteArray(im_data)
|
||||||
|
|
||||||
|
dataset.FlushCache() # 确保数据写入磁盘
|
||||||
|
dataset = None # 关闭文件
|
||||||
|
|
||||||
|
|
||||||
|
def Strech_linear(im_data):
|
||||||
|
im_data_dB=10*np.log10(im_data)
|
||||||
|
immask=np.isfinite(im_data_dB)
|
||||||
|
infmask = np.isinf(im_data_dB)
|
||||||
|
imvail_data=im_data[immask]
|
||||||
|
im_data_dB=0
|
||||||
|
|
||||||
|
minvalue=np.nanmin(imvail_data)
|
||||||
|
maxvalue=np.nanmax(imvail_data)
|
||||||
|
|
||||||
|
infmask = np.isinf(im_data_dB)
|
||||||
|
im_data[infmask] = minvalue-100
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254+1
|
||||||
|
im_data=np.clip(im_data,0,255)
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
def Strech_linear1(im_data):
|
||||||
|
im_data_dB = 10 * np.log10(im_data)
|
||||||
|
immask = np.isfinite(im_data_dB)
|
||||||
|
infmask = np.isinf(im_data_dB)
|
||||||
|
imvail_data = im_data[immask]
|
||||||
|
im_data_dB=0
|
||||||
|
|
||||||
|
minvalue=np.percentile(imvail_data,1)
|
||||||
|
maxvalue = np.percentile(imvail_data, 99)
|
||||||
|
|
||||||
|
|
||||||
|
im_data[infmask] = minvalue - 100
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254 + 1
|
||||||
|
im_data = np.clip(im_data, 0, 255)
|
||||||
|
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
|
||||||
|
def Strech_linear2(im_data):
|
||||||
|
im_data_dB = 10 * np.log10(im_data)
|
||||||
|
immask = np.isfinite(im_data_dB)
|
||||||
|
infmask = np.isinf(im_data_dB)
|
||||||
|
imvail_data = im_data[immask]
|
||||||
|
im_data_dB = 0
|
||||||
|
|
||||||
|
minvalue = np.percentile(imvail_data, 2)
|
||||||
|
maxvalue = np.percentile(imvail_data, 98)
|
||||||
|
|
||||||
|
im_data[infmask] = minvalue - 100
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254 + 1
|
||||||
|
im_data = np.clip(im_data, 0, 255)
|
||||||
|
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
def Strech_linear5(im_data):
|
||||||
|
im_data_dB = 10 * np.log10(im_data)
|
||||||
|
immask = np.isfinite(im_data_dB)
|
||||||
|
infmask = np.isinf(im_data_dB)
|
||||||
|
imvail_data = im_data[immask]
|
||||||
|
im_data_dB = 0
|
||||||
|
|
||||||
|
minvalue = np.percentile(imvail_data, 5)
|
||||||
|
maxvalue = np.percentile(imvail_data, 95)
|
||||||
|
|
||||||
|
im_data[infmask] = minvalue - 100
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254 + 1
|
||||||
|
im_data = np.clip(im_data, 0, 255)
|
||||||
|
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
def Strech_SquareRoot(im_data):
|
||||||
|
# 判断是否为dB
|
||||||
|
# immask = np.isfinite(im_data)
|
||||||
|
# imvail_data = im_data[immask]
|
||||||
|
# minvalue = np.percentile(imvail_data,30)
|
||||||
|
# if minvalue<0 :
|
||||||
|
# im_data=np.power(10.0,im_data/10.0)
|
||||||
|
|
||||||
|
im_data=np.sqrt(im_data)
|
||||||
|
immask = np.isfinite(im_data)
|
||||||
|
imvail_data = im_data[immask]
|
||||||
|
|
||||||
|
minvalue=np.nanmin(imvail_data)
|
||||||
|
maxvalue=np.nanmax(imvail_data)
|
||||||
|
minvalue_01Prec = np.percentile(imvail_data, 2) # 20250904 1%拉伸
|
||||||
|
maxvalue_999Prec = np.percentile(imvail_data, 98)
|
||||||
|
print('sqrt root min - max ', minvalue,maxvalue)
|
||||||
|
if (maxvalue-minvalue)/(maxvalue_999Prec-minvalue_01Prec)>3: # 表示 拉伸之后,像素值绝大部分很有可能集中在 80
|
||||||
|
minvalue=minvalue_01Prec
|
||||||
|
maxvalue=maxvalue_999Prec
|
||||||
|
print('sqrt root min(0.1) - max(99.9) ', minvalue, maxvalue)
|
||||||
|
|
||||||
|
|
||||||
|
im_data = (im_data - minvalue) / (maxvalue - minvalue) * 254 + 1
|
||||||
|
im_data = np.clip(im_data, 0, 255)
|
||||||
|
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
def DataStrech(im_data,strechmethod):
|
||||||
|
# [,"Linear1","Linear2","Linear5","SquareRoot"]
|
||||||
|
if strechmethod == "Linear" :
|
||||||
|
return Strech_linear(im_data)
|
||||||
|
elif strechmethod == "Linear1":
|
||||||
|
return Strech_linear1(im_data)
|
||||||
|
elif strechmethod == "Linear2":
|
||||||
|
return Strech_linear2(im_data)
|
||||||
|
elif strechmethod == "Linear5":
|
||||||
|
return Strech_linear5(im_data)
|
||||||
|
elif strechmethod == "SquareRoot":
|
||||||
|
return Strech_SquareRoot(im_data)
|
||||||
|
else:
|
||||||
|
return im_data.astype(np.uint8)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 文件模式
|
||||||
|
def stretchProcess(infilepath,outfilepath,strechmethod):
|
||||||
|
im_proj, im_Geotrans, im_data=read_tif(infilepath)
|
||||||
|
envifilepath=get_filename_without_ext(outfilepath)+".bin"
|
||||||
|
envifilepath=os.path.join(os.path.dirname(outfilepath),envifilepath)
|
||||||
|
im_data = DataStrech(im_data,strechmethod)
|
||||||
|
im_data = im_data.astype(np.uint8)
|
||||||
|
write_envi(im_data,im_Geotrans,im_proj,envifilepath)
|
||||||
|
Image.fromarray(im_data).save(outfilepath,compress_level=0)
|
||||||
|
print("图像拉伸处理结束")
|
||||||
|
|
||||||
|
|
||||||
|
#切片模式
|
||||||
|
def getSlicePoints(h):
|
||||||
|
n = int(math.floor((h - 1024) * 1.2 / sliceSize))
|
||||||
|
step=int(math.ceil((h-1024)/n))
|
||||||
|
ti=list(range(0,h-1024,step))
|
||||||
|
ti.append(h-1024)
|
||||||
|
# 评价重叠率
|
||||||
|
movelayer=[]
|
||||||
|
for i in range(len(ti)-1):
|
||||||
|
movelayer.append((ti[i] + 1024 - ti[i + 1]) / 1024 * 100.0)
|
||||||
|
print("重叠率:",movelayer)
|
||||||
|
return ti
|
||||||
|
|
||||||
|
|
||||||
|
def getsliceGeotrans(GeoTransform,Xpixel,Ypixel):
|
||||||
|
XGeo = GeoTransform[0]+GeoTransform[1]*Xpixel+GeoTransform[2]*Ypixel
|
||||||
|
YGeo = GeoTransform[3]+GeoTransform[4]*Xpixel+GeoTransform[5]*Ypixel
|
||||||
|
result=[
|
||||||
|
XGeo,GeoTransform[1],GeoTransform[2],
|
||||||
|
YGeo,GeoTransform[4],GeoTransform[5]
|
||||||
|
]
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def is_all_same(lst):
|
||||||
|
arr = np.array(lst)
|
||||||
|
# arr_num=arr.size
|
||||||
|
sum_data=np.sum(arr != arr[0])
|
||||||
|
return sum_data<400
|
||||||
|
|
||||||
|
def getNextSliceNumber(n,sliceSize,overlap=0.25):
|
||||||
|
step=int(sliceSize*(1-overlap))+1
|
||||||
|
ti = list(range(0, n, step))
|
||||||
|
newN= n if ti[-1]+1024 < n else ti[-1]+1024
|
||||||
|
# 评价重叠率
|
||||||
|
movelayer=[]
|
||||||
|
for i in range(len(ti)-1):
|
||||||
|
movelayer.append((ti[i] + 1024 - ti[i + 1]) / 1024 * 100.0)
|
||||||
|
print("重叠率:",movelayer)
|
||||||
|
return newN,ti
|
||||||
|
|
||||||
|
def sliceDataset(rootname,im_data,src_im_data, im_Geotrans, im_proj, outfolder):
|
||||||
|
binfolder=os.path.join(outfolder,"unit8binfolder")
|
||||||
|
pngfolder=os.path.join(outfolder,"pngfolder")
|
||||||
|
tifffolder=os.path.join(outfolder,"tifffolder")
|
||||||
|
|
||||||
|
|
||||||
|
h,w=im_data.shape
|
||||||
|
nextH,ht=getNextSliceNumber(h,sliceSize,BlockOverLayer)
|
||||||
|
nextW,wt=getNextSliceNumber(w,sliceSize,BlockOverLayer)
|
||||||
|
padH=nextH-h
|
||||||
|
padW=nextW-w
|
||||||
|
im_data=np.pad(im_data,((0,padH),(0,padW)),mode='constant',constant_values=0)
|
||||||
|
src_im_data=np.pad(src_im_data,((0,padH),(0,padW)),mode='constant',constant_values=0)
|
||||||
|
slice_ID=0
|
||||||
|
for hi in ht:
|
||||||
|
for wi in wt:
|
||||||
|
geotrans_temp=getsliceGeotrans(im_Geotrans,wi,hi)
|
||||||
|
im_data_temp=im_data[hi:hi+1024,wi:wi+1024]
|
||||||
|
src_im_data_temp=src_im_data[hi:hi+1024,wi:wi+1024]
|
||||||
|
slice_ID = slice_ID + 1
|
||||||
|
if not is_all_same(im_data_temp):
|
||||||
|
sliceBinPath=os.path.join(binfolder, rootname+"_"+str(slice_ID).zfill(4)+"_image.tiff")
|
||||||
|
slicepngPath=os.path.join(pngfolder, rootname+"_"+str(slice_ID).zfill(4)+"_image.png")
|
||||||
|
slicesrctiffPath=os.path.join(tifffolder, rootname+"_"+str(slice_ID).zfill(4)+"_image.tiff")
|
||||||
|
|
||||||
|
write_tiff(src_im_data_temp, geotrans_temp, im_proj, slicesrctiffPath)
|
||||||
|
write_envi(im_data_temp,geotrans_temp,im_proj,sliceBinPath)
|
||||||
|
Image.fromarray(im_data_temp).save(slicepngPath,compress_level=0)
|
||||||
|
|
||||||
|
print("图像切片结束")
|
||||||
|
|
||||||
|
|
||||||
|
def stretchSliceProcess(infilepath, outfolder, strechmethod):
|
||||||
|
binfolder=os.path.join(outfolder,"unit8binfolder")
|
||||||
|
pngfolder=os.path.join(outfolder,"pngfolder")
|
||||||
|
tifffolder=os.path.join(outfolder,"tifffolder")
|
||||||
|
allpngfolder = os.path.join(outfolder, "allpngfolder")
|
||||||
|
if not os.path.exists(binfolder):
|
||||||
|
os.makedirs(binfolder)
|
||||||
|
if not os.path.exists(pngfolder):
|
||||||
|
os.makedirs(pngfolder)
|
||||||
|
if not os.path.exists(tifffolder):
|
||||||
|
os.makedirs(tifffolder)
|
||||||
|
if not os.path.exists(allpngfolder):
|
||||||
|
os.makedirs(allpngfolder)
|
||||||
|
im_proj, im_Geotrans, im_data=read_tif(infilepath)
|
||||||
|
src_im_data=im_data*1.0
|
||||||
|
im_data = DataStrech(im_data,strechmethod) # 拉伸
|
||||||
|
im_data = im_data.astype(np.uint8)
|
||||||
|
rootname=Path(infilepath).stem
|
||||||
|
allImagePath=os.path.join(allpngfolder, rootname+"_all.png")
|
||||||
|
Image.fromarray(im_data).save(allImagePath,compress_level=0)
|
||||||
|
sliceDataset(rootname,im_data, src_im_data,im_Geotrans, im_proj, outfolder)
|
||||||
|
print("图像切片与拉伸完成")
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def getParams():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-i','--infile',type=str,default=r"F:\天仪SAR卫星数据集\舰船数据\bc2-sp-org-vv-20250205t032055-021998-000036-0055ee-01.tiff", help='输入shapefile文件')
|
||||||
|
# parser.add_argument('-o', '--outfile',type=str,default=r"F:\天仪SAR卫星数据集\舰船数据\bc2-sp-org-vv-20250205t032055-021998-000036-0055ee-01.png", help='输出geojson文件')
|
||||||
|
parser.add_argument('-o', '--outfile',type=str,default=r"F:\天仪SAR卫星数据集\舰船数据\切片结果", help='输出geojson文件')
|
||||||
|
group = parser.add_mutually_exclusive_group()
|
||||||
|
group.add_argument(
|
||||||
|
'--filemode',
|
||||||
|
action='store_const',
|
||||||
|
const='filemode',
|
||||||
|
dest='mode',
|
||||||
|
help='文件模式'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--slicemode',
|
||||||
|
action='store_const',
|
||||||
|
const='slicemode',
|
||||||
|
dest='mode',
|
||||||
|
help='切片模式'
|
||||||
|
)
|
||||||
|
parser.set_defaults(mode='slicemode')
|
||||||
|
group = parser.add_mutually_exclusive_group()
|
||||||
|
group.add_argument(
|
||||||
|
'--Linear',
|
||||||
|
action='store_const',
|
||||||
|
const='Linear',
|
||||||
|
dest='method',
|
||||||
|
help='线性拉伸'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--Linear1prec',
|
||||||
|
action='store_const',
|
||||||
|
const='Linear1',
|
||||||
|
dest='method',
|
||||||
|
help='1%线性拉伸'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--Linear2prec',
|
||||||
|
action='store_const',
|
||||||
|
const='Linear2',
|
||||||
|
dest='method',
|
||||||
|
help='2%线性拉伸'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--Linear5prec',
|
||||||
|
action='store_const',
|
||||||
|
const='Linear5',
|
||||||
|
dest='method',
|
||||||
|
help='5%线性拉伸'
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
'--SquareRoot',
|
||||||
|
action='store_const',
|
||||||
|
const='SquareRoot',
|
||||||
|
dest='method',
|
||||||
|
help='平方根拉伸'
|
||||||
|
)
|
||||||
|
parser.set_defaults(method='SquareRoot')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
parser = getParams()
|
||||||
|
intiffPath=parser.infile
|
||||||
|
modestr=parser.mode
|
||||||
|
methodstr = parser.method
|
||||||
|
if modestr == "filemode":
|
||||||
|
outbinPath = parser.outfile
|
||||||
|
print('infile=', intiffPath)
|
||||||
|
print('outfile=', outbinPath)
|
||||||
|
print('method=', methodstr)
|
||||||
|
stretchProcess(intiffPath, outbinPath, methodstr)
|
||||||
|
elif modestr == "slicemode":
|
||||||
|
outfolder = parser.outfile
|
||||||
|
print('infile=', intiffPath)
|
||||||
|
print('outfolder=', outfolder)
|
||||||
|
print('method=', methodstr)
|
||||||
|
stretchSliceProcess(intiffPath, outfolder, methodstr)
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
print("模式错误")
|
||||||
|
exit(2)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
exit(3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -6,11 +6,14 @@ import os
|
||||||
import argparse
|
import argparse
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy.spatial import KDTree
|
from scipy.spatial import KDTree
|
||||||
from DotaOperator import DotaObj,readDotaFile,writerDotaFile,createDota
|
from tools.DotaOperator import DotaObj,readDotaFile,writerDotaFile,createDota
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
def existOrCreate(dirpath):
|
||||||
|
if not os.path.exists(dirpath):
|
||||||
|
os.makedirs(dirpath)
|
||||||
|
|
||||||
def find_tif_files_pathlib(directory):
|
def find_tif_files_pathlib(directory):
|
||||||
path = Path(directory)
|
path = Path(directory)
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue