使用したライブラリ
Q.17. Laplacianフィルタ
Laplacianフィルタを実装せよ。
Laplacian(ラプラシアン)フィルタとは輝度の二次微分をとることでエッジ検出を行うフィルタである。
ラプラシアンフィルタは使ったことないです。ラプラシアンの差分近似自体は計算したことがあるので省略します。これもカーネルを変えるだけですね。ここらへんはフィルタ地獄ですね。早く抜け出したい・・・。
int main()
{
PPM ppm("imori.pnm");
int width = ppm.Get_width();
int height = ppm.Get_height();
PPM ppm2(width, height);
auto kernel = [&](int i, int j)
{
double ret = 0;
if (i == 0 && j == 0) ret = -4;
if (i * j == 0 && (abs(i) == 1 || abs(j) == 1)) ret = 1;
return ret;// / 16.;
};
auto conv = [&](const std::vector<std::vector<double>>& f)
{
std::vector < std::vector < double >> ret(width, std::vector<double>(height));
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
ret[i][j] = 0;
}
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
int sum = 0;
for (int di = -1; di <= 1; di++)
for (int dj = -1; dj <= 1; dj++)
{
if (i - di >= 0 && i - di < width && j - dj >= 0 && j - di < height)
{
ret[i][j] += kernel(di, dj) * f[i - di][j - dj];
sum += kernel(di, dj);
}
}
//ret[i][j] /= (double)sum;
}
return ret;
};
std::vector < std::vector < double >> arry(width, std::vector<double>(height));
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
int r = ppm(i, j, 'r');
int g = ppm(i, j, 'g');
int b = ppm(i, j, 'b');
int y = (std::round)(0.2126 * r + 0.7152 * g + 0.0722 * b);
arry[i][j] = y;
}
arry = conv(arry);
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
int val = abs(arry[i][j]);
if (val > 255) val = 255;
ppm2(i, j, 'r') = val;
ppm2(i, j, 'g') = val;
ppm2(i, j, 'b') = val;
}
ppm2.Flush("out.ppm");
return 0;
}