mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2024-12-27 15:44:12 +08:00
104 lines
2.5 KiB
C++
104 lines
2.5 KiB
C++
|
|
typedef struct
|
|
{
|
|
BYTE b;
|
|
BYTE g;
|
|
BYTE r;
|
|
} RGB;
|
|
|
|
int calculateOtsuThreshold(const std::vector<uint8_t> &grayscaleImage)
|
|
{
|
|
int histogram[256] = {0};
|
|
int totalPixels = grayscaleImage.size();
|
|
|
|
for (int i = 0; i < totalPixels; ++i)
|
|
{
|
|
histogram[grayscaleImage[i]]++;
|
|
}
|
|
|
|
float maxVariance = 0.0f;
|
|
int threshold = 0;
|
|
|
|
for (int t = 0; t < 256; ++t)
|
|
{
|
|
int w0 = 0;
|
|
int w1 = 0;
|
|
int sum0 = 0;
|
|
int sum1 = 0;
|
|
|
|
for (int i = 0; i < 256; ++i)
|
|
{
|
|
if (i <= t)
|
|
{
|
|
w0 += histogram[i];
|
|
sum0 += i * histogram[i];
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
if (variance > maxVariance)
|
|
{
|
|
maxVariance = variance;
|
|
threshold = t;
|
|
}
|
|
}
|
|
|
|
return threshold;
|
|
}
|
|
DECLARE_API bool otsu_binary(const void *image, int thresh)
|
|
{
|
|
auto imageptr = (uintptr_t)image;
|
|
BITMAPFILEHEADER *fileHeader = (BITMAPFILEHEADER *)imageptr;
|
|
imageptr += sizeof(BITMAPFILEHEADER);
|
|
BITMAPINFOHEADER *infoHeader = (BITMAPINFOHEADER *)imageptr;
|
|
imageptr += sizeof(BITMAPINFOHEADER);
|
|
|
|
int height, weight;
|
|
height = infoHeader->biHeight;
|
|
weight = infoHeader->biWidth;
|
|
if (infoHeader->biBitCount == 24)
|
|
{
|
|
int size = height * weight;
|
|
RGB *img = (RGB *)imageptr;
|
|
int threshold;
|
|
if (thresh == -1)
|
|
{
|
|
std::vector<uint8_t> grayscaleImage;
|
|
|
|
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);
|
|
}
|
|
else
|
|
{
|
|
threshold = thresh;
|
|
}
|
|
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;
|
|
}
|
|
else
|
|
{
|
|
img[i].r = img[i].g = img[i].b = 0;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
} |