Skip to content

Commit 8b0cf07

Browse files
authored
Merge pull request #151 from Matthewlele/master
operators Ancuti10, Song14, Ancuti11, Hsin11 and Tao18(not working)
2 parents 6f0dbb9 + 64e7d11 commit 8b0cf07

18 files changed

+1728
-311
lines changed

CMakeLists.txt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@ add_subdirectory(TMOChen05/) #Matus Bicanovsky
4545
#add_subdirectory(TMOMantiuk08/) #Matus Bicanovsky
4646
add_subdirectory(TMOAncuti10/) #Matus Bicanovsky
4747
add_subdirectory(TMOSong14/) #Matus Bicanovsky
48-
add_subdirectory(TMOTao18/) #Matus Bicanovsky
48+
#add_subdirectory(TMOTao18/) #Matus Bicanovsky - not working
4949
add_subdirectory(TMOQueiroz06/) #Peter Zdravecký
5050
add_subdirectory(TMOAlsam20/) #Peter Zdravecký
51-
add_subdirectory(TMOLiu15/) #Peter Zdravecký
52-
add_subdirectory(TMOLiu17/) #Peter Zdravecký
51+
#add_subdirectory(TMOLiu15/) #Peter Zdravecký
52+
#add_subdirectory(TMOLiu17/) #Peter Zdravecký
5353
add_subdirectory(TMOLiu16/) #Jakub Krystufek
54+
add_subdirectory(TMOAncuti11/) #Matus Bicanovsky
55+
add_subdirectory(TMOHsin11/) #Matus Bicanovsky
5456
#add_subdirectory(TMOYourOperatorNameLinux/)
5557
#add_subdirectory(TMOJin14/) #
5658
add_subdirectory(TMOLee10/) #Martin Molek
@@ -62,16 +64,16 @@ add_subdirectory(TMOBiswas05/) #Tomas Chlubna
6264
add_subdirectory(TMOXiong17/) #Filip Brezna: method 1
6365
add_subdirectory(TMOZhongping15/) #Filip Brezna: method 2
6466
#add_subdirectory(TMOJin17/) #Filip Brezna: method 3
65-
#add_subdirectory(TMOHu14/) #Vladimir Vlkovic
67+
add_subdirectory(TMOHu14/) #Vladimir Vlkovic
6668
#add_subdirectory(TMOTao17/) #Vladimir Vlkovic not ready
6769
#add_subdirectory(TMOSon14/) #Sedlar Pavel, Tomas Hudziec
6870
add_subdirectory(TMOCLAHE/) #Sedlar Pavel
6971
#add_subdirectory(TMOKuhn08/) #Pavel Melcer
7072
add_subdirectory(TMOEisemann04/) #Roman Jaska
7173
add_subdirectory(TMOTai08/) #Michal Vlnas
7274
#add_subdirectory(TMONguy15/) #Matej Valek
73-
add_subdirectory(TMOWu24/) #Filip Sapak
74-
add_subdirectory(TMOWu24_2/) #Branislav Dubec
75+
#add_subdirectory(TMOWu24/) #Filip Sapak
76+
#add_subdirectory(TMOWu24_2/) #Branislav Dubec
7577
add_subdirectory(TMONafchi17) #Tomas Krivanek
7678
add_subdirectory(TMONafchi17_2/) #Boris Strbak
7779
add_subdirectory(TMOMikamo14/) #Jan Findra

TMOAncuti10/CMakeLists.txt:Zone.Identifier

Whitespace-only changes.

TMOAncuti10/TMOAncuti10.cpp

Lines changed: 111 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -23,123 +23,16 @@
2323
* --------------------------------------------------------------------------- */
2424
TMOAncuti10::TMOAncuti10()
2525
{
26-
SetName(L"Ancuti10"); // TODO - Insert operator name
27-
SetDescription(L"Add your TMO description here"); // TODO - Insert description
28-
29-
dParameter.SetName(L"ParameterName"); // TODO - Insert parameters names
30-
dParameter.SetDescription(L"ParameterDescription"); // TODO - Insert parameter descriptions
31-
dParameter.SetDefault(1); // TODO - Add default values
32-
dParameter = 1.;
33-
dParameter.SetRange(-1000.0, 1000.0); // TODO - Add acceptable range if needed
34-
this->Register(dParameter);
26+
SetName(L"Ancuti10");
27+
SetDescription(L"Color to grayscale operator for images and video, method from paper: Image and Video Decolorization by Fusion");
3528
}
3629

3730
TMOAncuti10::~TMOAncuti10()
3831
{
3932
}
40-
//function to conver RGB to HSL color space, inputs are R, G, B values in the range [0, 255] and outputs are H, S, L values in the range [0, 1]
41-
void TMOAncuti10::convertRGBtoHSL(double R, double G, double B, double &H, double &S, double &L)
42-
{
43-
//normalize RGB values
44-
R /= 255.0;
45-
G /= 255.0;
46-
B /= 255.0;
47-
//find the maximum and minimum values of R, G, B
48-
double max = std::max({R, G, B});
49-
double min = std::min({R, G, B});
50-
//calculate luminance
51-
L = (max + min) / 2.0;
52-
if(max == min){
53-
H = S = 0.0; //achromatic
54-
}
55-
else{
56-
double tmp = max - min;
57-
S = (L > 0.5) ? tmp / (2.0 - max - min) : tmp / (max + min);
58-
double del_R = (((max - R) / 6.0) + (tmp / 2.0)) / tmp;
59-
double del_G = (((max - G) / 6.0) + (tmp / 2.0)) / tmp;
60-
double del_B = (((max - B) / 6.0) + (tmp / 2.0)) / tmp;
61-
if(R == max)
62-
H = del_B - del_G;
63-
else if(G == max)
64-
H = (1.0 / 3.0) + del_R - del_B;
65-
else if(B == max)
66-
H = (2.0 / 3.0) + del_G - del_R;
67-
if(H < 0.0)
68-
H += 1.0;
69-
if(H > 1.0)
70-
H -= 1.0;
71-
}
72-
}
73-
//function to convert RGB to XYZ color space, inputs are R, G, B values in the range [0, 255] and outputs are X, Y, Z values in the range [0, 100]
74-
void TMOAncuti10::convertRGBtoXYZ(double R, double G, double B, double &X, double &Y, double &Z)
75-
{
76-
//normalize RGB values
77-
R /= 255.0;
78-
G /= 255.0;
79-
B /= 255.0;
80-
//apply gamma correction
81-
R = (R > 0.04045) ? pow((R + 0.055) / 1.055, 2.4) : R / 12.92;
82-
G = (G > 0.04045) ? pow((G + 0.055) / 1.055, 2.4) : G / 12.92;
83-
B = (B > 0.04045) ? pow((B + 0.055) / 1.055, 2.4) : B / 12.92;
84-
//multiply by 100 to scale
85-
R *= 100.0;
86-
G *= 100.0;
87-
B *= 100.0;
88-
//convert RGB to XYZ using D65 illuminant
89-
X = R * 0.4124564 + G * 0.3575761 + B * 0.1804375;
90-
Y = R * 0.2126729 + G * 0.7151522 + B * 0.0721750;
91-
Z = R * 0.0193339 + G * 0.1191920 + B * 0.9503041;
92-
}
93-
//function to convert XYZ to CIELAB color space, inputs are X, Y, Z values in the range [0, 100]
94-
void TMOAncuti10::convertXYZtoCIELAB(double X, double Y, double Z, double &L, double &a, double &b)
95-
{
96-
//reference white points
97-
const double ref_X = 95.047;
98-
const double ref_Y = 100.000;
99-
const double ref_Z = 108.883;
100-
//normalize XYZ values
101-
X /= ref_X;
102-
Y /= ref_Y;
103-
Z /= ref_Z;
104-
//apply CIE-L*ab transformation
105-
X = (X > 0.008856) ? pow(X, 1.0 / 3.0) : (7.787 * X) + (16.0 / 116.0);
106-
Y = (Y > 0.008856) ? pow(Y, 1.0 / 3.0) : (7.787 * Y) + (16.0 / 116.0);
107-
Z = (Z > 0.008856) ? pow(Z, 1.0 / 3.0) : (7.787 * Z) + (16.0 / 116.0);
108-
109-
L = (116.0 * Y) - 16.0;
110-
a = 500.0 * (X - Y);
111-
b = 200.0 * (Y - Z);
112-
}
113-
//function to convert CIELAB to CIELCh color space, inputs are L, a, b values and outputs are C, h values
114-
void TMOAncuti10::convertCIELABtoCIELCh(double L, double a, double b, double &C, double &h)
115-
{
116-
C = sqrt(a * a + b * b);
117-
double var_h = atan2(b, a);
118-
if (var_h > 0)
119-
var_h = (var_h / M_PI) * 180.0;
120-
else
121-
var_h = 360 - (abs(var_h) / M_PI) * 180.0;
122-
h = var_h;
123-
}
124-
//function to compute L_HK value, inputs are L, C, h values
125-
double TMOAncuti10::computeL_HK(double L, double C, double H)
126-
{
127-
return L + (2.5 - 0.025 * L)*(0.116 * fabs(sin((H-90)/2)) + 0.085) * C; //formula from the paper
128-
}
12933

130-
//function to calculate average pixel value, inputs are channel data, width and height
131-
double TMOAncuti10::calculateAMPV(double* channel, int width, int height)
132-
{
133-
double sum = 0.0;
134-
int totalCount = width * height;
135-
for (int i = 0; i < totalCount; i++)
136-
{
137-
sum += channel[i];
138-
}
139-
return sum / totalCount;
140-
}
14134

142-
//function to apply separable binomial kernel, inputs are input data, output data, width and height
35+
//function to apply separable binomial kernel
14336
void TMOAncuti10::applySeparableBinomialKernel(double* input, double* output, int width, int height)
14437
{
14538
double kernel[5] = {1.0, 4.0, 6.0, 4.0, 1.0}; // 1D kernel
@@ -175,13 +68,13 @@ void TMOAncuti10::applySeparableBinomialKernel(double* input, double* output, in
17568
//function to compute saliency map, inputs are channel data, width and height and output is saliency map
17669
void TMOAncuti10::computeSaliencyMap(double* channel, double* saliencyMap, int width, int height)
17770
{
178-
double meanValue = calculateAMPV(channel, width, height); // mean value of the channel
71+
double meanValue = calculateAPV(channel, width, height); // mean value of the channel
17972
double* blurredChannel = new double[width * height];
18073
applySeparableBinomialKernel(channel, blurredChannel, width, height);
18174
//compute map
18275
for (int i = 0; i < width * height; i++)
18376
{
184-
saliencyMap[i] = fabs(meanValue - blurredChannel[i]);
77+
saliencyMap[i] = fabs(meanValue - blurredChannel[i]); //paper equation (2)
18578
}
18679
delete[] blurredChannel;
18780
}
@@ -194,7 +87,7 @@ void TMOAncuti10::computeExposednessMap(double* channel, double* exposednessMap,
19487

19588
for(int i = 0; i < width * height; i++)
19689
{
197-
exposednessMap[i] = exp(- ((channel[i] - 0.5) * (channel[i] - 0.5)/(sigma2))); //formula from the paper
90+
exposednessMap[i] = exp(- ((channel[i] - 0.5) * (channel[i] - 0.5)/(sigma2))); //formula from the paper, equation (3)
19891
}
19992
}
20093

@@ -205,7 +98,7 @@ void TMOAncuti10::computeChromaticMap(double* channel, double* chromaticMap, dou
20598
//compute chromatic map
20699
for (int i = 0; i < totalCount; i++)
207100
{
208-
chromaticMap[i] = fabs(channel[i] - saturation[i]);
101+
chromaticMap[i] = fabs(channel[i] - saturation[i]) / sqrt(2.0);
209102
}
210103
}
211104

@@ -259,7 +152,7 @@ void TMOAncuti10::fusePyramids(const std::vector<std::vector<cv::Mat>>& laplacia
259152
for(int i = 0; i < levels; i++){
260153
fusedPyramid[i] = cv::Mat::zeros(laplacianPyramids[0][i].size(), laplacianPyramids[0][i].type()); //initialize the output pyramid
261154
for(int k = 0; k < laplacianPyramids.size(); k++){
262-
fusedPyramid[i] += gaussianPyramids[k][i].mul(laplacianPyramids[k][i]); //fuse the pyramids according to the formula in paper
155+
fusedPyramid[i] += gaussianPyramids[k][i].mul(laplacianPyramids[k][i]); //fuse the pyramids according to the formula in paper, equation (5)
263156
}
264157
}
265158
}
@@ -276,25 +169,13 @@ cv::Mat TMOAncuti10::reconstructFromPyramid(const std::vector<cv::Mat>& pyramid)
276169
return current;
277170
}
278171

279-
280-
281-
/* --------------------------------------------------------------------------- *
282-
* This overloaded function is an implementation of your tone mapping operator *
283-
* --------------------------------------------------------------------------- */
172+
//main function of the c2g operator
284173
int TMOAncuti10::Transform()
285174
{
286-
// Source image is stored in local parameter pSrc
287-
// Destination image is in pDst
288-
289-
// Initialy images are in RGB format, but you can
290-
// convert it into other format
291-
//pSrc->Convert(TMO_Yxy); // This is format of Y as luminance
292-
//pDst->Convert(TMO_Yxy); // x, y as color information
293175

294176
double *pSourceData = pSrc->GetData(); // You can work at low level data
295177
double *pDestinationData = pDst->GetData(); // Data are stored in form of array
296-
// of three doubles representing
297-
// three colour components
178+
298179
int width = pSrc->GetWidth();
299180
int height = pSrc->GetHeight();
300181
double *R_Channel = new double[width * height];
@@ -313,10 +194,12 @@ int TMOAncuti10::Transform()
313194
//compute HKL channel
314195
for (int i = 0; i < width * height; i++)
315196
{
197+
//firstly we need to convert RGB intput into CIELch color space, that is done as RGB -> XYZ -> CIELab -> CIELch
316198
double X, Y, Z, L, a, b, C, h;
317199
convertRGBtoXYZ(R_Channel[i], G_Channel[i], B_Channel[i], X, Y, Z);
318200
convertXYZtoCIELAB(X, Y, Z, L, a, b);
319201
convertCIELABtoCIELCh(L, a, b, C, h);
202+
//then we compute the L_hk channel frame
320203
HKL_Channel[i] = computeL_HK(L, C, h);
321204
}
322205
double *saliencyMapR = new double[width * height];
@@ -416,40 +299,29 @@ int TMOAncuti10::Transform()
416299
computeGaussianPyramid(finalWeightMaps[i], gaussianPyramids[i], levels);
417300
}
418301
fprintf(stderr, "Gaussian pyramids computed\n");
419-
//ensure the sizes of the pyramids match
420-
for (int l = 0; l < levels; l++) {
421-
for (int k = 0; k < inputs.size(); k++) {
422-
if (laplacianPyramids[k][l].size() != gaussianPyramids[k][l].size()) {
423-
fprintf(stderr, "Error: Pyramid sizes do not match at level %d for input %d\n", l, k);
424-
return -1;
425-
}
426-
}
427-
}
428-
fprintf(stderr, "Pyramid sizes match\n");
429302
//fuse the pyramids
430303
std::vector<cv::Mat> fusedPyramid;
431304
fusePyramids(laplacianPyramids, gaussianPyramids, fusedPyramid);
432305
//reconstruct the final image from the fused pyramid
433306
fprintf(stderr, "Pyramids fused\n");
434307
cv::Mat fusedImage = reconstructFromPyramid(fusedPyramid);
435308
fprintf(stderr, "Image reconstructed\n");
436-
cv::normalize(fusedImage, fusedImage, 0, 255, cv::NORM_MINMAX);
437-
fusedImage.convertTo(fusedImage, CV_32F);
438-
fprintf(stderr, "Reconstruction done\n");
309+
cv::normalize(fusedImage, fusedImage, 0, 1, cv::NORM_MINMAX);
310+
fprintf(stderr, "Reconstruction done.\n");
439311

440312

441313
double pY, px, py;
442314
int j = 0;
443315
for (j = 0; j < pSrc->GetHeight(); j++)
444316
{
445-
pSrc->ProgressBar(j, pSrc->GetHeight()); // You can provide progress bar
317+
pSrc->ProgressBar(j, pSrc->GetHeight());
446318
for (int i = 0; i < pSrc->GetWidth(); i++)
447319
{
448320

449-
float pixel = fusedImage.at<float>(j, i);
450-
*pDestinationData++ = pixel / 255.0;
451-
*pDestinationData++ = pixel / 255.0;
452-
*pDestinationData++ = pixel / 255.0;
321+
double pixel = fusedImage.at<double>(j, i);
322+
*pDestinationData++ = pixel;
323+
*pDestinationData++ = pixel;
324+
*pDestinationData++ = pixel;
453325
}
454326
}
455327
pSrc->ProgressBar(j, pSrc->GetHeight());
@@ -474,3 +346,95 @@ int TMOAncuti10::Transform()
474346
delete[] saturation;
475347
return 0;
476348
}
349+
350+
//function to conver RGB to HSL color space
351+
void TMOAncuti10::convertRGBtoHSL(double R, double G, double B, double &H, double &S, double &L)
352+
{
353+
//find the maximum and minimum values of R, G, B
354+
double max = std::max({R, G, B});
355+
double min = std::min({R, G, B});
356+
//calculate luminance
357+
L = (max + min) / 2.0;
358+
if(max == min){
359+
H = S = 0.0; //achromatic
360+
}
361+
else{
362+
double tmp = max - min;
363+
S = (L > 0.5) ? tmp / (2.0 - max - min) : tmp / (max + min);
364+
double del_R = (((max - R) / 6.0) + (tmp / 2.0)) / tmp;
365+
double del_G = (((max - G) / 6.0) + (tmp / 2.0)) / tmp;
366+
double del_B = (((max - B) / 6.0) + (tmp / 2.0)) / tmp;
367+
if(R == max)
368+
H = del_B - del_G;
369+
else if(G == max)
370+
H = (1.0 / 3.0) + del_R - del_B;
371+
else if(B == max)
372+
H = (2.0 / 3.0) + del_G - del_R;
373+
if(H < 0.0)
374+
H += 1.0;
375+
if(H > 1.0)
376+
H -= 1.0;
377+
}
378+
}
379+
//function to convert RGB to XYZ color space
380+
void TMOAncuti10::convertRGBtoXYZ(double R, double G, double B, double &X, double &Y, double &Z)
381+
{
382+
383+
// //apply gamma correction
384+
R = (R/255.0 > 0.04045) ? pow((R + 0.055) / 1.055, 2.4) : R / 12.92;
385+
G = (G/255.0 > 0.04045) ? pow((G + 0.055) / 1.055, 2.4) : G / 12.92;
386+
B = (B/255.0 > 0.04045) ? pow((B + 0.055) / 1.055, 2.4) : B / 12.92;
387+
388+
//convert RGB to XYZ using D65 illuminant
389+
X = R * 0.4124564 + G * 0.3575761 + B * 0.1804375;
390+
Y = R * 0.2126729 + G * 0.7151522 + B * 0.0721750;
391+
Z = R * 0.0193339 + G * 0.1191920 + B * 0.9503041;
392+
}
393+
//function to convert XYZ to CIELAB color space
394+
void TMOAncuti10::convertXYZtoCIELAB(double X, double Y, double Z, double &L, double &a, double &b)
395+
{
396+
//reference white points
397+
const double ref_X = 95.047;
398+
const double ref_Y = 100.000;
399+
const double ref_Z = 108.883;
400+
//normalize XYZ values
401+
X /= ref_X;
402+
Y /= ref_Y;
403+
Z /= ref_Z;
404+
405+
X = (X > 0.008856) ? pow(X, 1.0 / 3.0) : (7.787 * X) + (16.0 / 116.0);
406+
Y = (Y > 0.008856) ? pow(Y, 1.0 / 3.0) : (7.787 * Y) + (16.0 / 116.0);
407+
Z = (Z > 0.008856) ? pow(Z, 1.0 / 3.0) : (7.787 * Z) + (16.0 / 116.0);
408+
409+
L = (116.0 * Y) - 16.0;
410+
a = 500.0 * (X - Y);
411+
b = 200.0 * (Y - Z);
412+
}
413+
//function to convert CIELAB to CIELCh color space
414+
void TMOAncuti10::convertCIELABtoCIELCh(double L, double a, double b, double &C, double &h)
415+
{
416+
C = sqrt(a * a + b * b);
417+
double var_h = atan2(b, a);
418+
if (var_h > 0)
419+
var_h = (var_h / M_PI) * 180.0;
420+
else
421+
var_h = 360 - (abs(var_h) / M_PI) * 180.0;
422+
h = var_h;
423+
}
424+
//function to compute L_HK value for given pixel
425+
double TMOAncuti10::computeL_HK(double L, double C, double H)
426+
{
427+
return L + (2.5 - 0.025 * L)*(0.116 * fabs(sin((H-90)/2)) + 0.085) * C; //computation of L_hk value for one pixel based on equation (1)
428+
}
429+
430+
//function to calculate average pixel value
431+
double TMOAncuti10::calculateAPV(double* channel, int width, int height)
432+
{
433+
double sum = 0.0;
434+
int totalCount = width * height;
435+
for (int i = 0; i < totalCount; i++)
436+
{
437+
sum += channel[i];
438+
}
439+
return sum / totalCount;
440+
}

0 commit comments

Comments
 (0)