-
Notifications
You must be signed in to change notification settings - Fork 0
/
multithresh_new.cpp
211 lines (174 loc) · 6.75 KB
/
multithresh_new.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
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#define GRAYSCALE 256
using namespace cv;
using namespace std;
// Name - Huzaifa
// lookupTables() builds lookup tables which will be used in the Otsu's algorithm
// - > Input Parameters - nb[i][j] This is the sum of the probabilties from i to j
// mu[i][j] This is the sum of product of k with the probability of k
// sigma[i][j] This is the sub-variance of the class from i to j
// prob[i] is the probability of the pixel value i
// - > Output Parameters -None
// findMaxSigma() finds the maximum between class variance for each possible class partition
// - > Input Parameters - level gives the number of classes the partition must have
// sigma[i][j] This is the sub-variance of the class from i to j
// t[] is the threshold values returned from the function
// - > Output Parameters -maxSigma is the maximum between class variance
// multithresh( Mat img, int N) calls the above two functions to calculate the threshold values
// -> Input Parameters - img is the Mat image whose threshold is to be calculated
// N is the number of threshold values that it is supposed to determine
// -> Output Parameters - v is the vector of integers which contains the threshold values
// Sources - http://www.iis.sinica.edu.tw/JISE/2001/200109_01.pdf
void LookupTables(double nb[GRAYSCALE][GRAYSCALE], double mu[GRAYSCALE][GRAYSCALE], double sigma[GRAYSCALE][GRAYSCALE], double prob[GRAYSCALE]) // initialize
{
for (int j=0; j < GRAYSCALE; j++) // Initializing the lookup table
for (int i=0; i < GRAYSCALE; ++i)
{
nb[i][j] = 0.0;
mu[i][j] = 0.0;
sigma[i][j] = 0.0;
}
for (int i=0; i < GRAYSCALE; ++i) // Determining the diagonal entries
{
nb[i][i] = prob[i];
mu[i][i] = (double) (i)*prob[i];
}
for (int i=0; i < GRAYSCALE-1; ++i) // Determining the first row (row 0 is the first row)
{
nb[0][i+1] = nb[0][i] + prob[i+1];
mu[0][i+1] = mu[0][i] + (double) ((i+1))*prob[i+1];
}
for (int i=1; i < GRAYSCALE; i++) // using row 0 to calculate others
for (int j=i; j < GRAYSCALE; j++)
{
nb[i][j] = nb[0][j] - nb[0][i-1];
mu[i][j] = mu[0][j] - mu[0][i-1];
}
for (int i=0; i < GRAYSCALE; ++i) // Determining the sub-variance for each class
for (int j=i+1; j < GRAYSCALE; j++)
{
if (nb[i][j] != 0)
sigma[i][j] = (mu[i][j]*mu[i][j])/nb[i][j];
else
sigma[i][j] = 0.0;
}
}
double findMaxSigma(int level, double sigma[GRAYSCALE][GRAYSCALE], int t[])
{
t[0] = 0;
double maxSig= 0.0; // Maximum between class variance
switch(level)
{
case 2: // For 1 threshold value
for (int i= 0; i < GRAYSCALE-level + 2; i++) // t1
{
double Sq = sigma[0][i] + sigma[i+1][255];
if (maxSig < Sq)
{
t[0] = i;
maxSig = Sq;
}
}
break;
case 3: // For 2 threshold values
for (int i= 0; i < GRAYSCALE-level + 2; i++) // t1
for (int j = i+1; j < GRAYSCALE-level + 3; j++) // t2
{
double Sq = sigma[0][i] + sigma[i+1][j] + sigma[j+1][255];
if (maxSig < Sq)
{
t[0] = i;
t[1] = j;
maxSig = Sq;
}
}
break;
case 4: // For 3 threshold values
for (int i= 0; i < GRAYSCALE-level + 2; i++) // t1
for (int j = i+1; j < GRAYSCALE-level + 3; j++) // t2
for (int k = j+1; k < GRAYSCALE-level + 4; k++) // t3
{
double Sq = sigma[0][i] + sigma[i+1][j] + sigma[j+1][k] + sigma[k+1][255];
if (maxSig < Sq)
{
t[0] = i;
t[1] = j;
t[2] = k;
maxSig = Sq;
}
}
break;
case 5: // For 4 threshold values
for (int i= 0; i < GRAYSCALE-level + 2; i++) // t1
for (int j = i+1; j < GRAYSCALE-level + 3; j++) // t2
for (int k = j+1; k < GRAYSCALE-level + 4; k++) // t3
for (int m = k+1; m < GRAYSCALE-level + 5; m++) // t4
{
double Sq = sigma[0][i] + sigma[i+1][j] + sigma[j+1][k] + sigma[k+1][m] + sigma[m+1][255];
if (maxSig < Sq)
{
t[0] = i;
t[1] = j;
t[2] = k;
t[3] = m;
maxSig = Sq;
}
}
break;
}
return maxSig;
}
vector<int> multithresh(Mat img, int N)
{
vector<int> v;
Mat img2 = Mat(img.rows, img.cols, CV_8UC1);
if( img.empty()) // Error check: If image file exists or not
{
cout<< "File could not be found" <<endl;
return v;
}
if( img.channels() > 1) // Converting RGB image to Gray image
cvtColor(img, img2, CV_BGR2GRAY);
else
img2 = img;
int hist[GRAYSCALE]; // Histogram of the pixel values
double prob[GRAYSCALE]; // Probability of pixel value
for(int i = 0 ; i < GRAYSCALE; i++) // initializes the histogram to zero
hist[i] = 0;
for(int i = 0; i < img2.rows; i++) // Creates the histogram
for(int j = 0; j < img2.cols; j++)
hist[ img2.at<uchar>(i,j) ]++;
double size = img2.rows * img2.cols; //Total number of pixels
for(int i = 0; i < GRAYSCALE; i++) // Creating the probabilty array
prob[i] = (double) (hist[i]/size);
int thresh[5];
double nb[GRAYSCALE][GRAYSCALE], mu[GRAYSCALE][GRAYSCALE], sigma[GRAYSCALE][GRAYSCALE]; //
LookupTables(nb,mu,sigma,prob); // Creating the lookup tables
findMaxSigma(N+1, sigma, thresh); // Using the lookup tables to find the maximum between class variance
v = vector<int>(thresh, thresh + sizeof thresh / sizeof thresh[0]); // creating vector from the array
return v;
}
vector<int> multithresh(Mat img)
{
return multithresh(img, 1);
}
int main(int argc, char** argv)
{
char* imageName = argv[1];
Mat image;
image = imread(imageName, 1); // Reads the image file
if(argc != 2 || !image.data) // Error check: If the file doesn't exist or the parameters to execute are present
{
printf("No image data.\n");
return -1;
}
vector<int> v = multithresh(image,3); // Calls the multithresh function and assigns the threshholds to v
for(int i = 0; i < 3; i++)
cout<<v[i]<<" ";
cout<<endl;
waitKey(0);
return 0;
}