104 lines
2.5 KiB
C++
Raw Normal View History

2024-11-05 15:46:45 +08:00
2024-01-08 23:37:00 +08:00
typedef struct
{
BYTE b;
BYTE g;
BYTE r;
2024-04-02 15:36:52 +08:00
} RGB;
2024-01-08 23:37:00 +08:00
2024-04-02 15:36:52 +08:00
int calculateOtsuThreshold(const std::vector<uint8_t> &grayscaleImage)
{
int histogram[256] = {0};
2024-01-08 23:37:00 +08:00
int totalPixels = grayscaleImage.size();
2024-04-02 15:36:52 +08:00
for (int i = 0; i < totalPixels; ++i)
{
2024-01-08 23:37:00 +08:00
histogram[grayscaleImage[i]]++;
}
float maxVariance = 0.0f;
int threshold = 0;
2024-04-02 15:36:52 +08:00
for (int t = 0; t < 256; ++t)
{
2024-01-08 23:37:00 +08:00
int w0 = 0;
int w1 = 0;
int sum0 = 0;
int sum1 = 0;
2024-04-02 15:36:52 +08:00
for (int i = 0; i < 256; ++i)
{
if (i <= t)
{
2024-01-08 23:37:00 +08:00
w0 += histogram[i];
sum0 += i * histogram[i];
}
2024-04-02 15:36:52 +08:00
else
{
2024-01-08 23:37:00 +08:00
w1 += histogram[i];
sum1 += i * histogram[i];
}
}
float mean0 = (w0 == 0) ? 0 : static_cast<float>(sum0) / w0;
float mean1 = (w1 == 0) ? 0 : static_cast<float>(sum1) / w1;
float variance = static_cast<float>(w0 * w1) * pow(mean0 - mean1, 2);
2024-04-02 15:36:52 +08:00
if (variance > maxVariance)
{
2024-01-08 23:37:00 +08:00
maxVariance = variance;
threshold = t;
}
}
return threshold;
2024-04-02 15:36:52 +08:00
}
2024-11-05 15:46:45 +08:00
DECLARE_API bool otsu_binary(const void *image, int thresh)
2024-04-02 15:36:52 +08:00
{
auto imageptr = (uintptr_t)image;
BITMAPFILEHEADER *fileHeader = (BITMAPFILEHEADER *)imageptr;
imageptr += sizeof(BITMAPFILEHEADER);
BITMAPINFOHEADER *infoHeader = (BITMAPINFOHEADER *)imageptr;
imageptr += sizeof(BITMAPINFOHEADER);
2024-01-08 23:37:00 +08:00
int height, weight;
height = infoHeader->biHeight;
weight = infoHeader->biWidth;
if (infoHeader->biBitCount == 24)
{
int size = height * weight;
2024-04-02 15:36:52 +08:00
RGB *img = (RGB *)imageptr;
2024-01-08 23:37:00 +08:00
int threshold;
2024-04-02 15:36:52 +08:00
if (thresh == -1)
{
std::vector<uint8_t> grayscaleImage;
2024-01-08 23:37:00 +08:00
2024-04-02 15:36:52 +08:00
for (int i = 0; i < size; i++)
{
grayscaleImage.push_back((BYTE)((img[i].r * 19595 + img[i].g * 38469 + img[i].b * 7472) >> 16));
}
threshold = calculateOtsuThreshold(grayscaleImage);
2024-01-08 23:37:00 +08:00
}
2024-04-02 15:36:52 +08:00
else
{
threshold = thresh;
2024-01-08 23:37:00 +08:00
}
2024-04-02 15:36:52 +08:00
for (int i = 0; i < size; i++)
{
if ((BYTE)((img[i].r * 19595 + img[i].g * 38469 + img[i].b * 7472) >> 16) > threshold)
{
img[i].r = img[i].g = img[i].b = 255;
2024-01-08 23:37:00 +08:00
}
2024-04-02 15:36:52 +08:00
else
{
img[i].r = img[i].g = img[i].b = 0;
2024-01-08 23:37:00 +08:00
}
}
2024-04-02 15:36:52 +08:00
2024-01-08 23:37:00 +08:00
return true;
}
2024-04-02 15:36:52 +08:00
else
{
2024-01-08 23:37:00 +08:00
return false;
}
}