def pic2data(pathname,region,factor = 'CR'): try: '''各区域对应图例坐标、左上角、右下角经纬度''' '''图片分辨率改变时修改这里的图例位置''' region_all={'AECN':(523,537,597,793,113.506,38.8444,124.2670,23.1044), #华东 'ACCN':(722,333,798,589,103.626,35.3322,120.005,24.0566), #华中 'ACHN':(948,613,1021,869,65.6571,46.4849,126.862,13.061),#全国 'ANCN':(725,5 ,799,261,104.643,43.0878,122.636,31.1917), #华北 'ANEC':(723,564,797,820,114.539,54.224,131.91,36.3301), #东北 'ABCJ':(884,98 ,955,348,96.4697,34.7539,126.494,25.0003), #长江流域 'ABHH':(692,250,757,499,107.015,40.9176,123.65,30.4626), #黄淮流域 'ACES':(721,537,789,789,103.491,35.7671,128.508,13.2104), #东南沿海 'ASCN':(725,338,791,589,104.654,27.6771,121.318,16.104), #华南 'ANWC':(749,6 ,1017,255,65.4922,43.212,109.31,29.4932),#西北 'ASWC':(727,10 ,791,218,96.1597,34.8143,112.812,20.7235) #西南 } #'R','CR'的颜色 if factor in ['R','CR']: '''R & CR''' colors={(1, 160, 246, 255):12.5, (0, 216, 0, 255):22.5, (255, 0, 240, 255):62.5, (231, 192, 0, 255):37.5, (214, 0, 0, 255):52.5, (192, 0, 0, 255):57.5, (173, 144, 240, 255):72.5, (150, 0, 180, 255):67.5, (0, 236, 236, 255):17.5, (255, 144, 0, 255):42.5, (255, 0, 0, 255):47.5, (1, 144, 0, 255):27.5, (255, 255, 0, 255):32.5} #'''VIL的颜色''' elif factor == 'VIL': colors={(1, 255, 0, 255):12.5, (0, 200, 0, 255):17.5, (255, 0, 240, 255):57.5, (231, 192, 0, 255):32.5, (214, 0, 0, 255):47.5, (192, 0, 0, 255):52.5, (173, 144, 240, 255):72.5, (0, 236, 236, 255):8.5, (120, 0, 132, 255):67.5, (255, 144, 0, 255):37.5, (255, 0, 0, 255):42.5, (216, 0, 156, 255):62.5, (255, 255, 0, 255):27.5, (1, 144, 0, 255):22.5} #'''OHP的颜色''' elif factor == 'OHP': colors={(255, 0, 240, 255):112.5, #100-125 (214, 0, 0, 255):69, #63-75 (192, 0, 0, 255):87.5,#75-100 (173, 144, 240, 255):130, #130- (0, 236, 236, 255):17.5, #10-25 (255, 144, 0, 255):44, #38-50 (255, 0, 0, 255):56.5, #50-63 (0, 0, 246, 255):2.5, #0-5 (255, 255, 0, 255):31.5, #25-38 (1, 160, 246, 255):7.5} #5-10 '''河流、行政边界、文字的颜色''' word_color=[(104, 104, 104, 255), #(253, 255, 254, 255), (204, 204, 204, 255), (190, 232, 255, 255), (156, 156, 156, 255), (130, 130, 130, 255)] '''打开文件''' img_src = Image.open(pathname) img_size=img_src.size region_del=region_all[region] #定义和图片大小一致的0矩阵 image_value=np.zeros((img_size[0],img_size[1])) src_strlist = img_src.load() '''获取格点数据,没有数据为0,河流、行政区域、文字数据为1''' for i in range(0,img_size[0],1): for j in range(0,img_size[1],1): if src_strlist[i,j] in colors: #是否有数据 image_value[i,j]=colors[src_strlist[i,j]] elif src_strlist[i,j] in word_color: #是否是河流等 image_value[i,j]=1 else: #是不需要的点 image_value[i,j]=0 '''找到图例并填充为0''' image_value[region_del[0]:region_del[2],region_del[1]:region_del[3]]=0 '''对河流、文字、行政边界的点进行插值''' image_out=np.copy(image_value) for i in range(0,img_size[0],1): for j in range(0,img_size[1],1): #判断是否为河流等点 if image_value[i,j]==1: sum_value=0 #周围所有有效点的值的和 count_1=0 #附近河流等点的个数 count_0=0 #附近无效点的个数 count_c=0 #附近数据点的个数 #取该点周围8各点进行判断 for n in [(i-1,j-1),(i-1,j ),(i-1,j+1), (i ,j-1), (i ,j+1), (i+1,j-1),(i+1,j ),(i+1,j+1)]: if image_value[n] > 1: count_c += 1 sum_value += image_value[n] elif image_value[n] == 1: count_1 += 1 else: count_0 += 1 #周围没有数据点,且有无效点 if count_c == 0 and count_0 > 0: image_out[i,j]=0 #有数据点 elif count_c >0: try: #数据点占多数 if count_c / count_0 > 0.5: image_out[i,j]=sum_value/count_c #数据点占少数 elif count_c / count_0 <= 0.5: image_out[i,j]=0 #无效点个数可能为0 except ZeroDivisionError: image_out[i,j]=sum_value/count_c #数据点和无效点都没有 elif count_1 == 8: #判断再往外的一层 for n in [(i-2,j-2),(i-2,j-1),(i-2,j ),(i-2,j+1),(i-2,j+2), (i-1,j-2) ,(i-1,j+2), (i ,j-2) ,(i ,j+2), (i+1,j-2) ,(i+1,j+2), (i+2,j-2),(i+2,j-1),(i+2,j ),(i+2,j+1),(i+2,j+2)]: if image_value[n] > 1: count_c += 1 sum_value += image_value[n] elif image_value[n] == 1: count_1 += 1 else: count_0 += 1 #没有数据点 if count_c == 0: image_out[i,j]=0 #有数据点 elif count_c >0: try: #数据点占多数 if count_c / count_0 > 0.5: image_out[i,j]=sum_value/count_c #数据点占少数 elif count_c / count_0 <= 0.5: image_out[i,j]=0 #无效点个数可能为0 except ZeroDivisionError: image_out[i,j]=sum_value/count_c '''坐标处理''' #转置 image_out=np.transpose(image_out) #颠倒y image_out=image_out[::-1] #得到经纬度转换后的原始网格对应的经纬度信息 lon,lat=get_latlon(region) #生成离散点数据 out_index=np.argwhere(image_out > 0) out_all=np.zeros((len(out_index),3)) out_all[:,0]=lat[out_index[:,0],out_index[:,1]] out_all[:,1]=lon[out_index[:,0],out_index[:,1]] out_all[:,2]=image_out[out_index[:,0],out_index[:,1]] #返回坐标转换后的经纬度对应的数据 return out_all #如果有问题则返回空list except: return []
from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt region_all=['AECN', #华东 'ACCN', #华中 # 'ACHN',#全国 'ANCN', #华北 'ANEC', #东北 'ABCJ', #长江流域 'ABHH', #黄淮流域 'ACES', #东南沿海 'ASCN', #华南 'ANWC',#西北 'ASWC' #西南 ] lon,lat=get_latlon('ACHN') #获取图像中的经纬度极值范围 #lon_min=np.min(lon) #lon_max=np.max(lon) #lat_min=np.min(lat) #lat_max=np.max(lat) dlon=0.04 dlat=0.04 lon_min = 108 lon_max = 132 lat_min = 20 lat_max = 40 #lon_min=latlon_domain[1] #lon_max=latlon_domain[3] #lat_min=latlon_domain[0] #lat_max=latlon_domain[2]
def write_latlon(picfile,datafile): #从文件路径中提取关键字 name=picfile.split('/')[-1] factor=name.split('_')[-2] region=name.split('_')[-1][0:4] datatime=name.split('_')[4] #生成输出文件名 outname='MOP_'+region+'_'+'factor'+'_'+datatime+'.latlon' #获取全国地图的经纬度网格 lon,lat=get_latlon('ACHN') #获取图像中的经纬度极值范围,生成0.04间隔的等经纬度网格 lon_min1=int(np.min(lon)*100)//4/25 lon_max1=int(np.max(lon)*100)//4/25 +0.04 lat_min1=int(np.min(lat)*100)//4/25 lat_max1=int(np.max(lat)*100)//4/25 +0.04 #生成0.04格距的网格 grid_x, grid_y = np.mgrid[lon_min1:lon_max1+0.04:0.04, lat_min1:lat_max1+0.04:0.04] #生成网格对应的空数据 grid_z1=np.zeros([np.shape(grid_x)[0],np.shape(grid_x)[1]]) #获得图像中对应的网格点的数值 out_all=pic2data(picfile) #如果返回空集合,则返回1退出 if out_all==[]: return 1 #放大系数 fdxs=10 #乘以放大系数 out_all[:,2]=out_all[:,2]*fdxs try: # In[] 打开文件读取latlon文件 with open (datafile,'rb+') as f: #从256个字节开始往后读数据 f.seek(256) #获得文件中头文件以外的数据大小 datasize=os.path.getsize(datafile)-256 #读取数据 context1=f.read(datasize) #获取有数值的点的信息 yxn=struct.unpack('h'*int(datasize/2),context1) #初始判断符为0 panduan=0 #读取原始latlon文件中数据,挨个读取yxn的数值并写入grid_z1中 for i in yxn: #panduan为0则该值为y if panduan==0: y=i panduan+=1 continue #panduan为0则该值为x elif panduan==1: x=i panduan+=1 continue #panduan为0则该值为n elif panduan==2: n0=0 n=i panduan+=1 continue #panduan为0则该值为数值 elif panduan==3: grid_z1[x+n0,y]=i n0+=1 if n0==n: panduan=0 continue #将新的区域的数据写入latlon中 for i in out_all: grid_z1[int(round((i[1]-lon_min1)/0.04)), int(round((i[0]-lat_min1)/0.04))]=i[2] image_out=grid_z1 #生成latlon文件数据 out=[] for y in range(0,np.shape(grid_z1)[1],1): #y ifFirst=True for x in range(0,np.shape(grid_z1)[0],1): if image_out[x,y] > 0: if ifFirst: if x!=np.shape(grid_z1)[0]-1: ifFirst=False out_tmp=[] count=1 out_tmp.extend([image_out[x,y]]) else: out.extend([y,x,1]) out.extend([image_out[x,y]]) else: if x!=np.shape(grid_z1)[0]-1: out_tmp.extend([image_out[x,y]]) count+=1 else: out_tmp.extend([image_out[x,y]]) count+=1 out.extend([y,x-count+1,count]) out.extend(out_tmp) elif image_out[x,y]==0 and not ifFirst: out.extend([y,x-count,count]) out.extend(out_tmp) ifFirst=True #加入结束判断符 out.extend([-1,-1,-1]) #将out转成二进制 for i in out: try: data_b+=struct.pack('h',int(i)) except NameError: data_b=struct.pack('h',int(i)) #删除256以后的值 f.truncate(256) #从256开始写入新的数据 f.seek(256) f.write(data_b) return 0 #不存在原始文件 except FileNotFoundError: # In[]将新的区域的数据写入latlon中 for i in out_all: grid_z1[int(round((i[1]-lon_min1)/0.04)), int(round((i[0]-lat_min1)/0.04))]=i[2] image_out=grid_z1 #生成文件 out=[] for y in range(0,np.shape(grid_z1)[1],1): #y ifFirst=True for x in range(0,np.shape(grid_z1)[0],1): if image_out[x,y] > 0: if ifFirst: if x!=np.shape(grid_z1)[0]-1: ifFirst=False out_tmp=[] count=1 out_tmp.extend([image_out[x,y]]) else: out.extend([y,x,1]) out.extend([image_out[x,y]]) else: if x!=np.shape(grid_z1)[0]-1: out_tmp.extend([image_out[x,y]]) count+=1 else: out_tmp.extend([image_out[x,y]]) count+=1 out.extend([y,x-count+1,count]) out.extend(out_tmp) elif image_out[x,y]==0 and not ifFirst: out.extend([y,x-count,count]) out.extend(out_tmp) ifFirst=True #加入结束判断符 out.extend([-1,-1,-1]) #将out转成二进制 for i in out: try: data_b+=struct.pack('h',int(i)) except NameError: data_b=struct.pack('h',int(i)) # In[]'''生成文件头''' dataname= outname.encode('utf-8')+b'\x00'*(128-len(outname)) varname =factor.encode('utf-8')+ b'\x00'*(32-len(factor)) char ='dBZ'.encode('utf-8')+ b'\x00'*(16-len('dBZ')) label = 0 #unsigned short unitlen = 2 #short slat=lat_min1 #float wlon=lon_min1#float nlat=lat_max1#float elon=lon_max1#float clat=(slat+nlat)/2#float clon=(wlon+elon)/2#float rows=np.shape(grid_z1)[1] # int cols=np.shape(grid_z1)[0] # int dlat=0.04 #float dlon=0.04 #float nodata=0.0 #float levelbytes =0 #long levelnum=0 #short amp= fdxs #short compmode =1 #short dates = 0 #unsigned short seconds= 0 #int min_value = 0 #short max_value = 0 #short #reserved = # head =dataname + varname + char +struct.pack('Hh6f2i3fq3hHi2h6h', label,unitlen,slat,wlon,nlat, # elon,clat,clon,rows,cols,0.04,0.04,nodata, # levelbytes,levelnum,amp,compmode, # dates,seconds,min_value,max_value, # 0,0,0,0,0,0); head =dataname + varname + char +struct.pack('Hh6f2i3fi3hHi2h6h', label,unitlen,slat,wlon,nlat, elon,clat,clon,rows,cols,dlat,dlon,nodata, levelbytes,levelnum,amp,compmode, dates,seconds,min_value,max_value, 0,0,0,0,0,0); # In[] '''存储''' all_out=head+data_b #将二进制数据写入文件 with open(datafile, 'wb') as f: f.write(all_out) return 0
def write_latlon(picfile, datafile): name = picfile.split('/')[-1] factor = name.split('_')[-2] region = name.split('_')[-1][0:4] datatime = name.split('_')[4] outname = 'MOP_' + region + '_' + 'factor' + '_' + datatime + '.latlon' lon, lat = get_latlon('ACHN') #获取图像中的经纬度极值范围,生成0.04间隔的等经纬度网格 lon_min1 = int(np.min(lon) * 100) // 4 / 25 lon_max1 = int(np.max(lon) * 100) // 4 / 25 + 0.04 lat_min1 = int(np.min(lat) * 100) // 4 / 25 lat_max1 = int(np.max(lat) * 100) // 4 / 25 + 0.04 #生成0.04格距的网格 grid_x, grid_y = np.mgrid[lon_min1:lon_max1 + 0.04:0.04, lat_min1:lat_max1 + 0.04:0.04] #处理 grid_z1 = np.zeros([np.shape(grid_x)[0], np.shape(grid_x)[1]]) out_all = pic2data(picfile) if out_all == []: return 1 try: with open(datafile, 'rb+') as f: f.seek(260) datasize = os.path.getsize(datafile) - 260 context1 = f.read(datasize) yxn = struct.unpack('h' * int(datasize / 2), context1) panduan = 0 for i in yxn: if panduan == 0: y = i panduan += 1 continue elif panduan == 1: x = i panduan += 1 continue elif panduan == 2: n0 = 0 n = i panduan += 1 continue elif panduan == 3: grid_z1[x + n0, y] = i n0 += 1 if n0 == n: panduan = 0 continue for i in out_all: grid_z1[int(round((i[1] - lon_min1) / 0.04)), int(round((i[0] - lat_min1) / 0.04))] = i[2] image_out = grid_z1 #生成文件 out = [] for y in range(0, np.shape(grid_z1)[1], 1): #y ifFirst = True for x in range(0, np.shape(grid_z1)[0], 1): if image_out[x, y] > 0: if ifFirst: if x != np.shape(grid_z1)[0] - 1: ifFirst = False out_tmp = [] count = 1 out_tmp.extend([image_out[x, y]]) else: out.extend([y, x, 1]) out.extend([image_out[x, y]]) else: if x != np.shape(grid_z1)[0] - 1: out_tmp.extend([image_out[x, y]]) count += 1 else: out_tmp.extend([image_out[x, y]]) count += 1 out.extend([y, x - count + 1, count]) out.extend(out_tmp) elif image_out[x, y] == 0 and not ifFirst: out.extend([y, x - count, count]) out.extend(out_tmp) ifFirst = True out.extend([-1, -1, -1]) for i in out: try: data_b += struct.pack('h', int(i)) except NameError: data_b = struct.pack('h', int(i)) f.truncate(260) f.seek(260) f.write(data_b) return 0 except FileNotFoundError: for i in out_all: grid_z1[int(round((i[1] - lon_min1) / 0.04)), int(round((i[0] - lat_min1) / 0.04))] = i[2] image_out = grid_z1 #生成文件 out = [] for y in range(0, np.shape(grid_z1)[1], 1): #y ifFirst = True for x in range(0, np.shape(grid_z1)[0], 1): if image_out[x, y] > 0: if ifFirst: if x != np.shape(grid_z1)[0] - 1: ifFirst = False out_tmp = [] count = 1 out_tmp.extend([image_out[x, y]]) else: out.extend([y, x, 1]) out.extend([image_out[x, y]]) else: if x != np.shape(grid_z1)[0] - 1: out_tmp.extend([image_out[x, y]]) count += 1 else: out_tmp.extend([image_out[x, y]]) count += 1 out.extend([y, x - count + 1, count]) out.extend(out_tmp) elif image_out[x, y] == 0 and not ifFirst: out.extend([y, x - count, count]) out.extend(out_tmp) ifFirst = True out.extend([-1, -1, -1]) for i in out: try: data_b += struct.pack('h', int(i)) except NameError: data_b = struct.pack('h', int(i)) # In[] '''生成文件头''' dataname = outname.encode('utf-8') + b'\x00' * (128 - len(outname)) varname = factor.encode('utf-8') + b'\x00' * (32 - len(factor)) char = 'dBZ'.encode('utf-8') + b'\x00' * (16 - len('dBZ')) label = 0 #unsigned short unitlen = 2 #short slat = lat_min1 #float wlon = lon_min1 #float nlat = lat_max1 #float elon = lon_max1 #float clat = (slat + nlat) / 2 #float clon = (wlon + elon) / 2 #float rows = np.shape(grid_z1)[1] # int cols = np.shape(grid_z1)[0] # int #dlat float #dlon float nodata = 0.0 #float levelbytes = 0 #long levelnum = 0 #short amp = 0 #short compmode = 1 #short dates = 0 #unsigned short seconds = 0 #int min_value = 0 #short max_value = 0 #short #reserved = # head =dataname + varname + char +struct.pack('Hh6f2i3fq3hHi2h6h', label,unitlen,slat,wlon,nlat, # elon,clat,clon,rows,cols,0.04,0.04,nodata, # levelbytes,levelnum,amp,compmode, # dates,seconds,min_value,max_value, # 0,0,0,0,0,0); head = dataname + varname + char + struct.pack( 'Hh6f2i3fq3hHi2h6h', label, unitlen, slat * 1000, wlon * 1000, nlat * 1000, elon * 1000, clat * 1000, clon * 1000, rows, cols, 0.04 * 1000, 0.04 * 1000, nodata, levelbytes, levelnum, amp, compmode, dates, seconds, min_value, max_value, 0, 0, 0, 0, 0, 0) # In[] '''存储''' all_out = head + data_b with open(datafile, 'wb') as f: f.write(all_out) return 0