使用说明:
输出结果存储在当面目录下的results文件夹(自动生成),命名为原始图片文件名+'_heat.png'
不用多次运行代码,需要用多少次就用多少次:
“动一下鼠标(选图片) 几下鼠标 (标点) 继续动一下鼠标(选图片)”
特点
交互式选点:在底图上单击增加点,再次单击去除点
核密度估计:基于选点估算核密度
热力图可视化:可调颜色图,经典配色方案:‘jet','viridis','coolwarm'
参数可调:(1)输出图像大小(比例) out_shape;(2)核密度(高斯核)估计带宽 bandwidth
(3)数据集所在目录
package友好:家常库
and GPT目前不能一条龙解决
代码如下:
import numpy as np
from sklearn.neighbors import KernelDensity
import matplotlib.pyplot as plt
import cv2
import tkinter as tk
from tkinter import filedialog
import os
def ManualControlKDE(bw=40, default_directory='./', outshape=1.0):
def toggle_neighbors(matrix, y, x):
# 切换当前点的状态
matrix[y, x] = 1 - matrix[y, x]
# 切换四个相邻点的状态
neighbors = [(y-1, x), (y+1, x), (y, x-1), (y, x+1)]
for neighbor_y, neighbor_x in neighbors:
if 0 <= neighbor_y < matrix.shape[0] and 0 <= neighbor_x < matrix.shape[1]:
matrix[neighbor_y, neighbor_x] = 1 - matrix[neighbor_y, neighbor_x]
def onclick(event):
if event.xdata is not None and event.ydata is not None:
x = int(round(event.xdata))
y = int(round(event.ydata))
# 切换当前点及其相邻点的状态
toggle_neighbors(matrix, y, x)
# 更新图像
update_plot()
def update_plot():
plt.clf()
plt.imshow(img)
plt.imshow(matrix, cmap='viridis', alpha=0.3)
plt.title("Click on points (1 to select, 0 to deselect)")
plt.draw()
resume = True
while resume:
root = tk.Tk()
root.withdraw() # 隐藏主窗口
# 打开文件选择对话框
file_path = filedialog.askopenfilename(title="选择文件", initialdir=default_directory, filetypes=[("图像文件", "*.png;*.jpg;*.jpeg")])
# 检查用户是否选择了文件
if file_path:
print("选择的文件路径:", file_path)
else:
print("未选择任何文件")
resume = False
root.destroy()
image_path = file_path
img = cv2.imread(image_path)
img = cv2.cvtColor(cv2.resize(img, (int(outshape*img.shape[1]), int(outshape*img.shape[0]))), cv2.COLOR_BGR2RGB)
# 初始化矩阵
matrix = np.zeros((img.shape[0], img.shape[1]), dtype=int)
# 通过交互式绘图选择点
plt.imshow(img)
plt.title("Click on points (1 to select, 0 to deselect)")
cid = plt.gcf().canvas.mpl_connect('button_press_event', onclick)
plt.show()
HW = matrix
data_points = np.argwhere(HW == 1)
# 使用核密度估计
kde = KernelDensity(bandwidth=bw, kernel='gaussian')
kde.fit(data_points)
# 生成网格坐标
x, y = np.meshgrid(np.linspace(0, HW.shape[1] - 1, HW.shape[1]), np.linspace(0, HW.shape[0] - 1, HW.shape[0]))
grid_points = np.c_[y.ravel(), x.ravel()]
# 计算核密度估计
log_density = kde.score_samples(grid_points)
density_matrix = np.exp(log_density).reshape(x.shape)
plt.figure()
plt.imshow(img)
# 叠加核密度图
plt.imshow(density_matrix, cmap='jet', alpha=0.3, extent=(0, img.shape[1], img.shape[0], 0))
# 关闭坐标轴
plt.axis('off')
# 设置空标题
plt.title('')
if not os.path.exists('./results/'):
os.mkdir('./results/')
# files = os.listdir('./results/')
base = os.path.basename(file_path).split('.')[0]
plt.savefig('./results/{}_heat.png'.format(base), bbox_inches='tight')
# 显示图形
plt.show()
default_directory = 'xxxxxx' # 指定包含需要处理的图像的目录
bandwidth = 40 # 影响热图效果
outshape = 0.5 # 输出大小比例
ManualControlKDE(bandwidth, default_directory, outshape)