-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhisto_match.cpp
More file actions
168 lines (138 loc) · 3.83 KB
/
histo_match.cpp
File metadata and controls
168 lines (138 loc) · 3.83 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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// ========================================================
// histo_match.cpp - Histogram program.
//
// Written by: Christyn Vasquez
// ========================================================
#include "IP.h"
using namespace std;
void histo_match(imageP, int, imageP);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// main:
//
// Main routine for quantization of image.
//
int
main(int argc, char** argv)
{
int n;
imageP inImage, outImage;
// Checks image version
if (argc != 4) {
cerr << "Usage: histo_stretch infile t1 t2 outfile\n";
exit(1);
}
// Read input image and reserve space for output
inImage = IP_readImage(argv[1]);
outImage = NEWIMAGE;
// Read n number
n = atoi(argv[2]);
// Quantization image and save result in file
histo_match(inImage, n, outImage);
IP_saveImage(outImage, argv[3]);
// Free up image structures/memory
IP_freeImage(inImage);
IP_freeImage(outImage);
return 1;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// histo_match:
//
// Histogram used is determined by number
// 0 for flat histo
// + for exponential histo
//
//
void
histo_match(imageP inImage, int n, imageP outImage)
{
int i, R;
int left[MXGRAY], width[MXGRAY];
uchar *in, *out;
long total, Hsum, Havg, H[MXGRAY];
double bin[MXGRAY];
// Total number of pixels in image
total = (long)inImage->height * inImage->width;
// Interval value for equal histogram
Havg = total / MXGRAY;
//
if(n >= 0){
// Get Value of each bin.
for (int i = 0 ; i < MXGRAY; i++){
double base = (double) (i/(double) MXGRAY);
bin[i] = pow(base,n);
}
// Find the total_sum of histogram entries.
double total_sum = 0;
for (int i = 0; i < MXGRAY; i++){
total_sum += bin[i];
}
//divide each bin by total_sum.
for (int i = 0; i < MXGRAY; i++){
bin[i] = round(total * (bin[i]/total_sum));
}
}
else{
for (int i = 0 ; i < MXGRAY; i++){
double base = (double) (i/(double) MXGRAY);
bin[i] = pow(base,-n);
}
// Find the total_sum of histogram entries.
double total_sum = 0;
for (int i = 0; i < MXGRAY; i++){
total_sum += bin[i];
}
//divide each bin by total_sum.
for (int i = 0; i < MXGRAY; i++){
bin[i] = round(total * ((1 - bin[i])/total_sum));
}
}
// Init out image dimensions and buffer
outImage->width = inImage->width;
outImage->height = inImage->height;
outImage->image = (uchar *) malloc(total);
in = inImage->image; // input image buffer
out = outImage->image; // output image buffer
for(i = 0; i < MXGRAY; i++) H[i] = 0; // clear histogram
for(i = 0; i < total; i++) H[in[i]]++; // eval histogram
R = 0; // right end of interval
Hsum = 0; // cumulative value for interval
// evaluate remapping of all input gray levels;
// Each input gray value maps to an interval of valid
// output values. The endpoints of the intervals are
// left[] and left[]+width[].
if (n == 0){
for(i=0; i<MXGRAY; i++) {
left[i] = R; // left end of interval
Hsum += H[i]; // cum. interval value
// make interval wider, if necessary
while(Hsum>Havg && R<MXGRAY-1){
Hsum -= Havg; // adjust Hsum
R++; // update right end
}
// width of interval
width[i] = R - left[i] + 1;
}
}else{
for(i=0; i<MXGRAY; i++) {
left[i] = R; // left end of interval
Hsum += H[i]; // cum. interval value
// make interval wider, if necessary
while(Hsum>bin[R] && R<MXGRAY-1){
Hsum -= bin[R]; // adjust Hsum
R++; // update right end
}
// width of interval
width[i] = R - left[i] + 1;
}
}
// visit all input pixels and remap intensities
for(i=0; i<total; i++) {
if(width[in[i]] == 1) out[i] = left[in[i]];
else { // in[i] spills over into width[] possible values
// randomly pick R from 0 to width[in[i]]
R = ((rand()&0x7fff)*width[in[i]])>>15;
// add R to left end of interval
out[i] = left[in[i]] + R;
}
}
}