热力图生成算法及其具体实现

目录
  • 1. 概述
  • 2. 详论
    • 2.1. 数据准备
    • 2.2. 准备绘制
    • 2.3. 绘制热力范围
    • 2.4. 绘制热力图
    • 2.5. 配色方案
  • 3. 问题
  • 4. 参考

1. 概述

以前一直觉得热力图非常高大上,现在终于有机会研究并总结这个问题了。其实从图像处理的角度上来说,热力图生成算法并没有什么特别的,要得到非常漂亮的效果,数据以及配色方案的也很重要。这里就用OpenCV简单实现一下,用什么工具不重要,重要的是其中的原理。

2. 详论

2.1. 数据准备

我们没有数据,但是可以通过随机数算法,生成一个热力点的集合:

struct HPoint {
  int x;
  int y;
  int value;
};

int width = 512;   //热力图宽
int height = 512;  //热力图高
int reach = 25;    //影响范围
int valueRange = 100;

vector heatPoints;  //热力点
vector heatRects;    //热力范围

void GetHeatPoint() {
  int num = 100;
  heatPoints.resize(num);
  heatRects.resize(num);

  for (int i = 0; i 

这段代码的意思是,我们根据给定的热力图宽高的范围,生成热力图范围内一定权值范围的热力点;并且,根据热力点影响范围求出其外包矩形。这里的随机数并没有给时间种子,所以每次运行的结果都是固定的。

2.2. 准备绘制

我们绘制的目的是一个包含透明度的彩色图片,所以需要创建4波段的图片。通过直接操作图片的内存buffer,首先我们将背景设置成黑色;然后遍历热力点,将热力点的范围涂成白色:

Mat img(height, width, CV_8UC4);
int nBand = 4;

uchar *data = img.data;
size_t dataLength = (size_t)width * height * nBand;
memset(data, 0, dataLength);

for (size_t i = 0; i 

热力图生成算法及其具体实现

2.3. 绘制热力范围

上面绘制的是热力点的外接矩形范围,现在我们绘制热力图真正影响范围。原理其实很简单,就是判断点是否在圆内:

  for (size_t i = 0; i 

热力图生成算法及其具体实现

2.4. 绘制热力图

接下来就让热力范围根据与热力点的距离渐变:距离越近,就越白,距离越远,就越黑:

  for (size_t i = 0; i 

热力图生成算法及其具体实现

立体感到是不错,但是问题在于我们需要将热力点的影响叠加起来,也就是每次遍历热力点之后,像素值也要叠加起来:

  for (size_t i = 0; i 

热力图生成算法及其具体实现

看起来略具意思了,但是有个问题是没有体现每个点的权值的影响,因此我们加上权值的影响,让热力的效果更真实一点:

  for (size_t i = 0; i 

热力图生成算法及其具体实现

2.5. 配色方案

最后就是给这个黑白热力图上色了。配色是非常重要的,需要一点美术功底才行,我们直接采用参考2中的颜色值进行配色。首先创建一个颜色映射表,将之前的黑白色映射到一个BGR渐变色集合:

array, 256> bGRTable;  //颜色映射表

//生成渐变色
void Gradient(array &start, array &end,
              vector> &RGBList) {
  array dBgr;
  for (int i = 0; i  boundaryValue = {0.2, 0.3, 0.4, 0.6, 0.8, 0.9, 1.0};
  array, 7> boundaryBGR;
  boundaryBGR[0] = {255, 0, 0};
  boundaryBGR[1] = {231, 111, 43};
  boundaryBGR[2] = {241, 192, 2};
  boundaryBGR[3] = {148, 222, 44};
  boundaryBGR[4] = {83, 237, 254};
  boundaryBGR[5] = {50, 118, 253};
  boundaryBGR[6] = {28, 64, 255};

  double lastValue = 0;
  array lastRGB = {0, 0, 0};
  vector> RGBList;
  int sumNum = 0;
  for (size_t i = 0; i 

通过这个颜色映射表,在填充像素的时候,将计算的Alpha映射成一个BGR值,填充到前三个波段中:

  for (size_t i = 0; i 

最终的成果如下:
热力图生成算法及其具体实现

3. 问题

  1. OpenCV显示的背景是黑色的,这是因为其默认是按照RGB三波段来显示的,其实最后的结果是个包含透明通道的图像,可以将其叠加到任何图层上:
    热力图生成算法及其具体实现
  2. 热力点可以有权值,也可以没有。没有权值可以认为所有点的权值是一样的,可以适当调整热力影响的范围让不同的热力点连接,否则就是一个个独立的圈。
  3. 如果出现红色的区域(热力值高)过多,那么原因可能是热力点太密了。同一个区域内收到的热力影响太多,计算的alpha超过1,映射到图像像素值导致被截断,无法区分热力值高的区域。那么一个合理的改进方案就是将计算的alpha缓存住,在计算所有的alpha的最大最小,将alpha再度映射到0到1之间,进而映射到像素值的0~255之间——就不会高位截断的问题了。如果有机会,再实现一下这个问题的改进。

4. 参考

  1. 你不知道的前端算法之热力图的实现
  2. 数据可视化:浅谈热力图如何在前端实现

具体源代码实现

发布者:糖太宗,转载请注明出处:https://www.qztxs.com/archives/science/technology/8283

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022年5月22日 下午4:03
下一篇 2022年5月22日 下午4:06

相关推荐

  • jetbrains产品免费食用方法-_-

    0x00 前言 jetbrains的产品大家都不是很陌生,我自己就用过IDEA、PyCharm、PhpStorm、GoLand这几款,专业版首次使用会有30天试用,本着有破解的就不用社区的,有最新版就不用旧版的原则,从网上找到了一些破解方法   0x01 破解补丁 通过搜多引擎能搜索到很多破解补丁,如果版本升级了,破解补丁就不能用了,需要重新找对应...

    2022年5月28日
    6200
  • xhs某书shield逆向破解(一) | 寻找Native函数

    shield是xhs请求header中的一个加密参数,具体算法是在so中计算的,so文件是libshield.so。我这边主要就讲一下如何利用unidbg调用so生成shield参数。因篇幅可能较长,这篇文章就讲下如何找到Native函数和函数所对应的偏移位置。 一、寻找Native函数 老规矩,首先反编译apk后用JD-GUI工具打开(也可使用jadx等工...

    2022年6月2日
    58900
  • 选redis还是memcache,源码怎么说?

    memcache和redis是互联网分层架构中,最常用的KV缓存。不少同学在选型的时候会纠结,到底是选择memcache还是redis。 画外音:不鼓励粗暴的实践,例如“memcache提供的功能是redis提供的功能的子集,不用想太多,选redis准没错”。   虽然redis比memcache更晚出来,且功能确实也更丰富,但对于一个技术人,了解“所以然”...

    2022年5月15日
    2500
  • 老板问我,什么是关联规则推荐?

    工程架构方向的程序员,看到推荐/搜索/广告等和算法相关的技术,心中或多或少有一丝胆怯。但认真研究之后,发现其实没有这么难。 今天给大家介绍下推荐系统中的“关联规则推荐”,保证大伙弄懂。 画外音:可以看excel截图,或者看公式,大伙结合自己能够理解的程度自取。   一、概念 什么是关联规则(Association Rules)? 答:关联规则是数据挖掘中的概...

    2022年5月10日
    6200
  • 老板问我,什么是基于内容的推荐?

    工程架构方向的程序员,看到推荐/搜索/广告等和算法相关的技术,心中或多或少有一丝胆怯。但认真研究之后,发现其实没有这么难。 今天给大家介绍下推荐系统中的“基于内容的推荐”,绝无任何公式,保证大伙弄懂。什么是基于内容的推荐(Content-based Recommendation)?答:通过用户历史感兴趣的信息,抽象信息内容共性,根据内容共性推荐其他信息。 比...

    技术 2022年5月11日
    1600

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信