google earth engine随缘学习(十四)文字标注(附自己改的Python代码)

文字标注

前言:因为最近在尝试用cesium和gee结合做东西,需要用到图例。其中我的图是动态生成的,所以一时间不知道怎么结合gee做动态图例,后来我看到有人直接把它显示在目标图层里,这是个好办法。但是要做图例,首先要解决的文字标注问题。
以后关于js的代码我尽量放置可以运行的链接,不再贴代码~
关于讨论文字标注的论坛链接
例子1 简单文本标注
简短版本(函数压缩成一句) https://code.earthengine.google.com/c4e0809d820b716354989f3caa1fcdbb
完整版本https://code.earthengine.google.com/2fa108d7211cdf73c62b241594bc1753
更简洁版本(调用包)https://code.earthengine.google.com/9fc23889ec43983250dfecf5be08267f
此后的几个例子关于文字标注函数的引用,大家可参照上述三种方式

google earth engine随缘学习(十四)文字标注(附自己改的Python代码)_第1张图片

例子2 经纬度标注
https://code.earthengine.google.com/ad954e02518c397f4734e5d92c88e021

google earth engine随缘学习(十四)文字标注(附自己改的Python代码)_第2张图片

例子3 图幅标注
https://code.earthengine.google.com/922a780f9e6372367270b2b477e68d4d

例子4 多文字图层合并

https://code.earthengine.google.com/90083716c54e0e3c19855517e74e3967

google earth engine随缘学习(十四)文字标注(附自己改的Python代码)_第3张图片

原理很简单,就是GEE根据字号和字型存储了大量的字符栅格图像,比如如下:
https://code.earthengine.google.com/59b09ba4a8aa38a673d6e4176d3bf041

google earth engine随缘学习(十四)文字标注(附自己改的Python代码)_第4张图片google earth engine随缘学习(十四)文字标注(附自己改的Python代码)_第5张图片

函数会根据你的字号和字型找到对应的图像,根据编码从中挑出你要的字符,经过重采样、投影变换等展示在你放置的位置上

Python代码

找了很久没有发现相关的Python函数或包,唯一可以查找的就是官方放在js package里的一个函数,于是只能自己手动改了,除了语法相关,还改了一些python里不适用的函数,如有错误,请批评指正!
def drawText(text, pos, scale, props):
    text = ee.String(text)
    ascii = {}
    for i in range(32, 128):
        ascii[chr(i%256)] = i
    ascii = ee.Dictionary(ascii)
    fontSize = "16"
    if props and ('fontSize' in props.keys()):
        fontSizee = str(props['fontSize'])

    fontType = "Arial"
    if props and ('fontType' in props.keys()):
        fontSize = str(props['fontType'])

    glyphs = ee.Image('users/gena/fonts/' + fontType + fontSize)
    if props and ('resample' in props.keys()):
        glyphs = glyphs.resample(props['resample'])

    proj = glyphs.projection()
    s = ee.Number(1).divide(proj.nominalScale())
    north = ee.Algorithms.If(proj.transform().index("-1.0").lt(0), -1, 1)
    glyphs = glyphs.changeProj(proj, proj.scale(s, s.multiply(north)))
    class newfont:
        def __init__(self):
            self.height = ee.Number(glyphs.get('height'))
            self.width = ee.Number(glyphs.get('width'))
            self.cellHeight = ee.Number(glyphs.get('cell_height'))
            self.cellWidth = ee.Number(glyphs.get('cell_width'))
            self.charWidths = ee.List(list(map(int, ee.String(glyphs.get('char_widths')).split(',').getInfo())))
    font = newfont()
    font.columns = font.width.divide(font.cellWidth).floor()
    font.rows = font.height.divide(font.cellHeight).floor()

    def translate(coord, x, y):
        x1 = ee.Number(coord.get(0)).subtract(x)
        y1 = ee.Number(coord.get(1)).subtract(y)
        return ee.List([x1, y1])
    
    def toAscii(text):
        def fun(char, prev):
            return ee.List(prev).add(ascii.get(char))
        return ee.List(text.split('').iterate(fun, ee.List([])))

    def moveChar(image, xmin, xmax, ymin, ymax, x, y):
        ll = ee.Image.pixelLonLat()
        nxy = ll.floor().round().changeProj(ll.projection(), image.projection())
        nx = nxy.select(0)
        ny = nxy.select(1)
        mask =nx.gte(xmin).add(nx.lt(xmax)).add(ny.gte(ymin)).add(ny.lt(ymax)).eq(4)
        return image.mask(mask).translate(ee.Number(xmin).multiply(-1).add(x), ee.Number(ymin).multiply(-1).subtract(y))

    codes = toAscii(text)

    def getwidth(code):
        return ee.Number(font.charWidths.get(ee.Number(code)))

    charWidths = codes.map(getwidth)
    alignX = 0
    alignY = 0
    alignX = ee.Number(charWidths.reduce(ee.Reducer.sum())).divide(2)
    alignY = ee.Number(font.cellHeight).divide(ee.Number(2).multiply(north))

    if props and ('alignX' in props.keys()):
        if props['alignX'] == 'center':
            alignX = ee.Number(charWidths.reduce(ee.Reducer.sum())).divide(2)
        elif props['alignX'] == 'left':
            alignX = 0
        elif props['alignX'] == 'right':
            alignX = ee.Number(charWidths.reduce(ee.Reducer.sum()))

    if props and ('alignY' in props.keys()):
        if props['alignY'] == 'center':
            alignY = ee.Number(font.cellHeight).divide(ee.Number(2).multiply(north))
        elif props['alignY'] == 'top':
            alignY = 0
        elif props['alignY'] == 'bottom':
            alignY = ee.Number(font.cellHeight)

    def computexpos(w, list):
        list = ee.List(list)
        lastX = ee.Number(list.get(-1))
        x = lastX.add(w)
        return list.add(x)

    charX = ee.List(charWidths.iterate(computexpos, ee.List([0]))).slice(0, -1)
    charPositions = charX.zip(ee.List.sequence(0, charX.size()))

    def computeglyph(code):
        code = ee.Number(code).subtract(32)
        y = code.divide(font.columns).floor().multiply(font.cellHeight)
        x = code.mod(font.columns).multiply(font.cellWidth)
        return [x, y]

    charGlyphPositions = codes.map(computeglyph)
    charGlyphInfo = charGlyphPositions.zip(charWidths).zip(charPositions)
    pos = ee.Geometry(pos).transform(proj, scale).coordinates()
    xpos = ee.Number(pos.get(0)).subtract(ee.Number(alignX).multiply(scale))
    ypos = ee.Number(pos.get(1)).subtract(ee.Number(alignY).multiply(scale))

    def drawglyphs(o):
        o = ee.List(o)
        glyphInfo = ee.List(o.get(0))
        gw = ee.Number(glyphInfo.get(1))
        glyphPosition = ee.List(glyphInfo.get(0))
        gx = ee.Number(glyphPosition.get(0))
        gy = ee.Number(glyphPosition.get(1))
        charPositions = ee.List(o.get(1))
        x = ee.Number(charPositions.get(0))
        i = ee.Number(charPositions.get(1))
        glyph = moveChar(glyphs, gx, gx.add(gw), gy, gy.add(font.cellHeight), x, 0)
        return glyph.changeProj(proj, proj.translate(xpos, ypos).scale(scale, scale))

    textImage = ee.ImageCollection(charGlyphInfo.map(drawglyphs)).mosaic()
    textImage = textImage.mask(textImage)
    if props:
        if 'textColor' in props.keys():
            textColor = props['textColor']
        else:
            textColor = 'ffffff'
        if 'outlineColor' in props.keys():
            outlineColor = props['outlineColor']
        else:
            outlineColor = '000000'
        if 'outlineWidth' in props.keys():
            outlineWidth = props['outlineWidth']
        else:
            outlineWidth = 0
        if 'textOpacity' in props.keys():
            textOpacity = props['textOpacity']
        else:
            textOpacity = 0.9
        if 'textWidth' in props.keys():
            textWidth = props['textWidth']
        else:
            textWidth = 1
        if 'outlineOpacity' in props.keys():
            outlineOpacity = props['outlineOpacity']
        else:
            outlineOpacity = 0.4

        textLine = textImage.visualize("b1", None, None, None, None, None, textOpacity, [textColor], True)

        if textWidth > 1:
            textLine.focal_max(textWidth)

        if not props and (props and(not ('outlineWidth' in props.keys()))):
            return textLine

        textOutline = textImage.focal_max(outlineWidth).visualize("b1", None, None, None, None, None, outlineOpacity, outlineColor, True)
        return ee.ImageCollection.fromImages(ee.List([textOutline, textLine])).mosaic()
    else:
        return textImage
        
point = ee.Geometry.Point([12.39,4.07])
string = 'PIKACHU'
props = {'fontSize': 32, 'textColor': '000000'}
text = drawText(string, point, 117407, props) #调用函数
ee.mapclient.addToMap(text)

本地Python运行效果

google earth engine随缘学习(十四)文字标注(附自己改的Python代码)_第6张图片

drawText(text, pos, scale, props) (字符串,位置,分辨率,字体属性)
props里可以修改的是字体的字型、字号、颜色、字体对于给定位置的相对位置、外轮廓颜色等,比如:text =drawText(‘PIKACHU’, ee.Geometry.Point([12.39, 4.07]), 117407, {‘fontSize’: 32, ‘textColor’: ‘FFFF00’, ‘alignX’: ‘left’, ‘textOpacity’: 0.7, ‘outlineColor’: ‘000000’,‘outlineWidth’: 4})
alignX、alignY修改相对位置,alignX三个可选参数为left、centre、right,alignY三个可选参数为top、bottom、center,

在这里插入图片描述
字背景是灰色的是因为网不好,加载底图失败了。。。。

明、后天应该会更新图例部分(感觉做不完。。。)

也可能明后天做完之后,等到答辩完下周再更新博客。。。

你可能感兴趣的:(小白的GEE学习)