使用したライブラリ
Q.22. ヒストグラム操作
ヒストグラムの平均値をm0=128、標準偏差をs0=52になるように操作せよ。
これはヒストグラムのダイナミックレンジを変更するのではなく、ヒストグラムを平坦に変更する操作である。
平均値m、標準偏差s、のヒストグラムを平均値m0, 標準偏差s0に変更するには、次式によって変換する。
線形変換で所望の統計量を持つように変換するだけです。負の値や256以上の値が出てしまうのでそれぞれ0,255にします。
int main()
{
PPM ppm("imori_dark.pnm");
int width = ppm.Get_width();
int height = ppm.Get_height();
int N = 256;
std::vector<int> hist(N);
for (int n = 0; n < N; n++)
{
hist[n] = 0;
}
double m = 0;
double m2 = 0;
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
m += ppm(i, j, 'r');
m += ppm(i, j, 'g');
m += ppm(i, j, 'b');
m2 += ppm(i, j, 'r')* ppm(i, j, 'r');
m2 += ppm(i, j, 'g')* ppm(i, j, 'g');
m2 += ppm(i, j, 'b')* ppm(i, j, 'b');
}
m /= (double)(width * height * 3);
m2 /= (double)(width * height * 3);
double s2 = m2 - m * m;
double s = sqrt(s2);
PPM ppm2(width, height);
double m0 = 128;
double s0 = 52;
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
double a;
a = s0 / s * (ppm(i, j, 'r') - m) + m0;
if (a < 0) a = 0;
else if (a >= N) a = N - 1;
ppm2(i, j, 'r') = a;
hist[a]++;
a = s0 / s * (ppm(i, j, 'g') - m) + m0;
if (a < 0) a = 0;
else if (a >= N) a = N - 1;
ppm2(i, j, 'g') = a;
hist[a]++;
a = s0 / s * (ppm(i, j, 'b') - m) + m0;
if (a < 0) a = 0;
else if (a >= N) a = N - 1;
ppm2(i, j, 'b') = a;
hist[a]++;
}
for (int n = 0; n < N; n++)
{
std::cout << n << " " << hist[n] << std::endl;
}
ppm2.Flush("out.ppm");
return 0;
}