离散二维点集的热度图生成

最近在处理一些二维注视点,需要直接将离散的二维注视点转换成概率分布,基本原理是用Gaussian函数进行卷积生成连续的概率分布。处理这个之前顺便做了一个简单的可视化,利用涂色原理生成热度图并涂上彩虹色。

HeatMap.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef HeatMap_hpp
#define HeatMap_hpp

#include <opencv2/opencv.hpp>
#include <cmath>

cv::Vec3b getRainbowColor(int gray, bool black_base = false);
void paintMap(cv::Mat_<float> &img, cv::Point p, int radius, int base = 0);
cv::Mat_<uchar> generateHeatMapGray(cv::Mat_<float> &raw_map);
cv::Mat_<cv::Vec3b> generateHeatMapColor(cv::Mat_<uchar> &heat_map_gray, bool black_base = false);
cv::Mat_<cv::Vec3b> generateHeatMapColor(cv::Mat_<float> &raw_map, bool black_base = false);

#endif /* HeatMap_hpp */

HeatMap.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//
// HeatMap.cpp
//
// Created by Li Songjiang on 4/14/16.
// Copyright © 2016 PKUCV. All rights reserved.
//

#include "HeatMap.hpp"

double getDistance(cv::Point p1, cv::Point p2) {
double ret = 0;
ret = sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
return ret;
}

cv::Vec3b getRainbowColor(int gray, bool black_base) {
if (gray <= 51) return cv::Vec3b(black_base ? 0 : 255, gray * 5, 0);
else if (gray <= 102) {
gray -= 51;
return cv::Vec3b(255 - gray * 5, 255, 0);
}
else if (gray <= 153) {
gray -= 102;
return cv::Vec3b(0, 255, gray * 5);
}
else if (gray <= 204) {
gray -= 153;
return cv::Vec3b(0, 255 - uchar(128.0 * gray / 51.0 + 0.5), 255);
}
else {
gray -= 204;
return cv::Vec3b(0, 127 - uchar(127.0 * gray / 51.0 + 0.5), 255);
}
}


void paintMap(cv::Mat_<float> &img, cv::Point p, int radius, int base) {
float dist;
int i_min, i_max, j_min, j_max;
i_min = p.x - radius < 0 ? 0 : p.x - radius;
i_max = p.x + radius > img.rows ? img.rows : p.x + radius;
j_min = p.y - radius < 0 ? 0 : p.y - radius;
j_max = p.y + radius > img.cols ? img.cols : p.y + radius;
for (int i =i_min; i < i_max; i++) {
for (int j =j_min; j < j_max; j++) {
dist = getDistance(p, cv::Point(i, j));
if (dist > radius) continue;
img.at<float>(i, j) += radius - dist + base;
}
}
}

cv::Mat_<uchar> generateHeatMapGray(cv::Mat_<float> &raw_map) {
cv::Mat_<uchar> heat_map_gray(raw_map.rows, raw_map.cols);
float min_value = 100000000.0, max_value = 0.0, delta;
for (int i = 0; i < raw_map.rows; i++) {
for (int j = 0; j < raw_map.cols; j++) {
if (raw_map.at<float>(i, j) > max_value) max_value = raw_map.at<float>(i, j);
if (raw_map.at<float>(i, j) < min_value) min_value = raw_map.at<float>(i, j);
}
}
delta = max_value - min_value;
for (int i = 0; i < heat_map_gray.rows; i++) {
for (int j = 0; j < heat_map_gray.cols; j++) {
heat_map_gray.at<uchar>(i, j) = 255.0 * (raw_map.at<float>(i, j) - min_value) / delta;
}
}
return heat_map_gray;
}

cv::Mat_<cv::Vec3b> generateHeatMapColor(cv::Mat_<uchar> &heat_map_gray, bool black_base) {
cv::Mat_<cv::Vec3b> heat_map_color(heat_map_gray.rows, heat_map_gray.cols);
for (int i = 0; i < heat_map_gray.rows; i++) {
for (int j = 0; j < heat_map_gray.cols; j++) {
heat_map_color.at<cv::Vec3b>(i, j) = getRainbowColor(heat_map_gray.at<uchar>(i, j), black_base);
}
}
return heat_map_color;
}


cv::Mat_<cv::Vec3b> generateHeatMapColor(cv::Mat_<float> &raw_map, bool black_base) {
cv::Mat_<uchar> heat_map_gray = generateHeatMapGray(raw_map);
return generateHeatMapColor(heat_map_gray, black_base);
}

依赖:OpenCV