Hammer坐标系转换到WGS1984

Hammer坐标系转换到WGS1984,以处理FY3D/MERSI NVI数据为例。FY3D/MERSI NVI空间分辨率250m,全球 10°×10°分幅。

01读取数据

import gdal
import h5py

infile = r"D:\微信公众号\FY3D_MERSI_5090_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS.HDF"
outfile = r"D:\微信公众号\FY3D_MERSI_5090_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS.tif"

hdf_ds = h5py.File(infile, "r")
left_x = hdf_ds.attrs['Left-Top X'][0]
left_y = hdf_ds.attrs["Left-Top Y"][0]
res_x = hdf_ds.attrs['Resolution X'][0]
res_y = hdf_ds.attrs['Resolution Y'][0]
ndviname = list(hdf_ds.keys())[6]
ndvi_ds = hdf_ds[ndviname]
rows = ndvi_ds.shape[0]
cols = ndvi_ds.shape[1]
data = ndvi_ds[()]
driver = gdal.GetDriverByName("GTiff")
outds = driver.Create(outfile, cols, rows, 1, gdal.GDT_Int16)
outds.SetGeoTransform( (float(left_x) * 1000 / 4.0, float(res_x) * 1000, 0, float(left_y) * 1000 / 4.0, 0, -1 * float(res_y) * 1000))
proj = 'PROJCS["World_Hammer",GEOGCS["Unknown datum based upon the custom spheroid",DATUM["Not_specified_based_on_custom_spheroid",SPHEROID["Custom spheroid",6363961,0]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199433]],PROJECTION["Hammer_Aitoff"],PARAMETER["False_Easting",0],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",0],UNIT["metre",1],AXIS["Easting",EAST],AXIS["Northing",NORTH]]'
outds.SetProjection(proj)
outband = outds.GetRasterBand(1)
outband.WriteArray(data)


编辑

FY3D_MERSI_4090_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS以Hammer投影坐标系写出。

编辑

FY3D_MERSI_5090_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS以Hammer投影坐标系写出。

02数据拼接

import gdal

filelist = [r"D:\微信公众号\FY3D_MERSI_4090_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS.tif",
            r"D:\微信公众号\FY3D_MERSI_5090_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS.tif"]
outfile = r"D:\微信公众号\FY3D_MERSI_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS.tif"
ds = gdal.Open(filelist[0])
cols = ds.RasterXSize
rows = ds.RasterYSize
ingeo = ds.GetGeoTransform()
proj = ds.GetProjection()
minx = ingeo[0]
maxy = ingeo[3]
maxx = ingeo[0] + ingeo[1] * cols
miny = ingeo[3] + ingeo[5] * rows
ds = None
for file in filelist[1:]:
    ds = gdal.Open(file)
    cols = ds.RasterXSize
    rows = ds.RasterYSize
    geo = ds.GetGeoTransform()
    minx_ = geo[0]
    maxy_ = geo[3]
    maxx_ = geo[0] + geo[1] * cols
    miny_ = geo[3] + geo[5] * rows
    minx = min(minx, minx_)
    maxy = max(maxy, maxy_)
    maxx = max(maxx, maxx_)
    miny = min(miny, miny_)
    geo = None
    ds = None
newcols = int((maxx - minx) / abs(ingeo[1]))
newrows = int((maxy - miny) / abs(ingeo[5]))
driver = gdal.GetDriverByName("GTiff")
outds = driver.Create(outfile, newcols, newrows, 1, gdal.GDT_Int16)
outgeo = (minx, ingeo[1], 0, maxy, 0, ingeo[5])
outds.SetGeoTransform(outgeo)
outds.SetProjection(proj)
outband = outds.GetRasterBand(1)
for file in filelist:
    ds = gdal.Open(file)
    data = ds.ReadAsArray()
    geo = ds.GetGeoTransform()
    x = int(abs((geo[0] - minx) / ingeo[1]))
    y = int(abs((geo[3] - maxy) / ingeo[5]))
    outband.WriteArray(data, x, y)
    ds = None
outband.FlushCache()

编辑

上边两幅影像的拼接结果(坐标系仍然为Hammer投影)。

03坐标系转换

import gdal
import numpy as np
import math
import osr

infile = r"D:\微信公众号\FY3D_MERSI_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS.tif"
outfile = r"D:\微信公众号\FY3D_MERSI_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS_WGS1984.tif"

ds = gdal.Open(infile)
ingeo = ds.GetGeoTransform()
cols = ds.RasterXSize
rows = ds.RasterYSize
or_x = ingeo[0]
or_y = ingeo[3]
end_x = ingeo[0] + cols * ingeo[1]
end_y = ingeo[3] + rows * ingeo[5]
# X方向分块
xblocksize = int((cols + 1) / 5)
# Y方向分块
yblocksize = int((rows + 1) / 5)
lon_max = -360
lon_min = 360
lat_max = -90
lat_min = 90
for i in range(0, rows + 1, yblocksize):
    if i + yblocksize < rows + 1:
        numrows = yblocksize
    else:
        numrows = rows + 1 - i
    for j in range(0, cols + 1, xblocksize):
        if j + xblocksize < cols + 1:
            numcols = xblocksize
        else:
            numcols = cols + 1 - j
        # 计算所有点的Hammer坐标系下X方向坐标数组
        x = ingeo[0] + j * ingeo[1]
        y = ingeo[3] + i * ingeo[5]
        xgrid, ygrid = np.meshgrid(np.linspace(x, x + numcols * ingeo[1], num=numcols),
                                   np.linspace(y, y + numrows * ingeo[5], num=numrows))
        # 将hammer坐标转化为经纬度坐标
        # 首先将Hammer转化为-1到1
        xgrid = np.where(xgrid > (18000.0 * 1000.0), (18000.0 * 1000.0) - xgrid, xgrid)
        xgrid = xgrid / (18000.0 * 1000.0)
        ygrid = np.where(ygrid > (9000.0 * 1000.0), (9000.0 * 1000.0) - ygrid, ygrid)
        ygrid = ygrid / (9000.0 * 1000.0)
        z = np.sqrt(1 - np.square(xgrid) / 2.0 - np.square(ygrid) / 2.0)
        lon = 2 * np.arctan(np.sqrt(2) * xgrid * z / (2.0 * (np.square(z)) - 1))
        xgrid = None
        lat = np.arcsin(np.sqrt(2) * ygrid * z)
        ygrid = None
        z = None
        lon = lon / math.pi * 180.0
        lat = lat / math.pi * 180.0
        lon[lon < 0] = lon[lon < 0] + 360.0
        # lat[lat<0]=lat[lat<0]+180
        lon_max = max(lon_max, np.max(lon))
        lon_min = min(lon_min, np.min(lon))
        lon = None
        lat_max = max(lat_max, np.max(lat))
        lat_min = min(lat_min, np.min(lat))
        lat = None

newcols = math.ceil((lon_max - lon_min) / 0.0025)
newrows = math.ceil((lat_max - lat_min) / 0.0025)
driver = gdal.GetDriverByName("GTiff")
outds = driver.Create(outfile, newcols, newrows, 1, gdal.GDT_Int16)
geo2 = (lon_min, 0.0025, 0, lat_max, 0, -1 * 0.0025)
oproj_srs = osr.SpatialReference()
proj_4 = "+proj=longlat +datum=WGS84 +no_defs"
oproj_srs.ImportFromProj4(proj_4)
outds.SetGeoTransform(geo2)
outds.SetProjection(oproj_srs.ExportToWkt())
outband = outds.GetRasterBand(1)
datav = ds.ReadAsArray()
data = np.full((datav.shape[0] + 1, datav.shape[1] + 1), -32750, dtype=int)
data[0:datav.shape[0], 0:datav.shape[1]] = datav
xblocksize = int(newcols / 5)
yblocksize = int(newrows / 5)
for i in range(0, newrows, yblocksize):
    if i + yblocksize < newrows:
        numrows = yblocksize
    else:
        numrows = newrows - i
    for j in range(0, newcols, xblocksize):
        if j + xblocksize < newcols:
            numcols = xblocksize
        else:
            numcols = newcols - j
        x = lon_min + j * 0.0025 + 0.0025 / 2.0
        y = lat_max + i * (-1 * 0.0025) - 0.0025 / 2.0
        newxgrid, newygrid = np.meshgrid(np.linspace(x, x + numcols * 0.0025, num=numcols),
                                         np.linspace(y, y + numrows * (-1 * 0.0025), num=numrows))
        # 将经纬度坐标转化为Hammer坐标
        newxgrid = np.where(newxgrid > 180.0, newxgrid - 360.0, newxgrid)
        newxgrid = newxgrid / 180.0 * math.pi
        newygrid = newygrid / 180.0 * math.pi
        newz = np.sqrt(1 + np.cos(newygrid) * np.cos(newxgrid / 2.0))
        x = np.cos(newygrid) * np.sin(newxgrid / 2.0) / newz
        newxgrid = None
        y = np.sin(newygrid) / newz
        newygrid = None
        newz = None
        x = x * (18000.0 * 1000.0)
        y = y * (9000.0 * 1000.0)
        x_index = (np.floor((x - or_x) / ingeo[1])).astype(int)
        x_index = np.where(x_index < 0, data.shape[1] - 1, x_index)
        x_index = np.where(x_index >= data.shape[1], data.shape[1] - 1, x_index)
        y_index = (np.floor((y - or_y) / ingeo[5])).astype(int)
        y_index = np.where(y_index < 0, data.shape[0] - 1, y_index)
        y_index = np.where(y_index >= data.shape[0], data.shape[0] - 1, y_index)
        newdata = data[y_index, x_index]
        outband.WriteArray(newdata, j, i)
outband.SetNoDataValue(-32750)
outband.FlushCache()

编辑

投影到WGS1984坐标系下。

04数据裁剪

import gdal

infile = r"D:\微信公众号\FY3D_MERSI_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS_WGS1984.tif"
shapefile = r"D:\我们自己的全国县级矢量\shp\province_shp\china_北京市_WGS1984.shp"
outfile = r"D:\微信公众号\FY3D_MERSI_L3_NVI_MLT_HAM_20210620_AOTD_0250M_MS_WGS1984_clip.tif"
warp_parameters = gdal.WarpOptions(format='GTiff',
                                   cutlineDSName = shapefile ,
                                   cropToCutline = True)
gdal.Warp(outfile, infile,  options = warp_parameters)

编辑

裁剪出北京市的结果。

关注我个人wx_gzh:小Rser


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容