shancx 1.8.92__py3-none-any.whl → 1.9.33.218__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- shancx/3D/__init__.py +25 -0
- shancx/Algo/Class.py +11 -0
- shancx/Algo/CudaPrefetcher1.py +112 -0
- shancx/Algo/Fake_image.py +24 -0
- shancx/Algo/Hsml.py +391 -0
- shancx/Algo/L2Loss.py +10 -0
- shancx/Algo/MetricTracker.py +132 -0
- shancx/Algo/Normalize.py +66 -0
- shancx/Algo/OptimizerWScheduler.py +38 -0
- shancx/Algo/Rmageresize.py +79 -0
- shancx/Algo/Savemodel.py +33 -0
- shancx/Algo/SmoothL1_losses.py +27 -0
- shancx/Algo/Tqdm.py +62 -0
- shancx/Algo/__init__.py +121 -0
- shancx/Algo/checknan.py +28 -0
- shancx/Algo/iouJU.py +83 -0
- shancx/Algo/mask.py +25 -0
- shancx/Algo/psnr.py +9 -0
- shancx/Algo/ssim.py +70 -0
- shancx/Algo/structural_similarity.py +308 -0
- shancx/Algo/tool.py +704 -0
- shancx/Calmetrics/__init__.py +97 -0
- shancx/Calmetrics/calmetrics.py +14 -0
- shancx/Calmetrics/calmetricsmatrixLib.py +147 -0
- shancx/Calmetrics/rmseR2score.py +35 -0
- shancx/Clip/__init__.py +50 -0
- shancx/Cmd.py +126 -0
- shancx/Config_.py +26 -0
- shancx/Df/DataFrame.py +11 -2
- shancx/Df/__init__.py +17 -0
- shancx/Df/tool.py +0 -0
- shancx/Diffm/Psamples.py +18 -0
- shancx/Diffm/__init__.py +0 -0
- shancx/Diffm/test.py +207 -0
- shancx/Doc/__init__.py +214 -0
- shancx/E/__init__.py +178 -152
- shancx/Fillmiss/__init__.py +0 -0
- shancx/Fillmiss/imgidwJU.py +46 -0
- shancx/Fillmiss/imgidwLatLonJU.py +82 -0
- shancx/Gpu/__init__.py +55 -0
- shancx/H9/__init__.py +126 -0
- shancx/H9/ahi_read_hsd.py +877 -0
- shancx/H9/ahisearchtable.py +298 -0
- shancx/H9/geometry.py +2439 -0
- shancx/Hug/__init__.py +81 -0
- shancx/Inst.py +22 -0
- shancx/Lib.py +31 -0
- shancx/Mos/__init__.py +37 -0
- shancx/NN/__init__.py +235 -106
- shancx/Path1.py +161 -0
- shancx/Plot/GlobMap.py +276 -116
- shancx/Plot/__init__.py +491 -1
- shancx/Plot/draw_day_CR_PNG.py +4 -21
- shancx/Plot/exam.py +116 -0
- shancx/Plot/plotGlobal.py +325 -0
- shancx/{radar_nmc.py → Plot/radarNmc.py} +4 -34
- shancx/{subplots_single_china_map.py → Plot/single_china_map.py} +1 -1
- shancx/Point.py +46 -0
- shancx/QC.py +223 -0
- shancx/RdPzl/__init__.py +32 -0
- shancx/Read.py +72 -0
- shancx/Resize.py +79 -0
- shancx/SN/__init__.py +62 -123
- shancx/Time/GetTime.py +9 -3
- shancx/Time/__init__.py +66 -1
- shancx/Time/timeCycle.py +302 -0
- shancx/Time/tool.py +0 -0
- shancx/Train/__init__.py +74 -0
- shancx/Train/makelist.py +187 -0
- shancx/Train/multiGpu.py +27 -0
- shancx/Train/prepare.py +161 -0
- shancx/Train/renet50.py +157 -0
- shancx/ZR.py +12 -0
- shancx/__init__.py +333 -262
- shancx/args.py +27 -0
- shancx/bak.py +768 -0
- shancx/df2database.py +62 -2
- shancx/geosProj.py +80 -0
- shancx/info.py +38 -0
- shancx/netdfJU.py +231 -0
- shancx/sendM.py +59 -0
- shancx/tensBoard/__init__.py +28 -0
- shancx/wait.py +246 -0
- {shancx-1.8.92.dist-info → shancx-1.9.33.218.dist-info}/METADATA +15 -5
- shancx-1.9.33.218.dist-info/RECORD +91 -0
- {shancx-1.8.92.dist-info → shancx-1.9.33.218.dist-info}/WHEEL +1 -1
- my_timer_decorator/__init__.py +0 -10
- shancx/Dsalgor/__init__.py +0 -19
- shancx/E/DFGRRIB.py +0 -30
- shancx/EN/DFGRRIB.py +0 -30
- shancx/EN/__init__.py +0 -148
- shancx/FileRead.py +0 -44
- shancx/Gray2RGB.py +0 -86
- shancx/M/__init__.py +0 -137
- shancx/MN/__init__.py +0 -133
- shancx/N/__init__.py +0 -131
- shancx/Plot/draw_day_CR_PNGUS.py +0 -206
- shancx/Plot/draw_day_CR_SVG.py +0 -275
- shancx/Plot/draw_day_pre_PNGUS.py +0 -205
- shancx/Plot/glob_nation_map.py +0 -116
- shancx/Plot/radar_nmc.py +0 -61
- shancx/Plot/radar_nmc_china_map_compare1.py +0 -50
- shancx/Plot/radar_nmc_china_map_f.py +0 -121
- shancx/Plot/radar_nmc_us_map_f.py +0 -128
- shancx/Plot/subplots_compare_devlop.py +0 -36
- shancx/Plot/subplots_single_china_map.py +0 -45
- shancx/S/__init__.py +0 -138
- shancx/W/__init__.py +0 -132
- shancx/WN/__init__.py +0 -132
- shancx/code.py +0 -331
- shancx/draw_day_CR_PNG.py +0 -200
- shancx/draw_day_CR_PNGUS.py +0 -206
- shancx/draw_day_CR_SVG.py +0 -275
- shancx/draw_day_pre_PNGUS.py +0 -205
- shancx/makenetCDFN.py +0 -42
- shancx/mkIMGSCX.py +0 -92
- shancx/netCDF.py +0 -130
- shancx/radar_nmc_china_map_compare1.py +0 -50
- shancx/radar_nmc_china_map_f.py +0 -125
- shancx/radar_nmc_us_map_f.py +0 -67
- shancx/subplots_compare_devlop.py +0 -36
- shancx/tool.py +0 -18
- shancx/user/H8mess.py +0 -317
- shancx/user/__init__.py +0 -137
- shancx/user/cinradHJN.py +0 -496
- shancx/user/examMeso.py +0 -293
- shancx/user/hjnDAAS.py +0 -26
- shancx/user/hjnFTP.py +0 -81
- shancx/user/hjnGIS.py +0 -320
- shancx/user/hjnGPU.py +0 -21
- shancx/user/hjnIDW.py +0 -68
- shancx/user/hjnKDTree.py +0 -75
- shancx/user/hjnLAPSTransform.py +0 -47
- shancx/user/hjnMiscellaneous.py +0 -182
- shancx/user/hjnProj.py +0 -162
- shancx/user/inotify.py +0 -41
- shancx/user/matplotlibMess.py +0 -87
- shancx/user/mkNCHJN.py +0 -623
- shancx/user/newTypeRadar.py +0 -492
- shancx/user/test.py +0 -6
- shancx/user/tlogP.py +0 -129
- shancx/util_log.py +0 -33
- shancx/wtx/H8mess.py +0 -315
- shancx/wtx/__init__.py +0 -151
- shancx/wtx/cinradHJN.py +0 -496
- shancx/wtx/colormap.py +0 -64
- shancx/wtx/examMeso.py +0 -298
- shancx/wtx/hjnDAAS.py +0 -26
- shancx/wtx/hjnFTP.py +0 -81
- shancx/wtx/hjnGIS.py +0 -330
- shancx/wtx/hjnGPU.py +0 -21
- shancx/wtx/hjnIDW.py +0 -68
- shancx/wtx/hjnKDTree.py +0 -75
- shancx/wtx/hjnLAPSTransform.py +0 -47
- shancx/wtx/hjnLog.py +0 -78
- shancx/wtx/hjnMiscellaneous.py +0 -201
- shancx/wtx/hjnProj.py +0 -161
- shancx/wtx/inotify.py +0 -41
- shancx/wtx/matplotlibMess.py +0 -87
- shancx/wtx/mkNCHJN.py +0 -613
- shancx/wtx/newTypeRadar.py +0 -492
- shancx/wtx/test.py +0 -6
- shancx/wtx/tlogP.py +0 -129
- shancx-1.8.92.dist-info/RECORD +0 -99
- /shancx/{Dsalgor → Algo}/dsalgor.py +0 -0
- {shancx-1.8.92.dist-info → shancx-1.9.33.218.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import ssl
|
|
4
|
+
import urllib.request
|
|
5
|
+
ssl._create_default_https_context = ssl._create_unverified_context
|
|
6
|
+
import datetime
|
|
7
|
+
import numpy as np
|
|
8
|
+
import matplotlib.pyplot as plt
|
|
9
|
+
import cartopy.crs as ccrs
|
|
10
|
+
import cartopy.feature as cfeature
|
|
11
|
+
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
|
|
12
|
+
from hjnwtx.colormap import cmp_hjnwtx
|
|
13
|
+
import os
|
|
14
|
+
def plotGlobal(b, latArr1, lonArr1, cmap='summer', title='Global QPF Data Visualization',saveDir = "./plotGlobal",ty=None ):
|
|
15
|
+
now_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
|
16
|
+
plt.figure(figsize=(20, 10), dpi=100)
|
|
17
|
+
ax = plt.axes(projection=ccrs.PlateCarree())
|
|
18
|
+
ax.add_feature(cfeature.LAND, facecolor='none') # 陆地无色
|
|
19
|
+
ax.add_feature(cfeature.OCEAN, facecolor='none') # 海洋无色
|
|
20
|
+
ax.add_feature(cfeature.COASTLINE, linewidth=0.8, edgecolor='black') # 海岸线黑色
|
|
21
|
+
ax.add_feature(cfeature.BORDERS, linestyle='-', linewidth=0.5, edgecolor='black') # 国界线黑色
|
|
22
|
+
ax.add_feature(cfeature.LAKES, alpha=0.3, facecolor='none', edgecolor='gray') # 湖泊无色,灰色边界
|
|
23
|
+
ax.add_feature(cfeature.RIVERS, edgecolor='gray', linewidth=0.5) # 河流灰色
|
|
24
|
+
lon_grid, lat_grid = np.meshgrid(lonArr1, latArr1)
|
|
25
|
+
stride = 10 # 每10个点取1个
|
|
26
|
+
cmap = {
|
|
27
|
+
"radar": cmp_hjnwtx["radar_nmc"],
|
|
28
|
+
"pre": cmp_hjnwtx["pre_tqw"],
|
|
29
|
+
None: 'summer'
|
|
30
|
+
}.get(ty)
|
|
31
|
+
img = ax.pcolormesh(lon_grid[::stride, ::stride],
|
|
32
|
+
lat_grid[::stride, ::stride],
|
|
33
|
+
b[::stride, ::stride],
|
|
34
|
+
cmap=cmap,
|
|
35
|
+
shading='auto',
|
|
36
|
+
transform=ccrs.PlateCarree())
|
|
37
|
+
cbar = plt.colorbar(img, ax=ax, orientation='vertical', pad=0.05, shrink=0.6)
|
|
38
|
+
cbar.set_label('Value Scale', fontsize=12)
|
|
39
|
+
ax.set_xticks(np.arange(-180, 181, 30), crs=ccrs.PlateCarree())
|
|
40
|
+
ax.set_yticks(np.arange(-90, 91, 15), crs=ccrs.PlateCarree())
|
|
41
|
+
ax.xaxis.set_major_formatter(LongitudeFormatter(zero_direction_label=True))
|
|
42
|
+
ax.yaxis.set_major_formatter(LatitudeFormatter())
|
|
43
|
+
ax.gridlines(color='gray', linestyle=':', alpha=0.5)
|
|
44
|
+
ax.set_title(title, fontsize=16, pad=20)
|
|
45
|
+
ax.set_global()
|
|
46
|
+
plt.tight_layout()
|
|
47
|
+
os.makedirs(saveDir, exist_ok=True)
|
|
48
|
+
plt.savefig(f"./{saveDir}/plotScatter_glob{now_str}.png", dpi=300, bbox_inches="tight")
|
|
49
|
+
plt.close()
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
plotGlobal(b, latArr1, lonArr1,
|
|
53
|
+
title='Global Meteorological Data',ty="radar")
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
import datetime
|
|
58
|
+
import numpy as np
|
|
59
|
+
import matplotlib.pyplot as plt
|
|
60
|
+
import cartopy.crs as ccrs
|
|
61
|
+
import cartopy.feature as cfeature
|
|
62
|
+
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
|
|
63
|
+
from hjnwtx.colormap import cmp_hjnwtx
|
|
64
|
+
import os
|
|
65
|
+
|
|
66
|
+
def plotGlobalPlus(b, latArr1, lonArr1, cmap='summer', title='Global QPF Data Visualization',
|
|
67
|
+
saveDir="./plotGlobal", ty=None, cartopy_data_dir="./share/cartopy"):
|
|
68
|
+
os.environ['CARTOPY_USER_BACKGROUNDS'] = cartopy_data_dir
|
|
69
|
+
os.makedirs(cartopy_data_dir, exist_ok=True)
|
|
70
|
+
now_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
|
71
|
+
plt.figure(figsize=(20, 10), dpi=100)
|
|
72
|
+
ax = plt.axes(projection=ccrs.PlateCarree())
|
|
73
|
+
try:
|
|
74
|
+
ax.add_feature(cfeature.LAND.with_scale('110m'), facecolor='none')
|
|
75
|
+
ax.add_feature(cfeature.OCEAN.with_scale('110m'), facecolor='none')
|
|
76
|
+
ax.add_feature(cfeature.COASTLINE.with_scale('110m'), linewidth=0.8, edgecolor='black')
|
|
77
|
+
ax.add_feature(cfeature.BORDERS.with_scale('110m'), linestyle='-', linewidth=0.5, edgecolor='black')
|
|
78
|
+
ax.add_feature(cfeature.LAKES.with_scale('110m'), alpha=0.3, facecolor='none', edgecolor='gray')
|
|
79
|
+
ax.add_feature(cfeature.RIVERS.with_scale('110m'), edgecolor='gray', linewidth=0.5)
|
|
80
|
+
except:
|
|
81
|
+
ax.add_feature(cfeature.LAND, facecolor='none')
|
|
82
|
+
ax.add_feature(cfeature.OCEAN, facecolor='none')
|
|
83
|
+
ax.add_feature(cfeature.COASTLINE, linewidth=0.8, edgecolor='black')
|
|
84
|
+
ax.add_feature(cfeature.BORDERS, linestyle='-', linewidth=0.5, edgecolor='black')
|
|
85
|
+
ax.add_feature(cfeature.LAKES, alpha=0.3, facecolor='none', edgecolor='gray')
|
|
86
|
+
ax.add_feature(cfeature.RIVERS, edgecolor='gray', linewidth=0.5)
|
|
87
|
+
lon_grid, lat_grid = np.meshgrid(lonArr1, latArr1)
|
|
88
|
+
stride = 10 # 每10个点取1个
|
|
89
|
+
cmap = {
|
|
90
|
+
"radar": cmp_hjnwtx["radar_nmc"],
|
|
91
|
+
"pre": cmp_hjnwtx["pre_tqw"],
|
|
92
|
+
None: cmap
|
|
93
|
+
}.get(ty, cmap)
|
|
94
|
+
img = ax.pcolormesh(lon_grid[::stride, ::stride],
|
|
95
|
+
lat_grid[::stride, ::stride],
|
|
96
|
+
b[::stride, ::stride],
|
|
97
|
+
cmap=cmap,
|
|
98
|
+
shading='auto',
|
|
99
|
+
transform=ccrs.PlateCarree())
|
|
100
|
+
cbar = plt.colorbar(img, ax=ax, orientation='vertical', pad=0.05, shrink=0.6)
|
|
101
|
+
cbar.set_label('Value Scale', fontsize=12)
|
|
102
|
+
ax.set_xticks(np.arange(-180, 181, 30), crs=ccrs.PlateCarree())
|
|
103
|
+
ax.set_yticks(np.arange(-90, 91, 15), crs=ccrs.PlateCarree())
|
|
104
|
+
ax.xaxis.set_major_formatter(LongitudeFormatter(zero_direction_label=True))
|
|
105
|
+
ax.yaxis.set_major_formatter(LatitudeFormatter())
|
|
106
|
+
ax.gridlines(color='gray', linestyle=':', alpha=0.5)
|
|
107
|
+
ax.set_title(title, fontsize=16, pad=20)
|
|
108
|
+
ax.set_global()
|
|
109
|
+
plt.tight_layout()
|
|
110
|
+
os.makedirs(saveDir, exist_ok=True)
|
|
111
|
+
save_path = os.path.join(saveDir, f"plotScatter_glob{now_str}.png")
|
|
112
|
+
plt.savefig(save_path, dpi=300, bbox_inches="tight")
|
|
113
|
+
plt.close()
|
|
114
|
+
print(f"图像已保存到: {save_path}")
|
|
115
|
+
return save_path
|
|
116
|
+
"""
|
|
117
|
+
if __name__ == "__main__":
|
|
118
|
+
plotGlobal(
|
|
119
|
+
b=CR,
|
|
120
|
+
latArr1=latArr,
|
|
121
|
+
lonArr1=lonArr,
|
|
122
|
+
title='Global Precipitation Forecast',
|
|
123
|
+
saveDir='./output',
|
|
124
|
+
ty='pre',
|
|
125
|
+
cartopy_data_dir='./share/cartopy'
|
|
126
|
+
)
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
import ssl
|
|
130
|
+
import urllib.request
|
|
131
|
+
ssl._create_default_https_context = ssl._create_unverified_context
|
|
132
|
+
import matplotlib.pyplot as plt
|
|
133
|
+
import cartopy.crs as ccrs
|
|
134
|
+
import cartopy.feature as cfeature
|
|
135
|
+
import os
|
|
136
|
+
import datetime
|
|
137
|
+
import numpy as np
|
|
138
|
+
def plotScatter(df1, title = "Total number ",saveDir="plotScatter", map_background=True,
|
|
139
|
+
projection=ccrs.PlateCarree(), figsize=(12, 8)):
|
|
140
|
+
now_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
|
141
|
+
if map_background:
|
|
142
|
+
fig = plt.figure(figsize=figsize)
|
|
143
|
+
ax = plt.axes(projection=projection)
|
|
144
|
+
ax.add_feature(cfeature.LAND, facecolor='none', alpha=0.3)
|
|
145
|
+
ax.add_feature(cfeature.OCEAN, facecolor='none', alpha=0.3)
|
|
146
|
+
ax.add_feature(cfeature.COASTLINE, linewidth=0.8, edgecolor='black')
|
|
147
|
+
ax.add_feature(cfeature.BORDERS, linestyle='-', linewidth=0.5, edgecolor='black')
|
|
148
|
+
ax.add_feature(cfeature.LAKES, alpha=0.3, facecolor='gray')
|
|
149
|
+
ax.add_feature(cfeature.RIVERS, edgecolor='gray', linewidth=0.5)
|
|
150
|
+
ax.gridlines(draw_labels=True, linewidth=0.5, color='gray', alpha=0.5, linestyle='--')
|
|
151
|
+
if len(df1) > 0:
|
|
152
|
+
buffer = 5 # 边距
|
|
153
|
+
min_lon, max_lon = df1["Lon"].min() - buffer, df1["Lon"].max() + buffer
|
|
154
|
+
min_lat, max_lat = df1["Lat"].min() - buffer, df1["Lat"].max() + buffer
|
|
155
|
+
# ax.set_extent([min_lon, max_lon, min_lat, max_lat], crs=ccrs.PlateCarree())
|
|
156
|
+
ax.set_global()
|
|
157
|
+
else:
|
|
158
|
+
ax.set_global() # 如果没有数据,显示全球
|
|
159
|
+
scatter = ax.scatter(
|
|
160
|
+
df1["Lon"],
|
|
161
|
+
df1["Lat"],
|
|
162
|
+
s=0.5,
|
|
163
|
+
alpha=0.7,
|
|
164
|
+
edgecolor="red",
|
|
165
|
+
linewidth=0.5,
|
|
166
|
+
color='red',
|
|
167
|
+
transform=ccrs.PlateCarree(), # 重要:指定坐标变换
|
|
168
|
+
zorder=10 # 确保散点在地图上方
|
|
169
|
+
)
|
|
170
|
+
plt.title(title, fontsize=14, pad=20)
|
|
171
|
+
|
|
172
|
+
plt.tight_layout()
|
|
173
|
+
os.makedirs(saveDir, exist_ok=True)
|
|
174
|
+
plt.savefig(f"./{saveDir}/plotScatter_{now_str}.png", dpi=300, bbox_inches="tight")
|
|
175
|
+
plt.close()
|
|
176
|
+
print(f"散点图已保存到: ./{saveDir}/plotScatter_{now_str}.png")
|
|
177
|
+
print(f"总共绘制了 {len(df1)} 个点")
|
|
178
|
+
|
|
179
|
+
"""
|
|
180
|
+
plotScatter(df2,title = f" Total number of stations ", saveDir="scatter_maps")
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
import ssl
|
|
184
|
+
import urllib.request
|
|
185
|
+
ssl._create_default_https_context = ssl._create_unverified_context
|
|
186
|
+
import datetime
|
|
187
|
+
import numpy as np
|
|
188
|
+
import matplotlib.pyplot as plt
|
|
189
|
+
import cartopy.crs as ccrs
|
|
190
|
+
import cartopy.feature as cfeature
|
|
191
|
+
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
|
|
192
|
+
from hjnwtx.colormap import cmp_hjnwtx
|
|
193
|
+
from shancx import crDir
|
|
194
|
+
def plotBorder(UTCstr, nclon, nclat, cr, fig_title,savepath="./plotBorder", datatype=None,font_path=None,shp_file="./"):
|
|
195
|
+
myfont = mpl.font_manager.FontProperties(fname = font_path, size = 12)
|
|
196
|
+
figpath = f"{savepath}/fig/{UTCstr[:4]}/{UTCstr[:8]}/{fig_title}.PNG"
|
|
197
|
+
crDir(figpath)
|
|
198
|
+
lonmin = np.min(nclon)
|
|
199
|
+
lonmax = np.max(nclon)
|
|
200
|
+
latmin = np.min(nclat)
|
|
201
|
+
latmax = np.max(nclat)
|
|
202
|
+
# 创建图形和坐标轴
|
|
203
|
+
fig = plt.figure(figsize=(6, 6))
|
|
204
|
+
ax = plt.axes(projection=ccrs.PlateCarree())
|
|
205
|
+
# 1. 首先添加Cartopy的基础地理要素(作为底层)
|
|
206
|
+
ax.add_feature(cfeature.OCEAN, facecolor='none') # 海洋无色
|
|
207
|
+
ax.add_feature(cfeature.LAND, facecolor='none') # 陆地无色
|
|
208
|
+
ax.add_feature(cfeature.COASTLINE, linewidth=0.8, edgecolor='gray') # 海岸线
|
|
209
|
+
ax.add_feature(cfeature.BORDERS, linestyle='-', linewidth=0.5, edgecolor='gray') # 国界线
|
|
210
|
+
ax.add_feature(cfeature.LAKES, alpha=0.3, facecolor='none', edgecolor='gray') # 湖泊
|
|
211
|
+
ax.add_feature(cfeature.RIVERS, edgecolor='gray', linewidth=0.5) # 河流
|
|
212
|
+
ax.set_xticks(np.arange(lonmin, lonmax + 0.1, 15))
|
|
213
|
+
ax.set_yticks(np.arange(latmin, latmax + 0.1, 10))
|
|
214
|
+
ax.set_xlim([nclon[0], nclon[-1]])
|
|
215
|
+
ax.set_ylim([nclat[-1], nclat[0]])
|
|
216
|
+
ax.xaxis.set_major_formatter(LongitudeFormatter())
|
|
217
|
+
ax.yaxis.set_major_formatter(LatitudeFormatter())
|
|
218
|
+
ax.tick_params(axis='both', labelsize=10)
|
|
219
|
+
# 3. 叠加自定义的省界矢量(显示在基础地理要素之上)
|
|
220
|
+
if os.path.exists(shp_file) and shp_file[-4:]==".shp" :
|
|
221
|
+
try:
|
|
222
|
+
shp = gpd.read_file(shp_file).boundary
|
|
223
|
+
# 使用较细的线宽,避免与国界线混淆
|
|
224
|
+
shp.plot(ax=ax, edgecolor='grey', linewidth=0.5, linestyle='-')
|
|
225
|
+
except Exception as e:
|
|
226
|
+
print(f"警告:读取矢量文件 {shp_file} 失败: {e}")
|
|
227
|
+
else:
|
|
228
|
+
print(f"警告:矢量文件 {shp_file} 不存在,将只绘制Cartopy地理要素。")
|
|
229
|
+
ax.set_title(fig_title, fontsize=12, loc='center', fontproperties=myfont)
|
|
230
|
+
# 5. 绘制雷达或降雨数据(在最上层)
|
|
231
|
+
if datatype == 'radar':
|
|
232
|
+
clevels = [0, 10, 20, 30, 40, 50, 60, 70]
|
|
233
|
+
colors = ['#62e6eaff', '#00d72eff', '#fefe3fff', '#ff9a29ff', '#d70e15ff', '#ff1cecff', '#af91edff']
|
|
234
|
+
elif datatype == 'rain':
|
|
235
|
+
clevels = [0.1, 2.5, 8, 16, 200]
|
|
236
|
+
colors = ["#a6f28f", "#3dba3d", "#61b8ff", "#0000ff"]
|
|
237
|
+
cs = plt.contourf(nclon, nclat, cr, levels=clevels, colors=colors, extend='both')
|
|
238
|
+
cb = plt.colorbar(cs, fraction=0.022, pad=0.03)
|
|
239
|
+
cb.set_ticks(clevels[:-1])
|
|
240
|
+
cb.set_ticklabels([str(level) for level in clevels[:-1]], fontproperties=myfont)
|
|
241
|
+
for label in ax.get_xticklabels() + ax.get_yticklabels():
|
|
242
|
+
label.set_fontproperties(myfont)
|
|
243
|
+
plt.savefig(figpath, dpi=300, bbox_inches='tight')
|
|
244
|
+
print(f"{fig_title.split('_')[0]}绘制完成: {figpath}")
|
|
245
|
+
plt.close()
|
|
246
|
+
|
|
247
|
+
"""
|
|
248
|
+
latArr = np.linspace(27, -13, 2000 )
|
|
249
|
+
lonArr = np.linspace(70, 150, 4000)
|
|
250
|
+
font_path = '/mnt/wtx_weather_forecast/scx/sever7/微软雅黑.ttf'
|
|
251
|
+
|
|
252
|
+
fig_title = f"实况雷达回波_{UTCstr}_test"
|
|
253
|
+
baseCR[:,900:3700] = CR
|
|
254
|
+
plotBorder(UTCstr,lonArr,latArr,baseCR,fig_title,datatype="radar",font_path=font_path)
|
|
255
|
+
fig_title = f"卫星反演雷达回波_{UTCstr}"
|
|
256
|
+
"""
|
|
257
|
+
|
|
258
|
+
import matplotlib as mpl
|
|
259
|
+
import matplotlib.pyplot as plt
|
|
260
|
+
import cartopy.crs as ccrs
|
|
261
|
+
import geopandas as gpd
|
|
262
|
+
from cartopy.mpl.ticker import LongitudeFormatter,LatitudeFormatter
|
|
263
|
+
import numpy as np
|
|
264
|
+
from shancx import crDir
|
|
265
|
+
def plot_fig1(cr,nclat,nclon,fig_title,datatype=None,savepath=None,font_path=None,shp_file=None):
|
|
266
|
+
figpath = f"{savepath}/fig/{fig_title.split('_')[1][:4]}/{fig_title.split('_')[1][:8]}/{fig_title.split('_')[1][:12]}/{fig_title}.PNG"
|
|
267
|
+
# if not os.path.exists(figpath):
|
|
268
|
+
lonmin = np.min(nclon)
|
|
269
|
+
lonmax = np.max(nclon)
|
|
270
|
+
latmin = np.min(nclat)
|
|
271
|
+
latmax = np.max(nclat)
|
|
272
|
+
myfont = mpl.font_manager.FontProperties(fname = font_path, size = 12)
|
|
273
|
+
fig = plt.figure(figsize=(6,6))
|
|
274
|
+
ax = plt.axes(projection=ccrs.PlateCarree())
|
|
275
|
+
ax.set_xticks(np.arange(lonmin, lonmax + 0.1, 15))
|
|
276
|
+
ax.set_yticks(np.arange(latmin, latmax + 0.1, 10))
|
|
277
|
+
ax.set_xlim([lonmin, lonmax])
|
|
278
|
+
ax.set_ylim([latmin, latmax])
|
|
279
|
+
ax.xaxis.set_major_formatter(LongitudeFormatter()) #刻度格式转换为经纬度样式
|
|
280
|
+
ax.yaxis.set_major_formatter(LatitudeFormatter())
|
|
281
|
+
ax.tick_params(axis = 'both',labelsize = 10)
|
|
282
|
+
shp = gpd.read_file(shp_file).boundary
|
|
283
|
+
shp.plot(ax=ax, edgecolor='grey', linewidth=0.7)
|
|
284
|
+
ax.set_title(fig_title, fontsize = 12, loc='center',fontproperties = myfont)
|
|
285
|
+
if datatype == 'radar':
|
|
286
|
+
clevels = [0,10, 20, 30, 40, 50, 60, 70]
|
|
287
|
+
colors = ['#62e6eaff','#00d72eff','#fefe3fff','#ff9a29ff','#d70e15ff','#ff1cecff','#af91edff']
|
|
288
|
+
# colors = ["#449ded", "#62e6ea", "#68f952", "#0000ff"]
|
|
289
|
+
elif datatype == 'rain':
|
|
290
|
+
clevels = [0.1, 2.5, 8, 16,200]
|
|
291
|
+
colors = ["#a6f28f", "#3dba3d", "#61b8ff", "#0000ff"]
|
|
292
|
+
if datatype == 'sat':
|
|
293
|
+
clevels = [150,170, 190, 210, 230, 250, 270, 290,310]
|
|
294
|
+
colors = [
|
|
295
|
+
'#00008B', # 150K 深蓝
|
|
296
|
+
'#0066CC', # 170K 钴蓝
|
|
297
|
+
'#00BFFF', # 190K 深天蓝
|
|
298
|
+
'#40E0D0', # 210K 绿松石
|
|
299
|
+
'#00FF00', # 230K 亮绿
|
|
300
|
+
'#FFFF00', # 250K 黄色
|
|
301
|
+
'#FFA500', # 270K 橙色
|
|
302
|
+
'#FF4500', # 290K 橙红
|
|
303
|
+
'#FF0000' # 310K 红色
|
|
304
|
+
]
|
|
305
|
+
cs = plt.contourf(nclon, nclat, cr, levels=clevels, colors=colors)
|
|
306
|
+
cb = plt.colorbar(cs, fraction=0.022)
|
|
307
|
+
cb.set_ticks(clevels[:-1])
|
|
308
|
+
cb.set_ticklabels([str(level) for level in clevels[:-1]],fontproperties = myfont)
|
|
309
|
+
for label in ax.get_xticklabels() + ax.get_yticklabels():
|
|
310
|
+
label.set_fontproperties(myfont)
|
|
311
|
+
crDir(figpath)
|
|
312
|
+
plt.savefig(figpath, dpi=300, bbox_inches='tight')
|
|
313
|
+
print(f"{fig_title.split('_')[0]}绘制完成: {figpath}")
|
|
314
|
+
plt.close()
|
|
315
|
+
"""
|
|
316
|
+
font_path = './shp/微软雅黑.ttf'
|
|
317
|
+
myfont = mpl.font_manager.FontProperties(fname = font_path, size = 12)
|
|
318
|
+
UTCstr="202508280000"
|
|
319
|
+
shp_file = "./shp/province_9south.shp"
|
|
320
|
+
savepath = f"./FY4BBIG"
|
|
321
|
+
fig_title = f"卫星反演雷达回波_{UTCstr}"
|
|
322
|
+
# base[20:1070,75:1625] = satCR
|
|
323
|
+
plot_fig(data,result['lats'],result['lons'],fig_title,datatype="radar")
|
|
324
|
+
"""
|
|
325
|
+
|
|
@@ -3,47 +3,17 @@ import matplotlib.pyplot as plt
|
|
|
3
3
|
import datetime
|
|
4
4
|
from hjnwtx.colormap import cmp_hjnwtx
|
|
5
5
|
import os
|
|
6
|
-
import numpy as np
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import numpy as np
|
|
9
7
|
|
|
10
8
|
from pathlib import Path
|
|
11
9
|
def MDir(path):
|
|
12
10
|
path_obj = Path(path)
|
|
13
11
|
directory = path_obj.parent if path_obj.suffix else path_obj
|
|
14
12
|
directory.mkdir(parents=True, exist_ok=True)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def drawimg(array_dt,ty ="CR",temp = "temp"):
|
|
18
|
-
now_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
|
19
|
-
if len(array_dt.shape)==3:
|
|
20
|
-
for i , img_ch_nel in enumerate(array_dt):
|
|
21
|
-
plt.imshow(img_ch_nel,vmin=0,vmax=10,cmap=cmp_hjnwtx["radar_nmc"])
|
|
22
|
-
plt.colorbar()
|
|
23
|
-
outpath = f"./radar_nmc/{temp}_{now_str}.png"
|
|
24
|
-
MDir(outpath)
|
|
25
|
-
plt.savefig(outpath)
|
|
26
|
-
plt.close()
|
|
27
|
-
if len(array_dt.shape)==2 and ty =="pre":
|
|
28
|
-
plt.imshow(array_dt,vmin=0,vmax=10,cmap=cmp_hjnwtx["pre_tqw"])
|
|
29
|
-
plt.colorbar()
|
|
30
|
-
outpath = f"./radar_nmc/{temp}_{now_str}.png"
|
|
31
|
-
MDir(outpath)
|
|
32
|
-
plt.savefig(outpath)
|
|
33
|
-
plt.close()
|
|
34
|
-
else:
|
|
35
|
-
plt.imshow(array_dt,vmin=0,vmax=72,cmap=cmp_hjnwtx["radar_nmc"])
|
|
36
|
-
plt.colorbar()
|
|
37
|
-
outpath = f"./radar_nmc/{temp}_{now_str}.png"
|
|
38
|
-
MDir(outpath)
|
|
39
|
-
plt.savefig(outpath)
|
|
40
|
-
plt.close()
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def drawimg_coor(array_dt, temp="temp"):
|
|
13
|
+
|
|
14
|
+
def plotRadarcoor(array_dt, temp="temp"):
|
|
44
15
|
now_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
|
45
|
-
y_coords2, x_coords2 = np.where(array_dt > 0)
|
|
46
|
-
|
|
16
|
+
y_coords2, x_coords2 = np.where(array_dt > 0)
|
|
47
17
|
def plot_and_save(image, path):
|
|
48
18
|
plt.imshow(image, vmin=0, vmax=10, cmap=cmp_hjnwtx["radar_nmc"])
|
|
49
19
|
for (x, y) in zip(x_coords2, y_coords2):
|
|
@@ -4,7 +4,7 @@ import cartopy.feature as cfeature
|
|
|
4
4
|
import cartopy.io.shapereader as shpreader
|
|
5
5
|
import datetime
|
|
6
6
|
import os
|
|
7
|
-
|
|
7
|
+
from hjnwtx.colormap import cmp_hjnwtx
|
|
8
8
|
def add_china_map(ax):
|
|
9
9
|
ax.add_feature(cfeature.COASTLINE, edgecolor='gray')
|
|
10
10
|
ax.add_feature(cfeature.BORDERS, linestyle=':', edgecolor='gray')
|
shancx/Point.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy.interpolate import griddata
|
|
3
|
+
def getPoint(field,lats=None,lons=None,obs_lats=None,obs_lons=None):
|
|
4
|
+
lon_mesh, lat_mesh = np.meshgrid(lons, lats)
|
|
5
|
+
grid_points = np.column_stack([lon_mesh.ravel(), lat_mesh.ravel()])
|
|
6
|
+
interp_values = griddata(grid_points, field.ravel(), (obs_lons, obs_lats), method='linear')
|
|
7
|
+
valid_mask = ~np.isnan(interp_values)
|
|
8
|
+
return interp_values[valid_mask]
|
|
9
|
+
"""
|
|
10
|
+
nlat, nlon = background.shape
|
|
11
|
+
lons = np.linspace(-180, 180, nlon, endpoint=False)
|
|
12
|
+
lats = np.linspace(90, -90, nlat)
|
|
13
|
+
obs_lats = df["lat"]
|
|
14
|
+
obs_lons = df["lon"]
|
|
15
|
+
"""
|
|
16
|
+
from scipy.spatial import cKDTree
|
|
17
|
+
def mask_KDTree(grid_lon, grid_lat, lon_points, lat_points, step_lonlat=0.2):
|
|
18
|
+
grid_shape = grid_lon.shape
|
|
19
|
+
grid_coords = np.column_stack((grid_lon.ravel(), grid_lat.ravel()))
|
|
20
|
+
thunder_points = np.column_stack((lon_points, lat_points))
|
|
21
|
+
tree = cKDTree(thunder_points)
|
|
22
|
+
indices = tree.query_ball_point(grid_coords, r = step_lonlat)
|
|
23
|
+
mask_flat = np.zeros(len(grid_coords), dtype=int)
|
|
24
|
+
for i, neighbors in enumerate(indices):
|
|
25
|
+
if len(neighbors) >= 1:
|
|
26
|
+
mask_flat[i] = 1
|
|
27
|
+
mask_flat = mask_flat.reshape(grid_shape)
|
|
28
|
+
return mask_flat
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
lon_points = df_sta['lon']
|
|
32
|
+
lat_points = df_sta['lat']
|
|
33
|
+
grid_lon = th.lon.data
|
|
34
|
+
grid_lat = th.lat.data
|
|
35
|
+
grid_lon,grid_lat = np.meshgrid(grid_lon, grid_lat)
|
|
36
|
+
grid_marked = mask_KDTree(grid_lon, grid_lat, lon_points, lat_points, step_lonlat=0.5) step_lonlat 度数 0.01代表1公里
|
|
37
|
+
"""
|
|
38
|
+
def repetitionlatlon(df):
|
|
39
|
+
threshold = 0.001
|
|
40
|
+
df['lat_group'] = np.round(df['lat'] / threshold) * threshold
|
|
41
|
+
df['lon_group'] = np.round(df['lon'] / threshold) * threshold
|
|
42
|
+
duplicate_counts = df.groupby(['lat_group', 'lon_group']).size().reset_index(name='repetition')
|
|
43
|
+
return duplicate_counts
|
|
44
|
+
'''
|
|
45
|
+
输入数据框,通过近似查询,计算重复的经纬度点
|
|
46
|
+
'''
|
shancx/QC.py
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import cv2
|
|
2
|
+
import numpy as np
|
|
3
|
+
from numba import jit
|
|
4
|
+
def removeSmallPatches(binary_mask, min_pixels=50, min_area=40):
|
|
5
|
+
binary_mask = (binary_mask > 0).astype(np.uint8)
|
|
6
|
+
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(
|
|
7
|
+
binary_mask, connectivity=8
|
|
8
|
+
)
|
|
9
|
+
output_mask = np.zeros_like(binary_mask)
|
|
10
|
+
for i in range(1, num_labels):
|
|
11
|
+
pixel_count = stats[i, cv2.CC_STAT_AREA]
|
|
12
|
+
if pixel_count < min_pixels:
|
|
13
|
+
continue
|
|
14
|
+
component_mask = (labels == i).astype(np.uint8)
|
|
15
|
+
contours, _ = cv2.findContours(component_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
|
16
|
+
if contours:
|
|
17
|
+
contour = contours[0]
|
|
18
|
+
area = cv2.contourArea(contour)
|
|
19
|
+
if area < min_area:
|
|
20
|
+
continue
|
|
21
|
+
output_mask[labels == i] = 255
|
|
22
|
+
return output_mask
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
mask = removeSmallPatches(b, min_pixels=50, min_area=40)
|
|
26
|
+
data = np.where(mask, data, 0)
|
|
27
|
+
filtered_data = np.full([256,256],0)
|
|
28
|
+
filtered_data[mask] = e[mask]
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
import cv2
|
|
32
|
+
import numpy as np
|
|
33
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
34
|
+
def process_block_optimized(args):
|
|
35
|
+
block, coords, min_pixels, min_area = args
|
|
36
|
+
y, x, y_end, x_end = coords
|
|
37
|
+
num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(block, 8)
|
|
38
|
+
result = np.zeros_like(block)
|
|
39
|
+
valid_labels = []
|
|
40
|
+
for i in range(1, num_labels):
|
|
41
|
+
if stats[i, cv2.CC_STAT_AREA] >= min_pixels:
|
|
42
|
+
valid_labels.append(i)
|
|
43
|
+
for i in valid_labels:
|
|
44
|
+
component_mask = (labels == i).astype(np.uint8)
|
|
45
|
+
contours, _ = cv2.findContours(component_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
|
46
|
+
if contours and cv2.contourArea(contours[0]) >= min_area:
|
|
47
|
+
result[labels == i] = 255
|
|
48
|
+
return result, coords
|
|
49
|
+
def removeSmallPatches_fast(binary_mask, min_pixels=100, min_area=40, num_workers=3):
|
|
50
|
+
binary_mask = (binary_mask > 0).astype(np.uint8)
|
|
51
|
+
h, w = binary_mask.shape
|
|
52
|
+
output = np.zeros_like(binary_mask)
|
|
53
|
+
block_size = 2000
|
|
54
|
+
blocks = []
|
|
55
|
+
for y in range(0, h, block_size):
|
|
56
|
+
for x in range(0, w, block_size):
|
|
57
|
+
y_end, x_end = min(y+block_size, h), min(x+block_size, w)
|
|
58
|
+
block = binary_mask[y:y_end, x:x_end]
|
|
59
|
+
blocks.append((block, (y, x, y_end, x_end), min_pixels, min_area))
|
|
60
|
+
with ThreadPoolExecutor(num_workers) as executor:
|
|
61
|
+
for result, (y, x, y_end, x_end) in executor.map(process_block_optimized, blocks):
|
|
62
|
+
output[y:y_end, x:x_end] = result
|
|
63
|
+
return output
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
mask = removeSmallPatches(b, min_pixels=50, min_area=40)
|
|
67
|
+
data = np.where(mask, data, 0)
|
|
68
|
+
filtered_data = np.full([256,256],0)
|
|
69
|
+
filtered_data[mask] = e[mask]
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
import cv2
|
|
73
|
+
import numpy as np
|
|
74
|
+
from numba import jit, prange
|
|
75
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
76
|
+
def removeSmallPatches_optimized(binary_mask, min_pixels=50, min_area=40):
|
|
77
|
+
binary_mask = (binary_mask > 0).astype(np.uint8)
|
|
78
|
+
num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(binary_mask, connectivity=8)
|
|
79
|
+
output_mask = np.zeros_like(binary_mask)
|
|
80
|
+
valid_labels = [i for i in range(1, num_labels) if stats[i, cv2.CC_STAT_AREA] >= min_pixels]
|
|
81
|
+
for i in valid_labels:
|
|
82
|
+
contour_mask = (labels == i).astype(np.uint8)
|
|
83
|
+
contours, _ = cv2.findContours(contour_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
|
84
|
+
|
|
85
|
+
if contours and cv2.contourArea(contours[0]) >= min_area:
|
|
86
|
+
output_mask[labels == i] = 255
|
|
87
|
+
|
|
88
|
+
return output_mask
|
|
89
|
+
|
|
90
|
+
@jit(nopython=True, parallel=True, nogil=True)
|
|
91
|
+
def numba_filter_components(labels, stats, min_pixels, min_area):
|
|
92
|
+
height, width = labels.shape
|
|
93
|
+
output = np.zeros((height, width), dtype=np.uint8)
|
|
94
|
+
for i in prange(1, stats.shape[0]):
|
|
95
|
+
if stats[i, 4] >= min_pixels: # stats[i, 4] 对应 cv2.CC_STAT_AREA
|
|
96
|
+
for y in range(height):
|
|
97
|
+
for x in range(width):
|
|
98
|
+
if labels[y, x] == i:
|
|
99
|
+
output[y, x] = 255
|
|
100
|
+
return output
|
|
101
|
+
def removeSmallPatches_numba(binary_mask, min_pixels=50, min_area=40):
|
|
102
|
+
binary_mask = (binary_mask > 0).astype(np.uint8)
|
|
103
|
+
num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(binary_mask, connectivity=8)
|
|
104
|
+
output_mask = numba_filter_components(labels, stats, min_pixels, min_area)
|
|
105
|
+
if min_area > 0:
|
|
106
|
+
num_labels2, labels2, stats2, _ = cv2.connectedComponentsWithStats(output_mask, connectivity=8)
|
|
107
|
+
final_output = np.zeros_like(output_mask)
|
|
108
|
+
for i in range(1, num_labels2):
|
|
109
|
+
contour_mask = (labels2 == i).astype(np.uint8)
|
|
110
|
+
contours, _ = cv2.findContours(contour_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
|
111
|
+
if contours and cv2.contourArea(contours[0]) >= min_area:
|
|
112
|
+
final_output[labels2 == i] = 255
|
|
113
|
+
return final_output
|
|
114
|
+
return output_mask
|
|
115
|
+
def process_block_optimized_v2(args):
|
|
116
|
+
block, coords, min_pixels, min_area = args
|
|
117
|
+
num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(block, connectivity=8)
|
|
118
|
+
result = np.zeros_like(block)
|
|
119
|
+
valid_labels = []
|
|
120
|
+
for i in range(1, num_labels):
|
|
121
|
+
if stats[i, cv2.CC_STAT_AREA] >= min_pixels:
|
|
122
|
+
valid_labels.append(i)
|
|
123
|
+
for i in valid_labels:
|
|
124
|
+
component_indices = (labels == i)
|
|
125
|
+
if component_indices.any():
|
|
126
|
+
component_mask = component_indices.astype(np.uint8)
|
|
127
|
+
contours, _ = cv2.findContours(component_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
|
128
|
+
if contours and cv2.contourArea(contours[0]) >= min_area:
|
|
129
|
+
result[component_indices] = 255
|
|
130
|
+
return result, coords
|
|
131
|
+
def removeSmallPatches_fast_v2(binary_mask, min_pixels=100, min_area=40, num_workers=4):
|
|
132
|
+
binary_mask = (binary_mask > 0).astype(np.uint8)
|
|
133
|
+
h, w = binary_mask.shape
|
|
134
|
+
optimal_block_size = max(500, min(2000, (h * w) // (num_workers * 10000)))
|
|
135
|
+
output = np.zeros_like(binary_mask)
|
|
136
|
+
blocks = []
|
|
137
|
+
for y in range(0, h, optimal_block_size):
|
|
138
|
+
for x in range(0, w, optimal_block_size):
|
|
139
|
+
y_end, x_end = min(y + optimal_block_size, h), min(x + optimal_block_size, w)
|
|
140
|
+
block = binary_mask[y:y_end, x:x_end].copy()
|
|
141
|
+
blocks.append((block, (y, x, y_end, x_end), min_pixels, min_area))
|
|
142
|
+
actual_workers = min(num_workers, len(blocks))
|
|
143
|
+
with ThreadPoolExecutor(max_workers=actual_workers) as executor:
|
|
144
|
+
for result, (y, x, y_end, x_end) in executor.map(process_block_optimized_v2, blocks):
|
|
145
|
+
output[y:y_end, x:x_end] = result
|
|
146
|
+
return output
|
|
147
|
+
def get_optimal_function(binary_mask, min_pixels=50, min_area=40):
|
|
148
|
+
h, w = binary_mask.shape
|
|
149
|
+
total_pixels = h * w
|
|
150
|
+
if total_pixels < 1000000: # 小于100万像素
|
|
151
|
+
return removeSmallPatches_optimized
|
|
152
|
+
if min_area <= 0:
|
|
153
|
+
return removeSmallPatches_numba
|
|
154
|
+
return removeSmallPatches_fast_v2
|
|
155
|
+
def auto_remove_small_patches(binary_mask, min_pixels=50, min_area=40):
|
|
156
|
+
optimal_func = get_optimal_function(binary_mask, min_pixels, min_area)
|
|
157
|
+
return optimal_func(binary_mask, min_pixels, min_area)
|
|
158
|
+
"""
|
|
159
|
+
try:
|
|
160
|
+
result = auto_remove_small_patches(binary_mask, min_pixels=50, min_area=40)
|
|
161
|
+
except Exception as e:
|
|
162
|
+
from original_module import removeSmallPatches
|
|
163
|
+
result = removeSmallPatches(binary_mask, min_pixels=50, min_area=40)
|
|
164
|
+
removeSmallPatches_numba optimum performance min_area <= 0
|
|
165
|
+
removeSmallPatches_fast_v2 area
|
|
166
|
+
"""
|
|
167
|
+
@jit(nopython=True, parallel=True, nogil=True)
|
|
168
|
+
def QC_simple_numba(mat, dbzTH = 10.0, areaTH=20):
|
|
169
|
+
# Create a copy of the matrix
|
|
170
|
+
mat1 = np.copy(mat)
|
|
171
|
+
rows, cols = mat1.shape
|
|
172
|
+
|
|
173
|
+
# Create binary mask based on threshold
|
|
174
|
+
mask = np.zeros((rows, cols), dtype=np.uint8)
|
|
175
|
+
for i in range(rows):
|
|
176
|
+
for j in range(cols):
|
|
177
|
+
if mat1[i, j] > dbzTH:
|
|
178
|
+
mask[i, j] = 1
|
|
179
|
+
# Simple 8-connectivity region labeling (flood fill algorithm)
|
|
180
|
+
labels = np.zeros((rows, cols), dtype=np.int32)
|
|
181
|
+
current_label = 1
|
|
182
|
+
region_areas = []
|
|
183
|
+
for i in range(rows):
|
|
184
|
+
for j in range(cols):
|
|
185
|
+
# If current pixel is foreground and not yet labeled
|
|
186
|
+
if mask[i, j] == 1 and labels[i, j] == 0:
|
|
187
|
+
# Start flood fill
|
|
188
|
+
stack = [(i, j)]
|
|
189
|
+
labels[i, j] = current_label
|
|
190
|
+
area = 0
|
|
191
|
+
|
|
192
|
+
while stack:
|
|
193
|
+
x, y = stack.pop()
|
|
194
|
+
area += 1
|
|
195
|
+
|
|
196
|
+
# Check 8 surrounding pixels
|
|
197
|
+
for dx in [-1, 0, 1]:
|
|
198
|
+
for dy in [-1, 0, 1]:
|
|
199
|
+
nx, ny = x + dx, y + dy
|
|
200
|
+
# Check bounds and conditions
|
|
201
|
+
if (0 <= nx < rows and 0 <= ny < cols and
|
|
202
|
+
mask[nx, ny] == 1 and labels[nx, ny] == 0):
|
|
203
|
+
labels[nx, ny] = current_label
|
|
204
|
+
stack.append((nx, ny))
|
|
205
|
+
|
|
206
|
+
region_areas.append(area)
|
|
207
|
+
current_label += 1
|
|
208
|
+
|
|
209
|
+
# Apply area threshold filtering
|
|
210
|
+
for i in range(rows):
|
|
211
|
+
for j in range(cols):
|
|
212
|
+
if labels[i, j] > 0 and region_areas[labels[i, j] - 1] < areaTH:
|
|
213
|
+
mat1[i, j] = 0
|
|
214
|
+
return mat1
|
|
215
|
+
def QC_ref_numba(mat, dbzTH = 10, areaTH=20):
|
|
216
|
+
for i in range(len(mat)):
|
|
217
|
+
mat[i] = QC_simple_numba(mat[i], dbzTH, areaTH)
|
|
218
|
+
return mat
|
|
219
|
+
"""
|
|
220
|
+
CR = subset["CR"].data[0].copy()
|
|
221
|
+
CR[CR < 6] = 0
|
|
222
|
+
CR = QC_ref_numba(CR[None], areaTH=15)[0]
|
|
223
|
+
"""
|