feat: fix positions

This commit is contained in:
Dustella 2025-02-12 23:44:00 +08:00
parent a501342700
commit 35fe44339a
Signed by: Dustella
GPG Key ID: 35AA0AA3DC402D5C
5 changed files with 242 additions and 25 deletions

3
.gitignore vendored
View File

@ -7,4 +7,5 @@ staged
res.md
dist
*.spec
build
build
!colorbar.ipynb

165
colorbar.ipynb Normal file
View File

@ -0,0 +1,165 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0.050383, 0.029803, 0.527975, 1. ],\n",
" [0.063536, 0.028426, 0.533124, 1. ],\n",
" [0.075353, 0.027206, 0.538007, 1. ],\n",
" ...,\n",
" [0.944152, 0.961916, 0.146861, 1. ],\n",
" [0.941896, 0.96859 , 0.140956, 1. ],\n",
" [0.940015, 0.975158, 0.131326, 1. ]], shape=(256, 4))"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"import matplotlib as mpl\n",
"import numpy as np\n",
"\n",
"mpl.colormaps[\"plasma\"](np.linspace(0, 1, 256))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from matplotlib.colors import ListedColormap\n",
"import numpy as np\n"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/tmp/ipykernel_4058693/3103424214.py:42: UserWarning: set_ticklabels() should only be used with a fixed number of ticks, i.e. after set_ticks() or using a FixedLocator.\n",
" ax.set_xticklabels([format_spec % val for val in ax.get_xticks()])\n"
]
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 500x80 with 1 Axes>"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 500x80 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from matplotlib.colorbar import ColorbarBase\n",
"\n",
"\n",
"def create_colorbar(get_color, vmin=0, vmax=1, width=8, height=0.8, dpi=100, num_samples=256, \n",
" title=None, format_spec=\"%.2f\"):\n",
" \"\"\"\n",
" 创建自定义colorbar\n",
" \n",
" 参数:\n",
" get_color: 颜色映射函数接受vmin-vmax之间的值返回(r,g,b,a)颜色元组\n",
" vmin: colorbar最小值\n",
" vmax: colorbar最大值\n",
" width: 图像宽度\n",
" height: 图像高度\n",
" dpi: 图像分辨率\n",
" num_samples: 颜色采样数量\n",
" title: colorbar标题\n",
" format_spec: 刻度格式化字符串\n",
" \"\"\"\n",
" # 创建图形\n",
" fig, ax = plt.subplots(figsize=(width, height), dpi=dpi)\n",
" \n",
" # 生成颜色样本\n",
" colors = []\n",
" for i in range(num_samples):\n",
" # 计算实际值\n",
" value = vmin + (vmax - vmin) * (i / (num_samples - 1))\n",
" r, g, b, a = get_color(value)\n",
" colors.append((r, g, b, a))\n",
" \n",
" # 创建自定义colormap\n",
" custom_cmap = ListedColormap(colors)\n",
" \n",
" # 直接创建colorbar\n",
" ColorbarBase(ax, \n",
" cmap=custom_cmap,\n",
" orientation='horizontal',\n",
" norm=plt.Normalize(vmin, vmax))\n",
" \n",
" # 设置刻度数量和格式\n",
" ax.locator_params(nbins=5) # 设置大约5个刻度\n",
" ax.set_xticklabels([format_spec % val for val in ax.get_xticks()])\n",
" \n",
" # 设置标题(如果提供)\n",
" if title:\n",
" ax.set_title(title)\n",
" \n",
" # 调整布局\n",
" plt.tight_layout()\n",
" \n",
" return fig\n",
"\n",
"def get_color(value):\n",
" if value == 0:\n",
" return (0, 0, 0, 0)\n",
" result = mpl.colormaps[\"hot\"](value)\n",
" _res = tuple([int(255 * x) for x in result])\n",
" r, g, b, a = _res\n",
" # return (r, g, b, a)\n",
" return (result[0], result[1], result[2], value*3)\n",
"\n",
"create_colorbar(get_color, vmax=0.3, width=5)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "vertex",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -2,6 +2,7 @@ from io import BytesIO
from flask import Blueprint, request, send_file
from src.plot import create_heatmap, find_centroids
from src.process_data import get_all_heat_points
from src.read_tar import TarGet
@ -30,6 +31,19 @@ def render():
return send_file(buff, mimetype='image/png')
@tc_module.route("/render/heatpoint")
def get_points():
path = request.args.get('path')
day = request.args.get('day')
tar = TarGet(path)
data = tar.read_dtcp()
data_this_day = data["data"][:, :, int(day)]
result = get_all_heat_points(data_this_day, (0, -35))
return result
@tc_module.route("/metadata/centroids")
def get_centroids():
path = request.args.get('path')
@ -39,7 +53,11 @@ def get_centroids():
data_this_day = data["data"][:, :, int(day)]
centords = find_centroids(data_this_day)
return centords
def mapper(data):
x, y = data
return x, y-35
return list(map(mapper, centords))
@tc_module.route("/metadata/tc")

View File

@ -2,15 +2,18 @@ import numpy as np
from PIL import Image
from scipy import ndimage
import matplotlib as mpl
COLOR_MAPS = mpl.colormaps
def find_centroids(image):
def find_centroids(image, offset_result=(0, 0)):
"""
找出图像中所有联通区域的重心
Args:
image: 2D numpy array值为0或非0
offset_result: 重心坐标的偏移量用于将重心坐标转换为原始图像坐标
Returns:
list of tuples: [(y1,x1), (y2,x2), ...] 表示每个联通区域的重心坐标
"""
@ -30,13 +33,15 @@ def find_centroids(image):
centroid_y = np.average(y_coords, weights=weights)
centroid_x = np.average(x_coords, weights=weights)
centroids.append((centroid_y, centroid_x))
offset_x, offset_y = offset_result
centroids.append((centroid_y + offset_y, centroid_x + offset_x))
return centroids
def create_heatmap(data,
colormap='hot',
colormap='plasma',
flip_vertical=False,
flip_horizontal=False,
rotate_90=0,
@ -47,7 +52,7 @@ def create_heatmap(data,
参数:
data: 2D numpy array值应该在0-1之间
colormap: 颜色映射方案目前支持'hot'
colormap: 颜色映射方案目前支持'plasma'
flip_vertical: 是否垂直翻转
flip_horizontal: 是否水平翻转
rotate_90: 顺时针旋转的90度次数 (0, 1, 2, 3)
@ -78,28 +83,25 @@ def create_heatmap(data,
image = Image.new('RGBA', (width, height), (0, 0, 0, 0))
# 创建颜色映射
if colormap == 'hot':
# 红色到黄色的渐变
# 非线性变换,使得低值更容易区分。 使用 sqrt(x) 作为映射函数
def get_color(value):
# 首先把原value从0~0.1映射到0~1。如果value大于0.1就直接取1
value = min(value / 0.4, 1)
if np.isnan(value):
return (0, 0, 0, 0)
r = int(min(255, np.sqrt(value) * 256))
g = int(max(0, min(255, np.sqrt(value) * 256 - 256)))
return (r, g, 0, int(value * 255))
# def get_color(value):
# if np.isnan(value):
# return (0, 0, 0, 0)
# r = int(min(255, value * 510))
# g = int(max(0, min(255, value * 510 - 255)))
# return (r, g, 0, int(value * 255))
if type(colormap) == str:
mapper = COLOR_MAPS[colormap]
if mapper is None:
raise ValueError('Invalid colormap name')
def get_color(value):
if value == 0:
return (0, 0, 0, 0)
result = mapper(value)
_res = tuple([int(255 * x) for x in result])
r, g, b, _ = _res
return (r, g, b, min(int(value * 255 * 3), 255))
else:
get_color = colormap
# 填充像素
pixels = image.load()
for y in range(height):
for x in range(width):
pixels[x, y] = get_color(data[y, x])
pixels[x, y] = get_color(
data[y, x])
return image

View File

@ -0,0 +1,31 @@
from dataclasses import dataclass
from typing import List
import numpy as np
@dataclass
class HeatPoint:
lng: float
lat: float
count: int
def get_all_heat_points(data: np.ndarray, offset=(0, 0)) -> List[HeatPoint]:
"""
# filter all points that has value greater than 0
data: 2D numpy array
offset: tuple, the offset of the data
"""
# first, we need to filter all points that has value greater than 0
points = []
for i in range(data.shape[0]):
for j in range(data.shape[1]):
if data[i, j] > 0:
if data[i, j] > 0:
points.append(
HeatPoint(lng=float(j+offset[1]+0.1), lat=float(i+offset[0]+0.1), count=int(data[i, j]*256+1)))
else:
continue
return list(filter(lambda d: d.count > 0, points))