-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlocalcontrastenhancer.cpp
More file actions
119 lines (112 loc) · 3.46 KB
/
localcontrastenhancer.cpp
File metadata and controls
119 lines (112 loc) · 3.46 KB
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "localcontrastenhancer.h"
#include <omp.h>
#include <utils.h>
#include <QDebug>
using namespace cv;
void LocalContrastEnhancer::doWork(Mat &image, float force)
{
_image = image;
_force = force;
TILE_XCOUNT = 2 + 8 * force;
TILE_YCOUNT = 2 + 8 * force;
start();
}
void LocalContrastEnhancer::setMode(LocalContrastEnhancer::Mode m)
{
_mode = m;
}
Mat LocalContrastEnhancer::unsharpMask()
{
Mat result;
GaussianBlur(_image, result, cv::Size(0, 0), 3);
addWeighted(_image, 1.5 + _force * 2, result, -0.5 -_force * 2, 0, result);
return result;
}
void LocalContrastEnhancer::run()
{
Mat result;
switch (_mode) {
case AHE:
result = processAdaptive();
break;
case CLAHE:
result = processAdaptive(true);
break;
case UnsharpMask:
result = unsharpMask();
break;
default:
result = processUniform();
}
emit resultReady(result);
}
Mat LocalContrastEnhancer::processAdaptive(bool limitContrast)
{
float HIST_LIMIT = 1.0f;
if (limitContrast) {
HIST_LIMIT = 0.2 + _force * 0.8;
TILE_XCOUNT = 6;
TILE_YCOUNT = 6;
}
uchar *map = new uchar[256 * TILE_XCOUNT * TILE_YCOUNT];
Mat result;
int w = _image.cols;
int h = _image.rows;
// each tile is (2 * dx + 1) * (2 * dy + 1)
float tileWidth = (w - 1.0f) / (TILE_XCOUNT - 1);
float tileHeight = (h - 1.0f) / (TILE_YCOUNT - 1);
int dx = (tileWidth - 1) / 2;
int dy = (tileHeight - 1) / 2;
copyMakeBorder(_image, result, dy, dy, dx, dx, BORDER_REFLECT101 | BORDER_ISOLATED);
int tile = 0; // current tile
for (float x = dx; x < result.cols - dx; x += tileWidth) {
for (float y = dy; y < result.rows - dy; y += tileHeight) {
Rect r(x - dx, y - dy, 2 * dx + 1, 2 * dy + 1);
Mat m = result(r);
uchar *pmap = map + tile * 256;
Utils::createMap(m, pmap, limitContrast, HIST_LIMIT);
tile++;
}
}
result = _image.clone();
uchar *data = (uchar*)result.data;
#pragma omp parallel for
for (int i = 0; i < w - 1; i++) {
for (int j = 0; j < h - 1; j++) {
// tiles indices
int idx = i / tileWidth;
int idy = j / tileHeight;
int ul = idx * TILE_YCOUNT + idy;
int ur = (idx + 1) * TILE_YCOUNT + idy;
int bl = idx * TILE_YCOUNT + idy + 1;
int br = (idx + 1) * TILE_YCOUNT + idy + 1;
uchar val = data[j * w + i];
if (val > 0) {
uchar val_ul = map[256 * ul + val];
uchar val_ur = map[256 * ur + val];
uchar val_bl = map[256 * bl + val];
uchar val_br = map[256 * br + val];
float x1 = idx * tileWidth;
float y1 = idy * tileHeight;
float x2 = (idx + 1) * tileWidth;
float y2 = (idy + 1) * tileHeight;
val = 1.0f / (x2 - x1) / (y2 - y1) *
(val_ul * (x2 - i) * (y2 - j) +
val_ur * (i - x1) * (y2 - j) +
val_bl * (x2 - i) * (j - y1) +
val_br * (i - x1) * (j - y1));
}
data[j * w + i] = val;
}
}
delete[] map;
return result;
}
Mat LocalContrastEnhancer::processUniform()
{
Mat result = _image.clone();
uchar map[256];
Utils::createMap(_image, map);
Utils::applyMap(map, result);
return result;
}