如何用Plotly绘制支持Hover显示类别信息的语义分割图
解决方案:Plotly语义分割图带悬停类别信息
核心思路
先构建一个与原图尺寸一致的类别标签矩阵,每个像素位置存储对应的类别名称(无掩码覆盖则为"背景"),然后通过Plotly的imshow函数绑定这个标签矩阵,就能实现悬停时显示类别信息,同时避免多trace覆盖的问题。
步骤1:构建类别标签矩阵
假设输入:
img: 形状为(H, W, 3)的uint8原图数组masks_dict: 字典,键为类别名称,值为形状(H, W)的uint8二进制掩码(1为目标区域,0为背景)
代码示例:
import numpy as np # 初始化标签矩阵,默认值为"背景" h, w = img.shape[:2] label_matrix = np.full((h, w), "背景", dtype=str) # 遍历每个类别,将掩码区域替换为对应类别名称 for class_name, mask in masks_dict.items(): # 确保掩码是二进制格式 mask_binary = (mask > 0).astype(bool) label_matrix[mask_binary] = class_name
步骤2:用Plotly绘制带悬停的分割图
方法1:快速实现(仅原图+悬停信息)
用plotly.express.imshow直接绑定hovertext,简洁高效:
import plotly.express as px fig = px.imshow(img, binary_string=True) # 转置标签矩阵匹配Plotly的坐标逻辑(x对应宽度,y对应高度) fig.update_traces( hovertext=label_matrix.T, hovertemplate="位置: (%{x}, %{y})<br>类别: %{hovertext}" ) fig.show()
方法2:自定义叠加掩码颜色(带半透明效果)
如果需要同时显示掩码的颜色叠加层,可在原图上添加半透明掩码trace,同时保留底层的悬停信息:
import plotly.graph_objects as go # 创建基础原图trace,绑定悬停信息 fig = go.Figure() fig.add_trace( go.Image( z=img, hovertext=label_matrix.T, hovertemplate="位置: (%{x}, %{y})<br>类别: %{hovertext}" ) ) # 自定义类别对应的半透明颜色 color_map = { "道路": "rgba(255,0,0,0.3)", "建筑": "rgba(0,255,0,0.3)", "植被": "rgba(0,0,255,0.3)" } # 叠加每个类别的掩码层 for class_name, mask in masks_dict.items(): # 生成RGBA格式的掩码图像 mask_rgba = np.zeros((h, w, 4), dtype=np.uint8) r, g, b, a = [int(c) for c in color_map.get(class_name, "rgba(128,128,128,0.3)").strip("rgba()").split(",")] mask_rgba[mask > 0] = [r, g, b, a] # 添加掩码层,关闭自身hover避免干扰 fig.add_trace(go.Image(z=mask_rgba, hoverinfo="skip")) fig.update_layout(width=800, height=600) fig.show()
常见问题解决
- 最后一个trace覆盖整图:避免用
add_heatmap,改用Imagetrace并设置透明度,或者直接用标签矩阵绑定hovertext的单trace方案,从根源解决覆盖问题。 - 悬停位置与像素不匹配:Plotly的
imshow中x轴对应图像宽度、y轴对应高度,因此需要将label_matrix转置(.T),确保悬停信息坐标与像素位置对齐。
内容的提问来源于stack exchange,提问作者Nicola Fanelli
相关产品推荐
相关产品推荐

