-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinar.cpp
155 lines (121 loc) · 5.15 KB
/
binar.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
#include "include/bitmapRW.h"
#include <iostream>
#define MIN_BRIGHTNESS 50
#define INPUT "../data/stars.bmp"
#define OUTPUT "../data/img2.bmp"
//TODO rewrite otsu properly
// Определение порога методом Оцу
int otsuThreshold(byte *pixels, uint32_t size)
{
// Проверки на NULL и проч. опустим, чтобы сконцетрироваться
// на работе метода
// Посчитаем минимальную и максимальную яркость всех пикселей
int min = pixels[0];
int max = pixels[0];
for (int i = 1; i < size; i+=3)
{
int value = pixels[i];
if (value < min)
min = value;
if (value > max)
max = value;
}
// Гистограмма будет ограничена снизу и сверху значениями min и max,
// поэтому нет смысла создавать гистограмму размером 256 бинов
int histSize = max - min + 1;
int* hist = new int[histSize];
// Заполним гистограмму нулями
for (int t = 0; t < histSize; t++)
hist[t] = 0;
// И вычислим высоту бинов
for (int i = 0; i < size; i+=3)
hist[pixels[i] - min]++;
// Введем два вспомогательных числа:
int m = 0; // m - сумма высот всех бинов, домноженных на положение их середины
int n = 0; // n - сумма высот всех бинов
for (int t = 0; t <= max - min; t++)
{
m += t * hist[t];
n += hist[t];
}
float maxSigma = -1; // Максимальное значение межклассовой дисперсии
int threshold = 0; // Порог, соответствующий maxSigma
int alpha1 = 0; // Сумма высот всех бинов для класса 1
int beta1 = 0; // Сумма высот всех бинов для класса 1, домноженных на положение их середины
// Переменная alpha2 не нужна, т.к. она равна m - alpha1
// Переменная beta2 не нужна, т.к. она равна n - alpha1
// t пробегается по всем возможным значениям порога
for (int t = 0; t < max - min; t++)
{
alpha1 += t * hist[t];
beta1 += hist[t];
// Считаем вероятность класса 1.
float w1 = (float)beta1 / n;
// Нетрудно догадаться, что w2 тоже не нужна, т.к. она равна 1 - w1
// a = a1 - a2, где a1, a2 - средние арифметические для классов 1 и 2
float a = (float)alpha1 / beta1 - (float)(m - alpha1) / (n - beta1);
// Наконец, считаем sigma
float sigma = w1 * (1 - w1) * a * a;
// Если sigma больше текущей максимальной, то обновляем maxSigma и порог
if (sigma > maxSigma)
{
maxSigma = sigma;
threshold = t;
}
}
// Не забудем, что порог отсчитывался от min, а не от нуля
threshold += min;
// Все, порог посчитан, возвращаем его наверх :)
return threshold;
}
int main(int argc, char *argv[]) {
byte *pixels;
int32_t width;
int32_t height;
uint32_t bytesPerPixel;
clock_t start, end;
start = clock();
char* input = argv[1];
char* output = argv[2];
ReadImage(input, &pixels, &width, &height, &bytesPerPixel);
byte threshold = otsuThreshold(pixels, width*height);
//printf("%d\n", threshold);
for (int64_t i = 0; i < (uint64_t) width*height*bytesPerPixel; i+=bytesPerPixel) {
byte r, g, b;
b = pixels[i];
g = pixels[i+1];
r = pixels[i+2];
double brightness = (0.2989*r+0.5870*g+0.1140*b);
//int brightness = r+g+b;
//if (brightness < 64)
if (brightness < threshold)
{
pixels[i] = 0;
pixels[i+1] = 0;
pixels[i+2] = 0;
}
else {
pixels[i] = 0xff;
pixels[i+1] = 0xff;
pixels[i+2] = 0xff;
}
}
WriteImage(output, pixels, width, height, bytesPerPixel);
end = clock();
double runtime = double(end - start) / double(CLOCKS_PER_SEC);
printf("%f\n", runtime);
//Даня, это тебе
byte* pixel_data_bin;
pixel_data_bin = (byte*) malloc(width * height);
int64_t j = 0;
int64_t i = 0;
while (i < (uint64_t) width*height*bytesPerPixel){
pixel_data_bin[j] = pixels[i];
i+=bytesPerPixel;
j++;
}
//теперь в pixel_data_bin хранятся последовательно пиксели (из правого нижнего угла в левый верхний (sic!))
//его можно использовать дальше или записать в любой файл ("wb")
free(pixel_data_bin);
free(pixels);
}