Compare commits

...

29 Commits
main ... master

Author SHA1 Message Date
chenzenghui e1fad5f0f1 切片样例数据 2025-12-12 11:00:19 +08:00
chenzenghui 9c8e14e2c7 更新点位程序 2025-11-24 16:13:48 +08:00
chenzenghui 5794cfbe49 更新港口文件 2025-10-10 20:30:37 +08:00
chenzenghui acf441db4a 修改了进度打印结果 2025-10-09 13:57:34 +08:00
chenzenghui 7226fe582f 修复无港口切片时,仍然执行港口切片的bug 2025-10-05 11:31:55 +08:00
chenzenghui b2f9b01555 更新港口切片逻辑 2025-10-03 14:06:14 +08:00
chenzenghui d63423ff18 更新港口切片逻辑 2025-10-03 13:37:55 +08:00
chenzenghui c689b2d84d 修改港口切片 2025-09-26 12:17:02 +08:00
chenzenghui 7882cdfe62 修改港口切片 2025-09-26 11:50:25 +08:00
chenzenghui 0f44939718 修改测试参数 2025-09-26 11:04:14 +08:00
陈增辉 654df6d3cc 1. 增加分块工具 2025-09-26 10:51:12 +08:00
chenzenghui cf2423fc6b 修复bug 2025-09-26 10:28:31 +08:00
陈增辉 db88494e41 1. 修改字符 2025-09-26 10:15:28 +08:00
chenzenghui a521ccb844 修复bug 2025-09-26 10:11:35 +08:00
陈增辉 d5e6af700a 1. 增加批处理工具 2025-09-26 10:03:52 +08:00
陈增辉 9ad27ac6d4 1. 增加批处理工具 2025-09-26 10:03:05 +08:00
陈增辉 0b64b18ef0 1. 增加专门针对港口的 shapefile 2 dota的程序 2025-09-26 09:52:26 +08:00
陈增辉 83f3d5750b 增加注释 2025-09-25 20:36:07 +08:00
chenzenghui 4cad12128c MJ舰船区分 2025-09-25 20:30:08 +08:00
chenzenghui ec99cabb07 只生成拉伸tiff,与港口坐标 2025-09-24 16:49:53 +08:00
chenzenghui 1a5372f04a 只生成拉伸tiff,与港口坐标 2025-09-24 16:46:53 +08:00
chenzenghui c702658884 按照JM区分 2025-09-22 18:07:46 +08:00
chenzenghui 595751a3c3 更新目标文件 2025-09-22 17:28:07 +08:00
陈增辉 a66f9ac220 增加军民港口文件区分 2025-09-22 17:18:26 +08:00
陈增辉 a9f390d2f8 增加军民港口文件区分 2025-09-22 17:14:55 +08:00
chenzenghui 2b72ea22db 移动港口切分文件 2025-09-22 15:54:22 +08:00
chenzenghui 2b3b14fa83 自动目标文件夹 2025-09-22 15:13:21 +08:00
陈增辉 e032838c39 拆分港口工具 2025-09-22 15:07:12 +08:00
chenzenghui dd10658c05 增加港口拆分数据 2025-09-22 14:19:21 +08:00
20 changed files with 3141 additions and 17 deletions

1
.idea/.gitignore vendored
View File

@ -3,3 +3,4 @@
/workspace.xml /workspace.xml
# 基于编辑器的 HTTP 客户端请求 # 基于编辑器的 HTTP 客户端请求
/httpRequests/ /httpRequests/
/vcs.xml

View File

@ -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">

View File

@ -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>

6
.idea/vcs.xml Normal file
View File

@ -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>

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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")

View File

@ -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)

BIN
data.rar Normal file

Binary file not shown.

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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"

View File

@ -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)

View File

@ -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.