|
楼主 |
发表于 2024-4-27 23:48
|
显示全部楼层
本帖最后由 我不是Carl2 于 2024-5-15 00:45 编辑
陆地叠图:
伪VIS的陆地叠图有两种方式:Blue Marble和Black Marble。这里我们主要讲解流程更复杂的Blue Marble叠图。
Blue Marble下载网址如下:
https://visibleearth.nasa.gov/im ... d-shaded-topography
下面是个人预处理的Blue Marble底图,海面弄蓝了一点:
https://archive.dapiya.top/AI-VIS_Demo/Worldv3.png
(感谢王站长帮忙生成图片链接)
读取图片可以使用第三方库opencv:
- import cv2
- image = cv2.imread(r'底图文件路径', cv2.IMREAD_COLOR)
复制代码
Blue Marble是覆盖全球的等经纬投影地图。我们希望将其裁到和卫星亮温、经纬度等数据相同的网格上,即2030×1354的扫描网格,以便后续运算。我们将每个像素的经纬度转化为该经纬度在全球等经纬地图中的行列号,并把对应行列号的Blue Marble像素填回扫描网格。
- indexlon = np.round(newlon*60).astype(int)
- indexlat = np.rint((90-newlat)*60).astype(int)
- BM = image[indexlat, indexlon, :]/255
复制代码
这时候如果我们直接把Blue Marble画出来:
- plt.pcolormesh(newlon, newlat, BM)
复制代码
陆地的裁取没什么问题,且底图确实和亮温,经纬度等数据处于同一网格。唯一的问题是颜色不对,这是由于Matplotlib默认按照r, g, b的顺序,而opencv读取的顺序是b, g, r,将BM的第三个维度取倒序就能得到颜色正确的底图了。
- plt.pcolormesh(newlon, newlat, BM[:, :, ::-1])
复制代码
接下来就是将模拟反射率和底图通过合成算法叠起来。此处许多步骤相当经验性,并且色调与代码可能还有不小的优化空间。有能力的读者可以自己尝试优化这部分代码,不过直接用我现在这版应该也大差不差。
将底图分解为rgb三个通道,并去除一列与合成好的模拟反射率对齐
- b1, g1, r1 = cv2.split(BM[:, 1:])
复制代码
提亮模拟反射率以免合成后海面过暗
初步合成模拟反射率与底图
- blue = b * b1 + np.power(b, 1.6) * (1 - b1)
- green = b * g1 + np.power(b, 1.6) * (1 - g1)
- red = b * r1 + np.power(b, 1.6) * (1 - r1)
- land_brightness = np.clip((g1 + r1)/2, 0, 0.4)
复制代码
后续调色需要海洋和陆地分开调,通过映射底图的r通道做一个海陆分离,对于陆地像素ocean=0,海面像素ocean=1。
- norm2 = Normalize(vmin=0, vmax=1, clip=True)
- map2 = ScalarMappable(norm2, LinearSegmentedColormap('1', oceandata))
- ocean = map2.to_rgba(r1)[:, :, 0]
复制代码
用于映射的色阶oceandata:
- oceandata={'green': [(0, 0, 0),
- (1, 1, 1)],
- 'red': [(0, 255/255, 255/255),
- (15/255, 255/255, 255/255),
- (30/255, 0/255, 0/255),
- (1, 0, 0)],
- 'blue': [(0, 0, 0),
- (1, 1, 1)]}
复制代码
根据亮温,模拟反射率调整图像饱和度。反射率越高/亮温越低,饱和度越低,陆地的饱和度也设置的比海面更高一些。这里饱和度的定义并不正式,和HSV空间中的有些区别。
- Saturation = 1.5 * (1 - np.clip(ref - 0.4, 0, 0.5)/0.5) + (1 - ocean) * 3 * (np.clip(bt31[:, 1:], -60, 10) + 60)/70
- avg = (blue + green + red) / 3
- blue = (avg + (blue - avg) * Saturation) * 0.98
- green = avg + (green - avg) * Saturation
- red = avg + (red - avg) * Saturation
复制代码
调整一下洋面颜色(这段两年多前写的有点过于繁琐,大概率是可以继续优化的):
- recolor = np.clip(green, 0.1, 0.3) - 0.1
- red = red * (0.2 + recolor * 4) * ocean + (1-ocean) * red
- green = green * (0.8 + recolor) * ocean + (1-ocean) * green
- norm3 = Normalize(vmin=0, vmax=1, clip=True)
- map3 = ScalarMappable(norm3, LinearSegmentedColormap('1', recolordata))
- recolor2 = map3.to_rgba(green)[:, :, 0]
- green = green + (- 10/255 + recolor2) * ocean
复制代码
用于调整洋面颜色的色阶:
- recolordata={'green': [(0, 0, 0),
- (1, 1, 1)],
- 'red': [(0, 0/255, 0/255),
- (8/255, 4/255, 4/255),
- (20/255, 2/255, 2/255),
- (37/255, 10/255, 10/255),
- (57/255, 10/255, 10/255),
- (74/255, 16/255, 16/255),
- (140/255, 15/255, 15/255),
- (160/255, 10/255, 10/255),
- (1, 10/255, 10/255)],
- 'blue': [(0, 0, 0),
- (1, 1, 1)]}
复制代码
将三个颜色通道合并,限制到0~1的值以便pcolormesh画图:
- rgb = np.stack([red, green, blue], axis=2)
- rgb = np.clip(rgb, 0, 1)
复制代码
出图效果如下:
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|