1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【画像処理100本ノックに挑戦】Q.19. LoGフィルタ

Posted at

使用したライブラリ

【画像処理100本ノック】独自の画像入出力クラスを作る

Q.19. LoGフィルタ

LoGフィルタ(sigma=3、カーネルサイズ=5)を実装し、imori_noise.jpgのエッジを検出せよ。
LoGフィルタとはLaplacian of Gaussianであり、ガウシアンフィルタで画像を平滑化した後にラプラシアンフィルタで輪郭を取り出すフィルタである。
Laplcianフィルタは二次微分をとるのでノイズが強調されるのを防ぐために、予めGaussianフィルタでノイズを抑える。

畳み込みの式の微分を考えれば、この場合カーネルを二階微分してから畳み込めばよいことがわかります。

int main()
{
	PPM ppm("imori_noise.pnm");
	int width = ppm.Get_width();
	int height = ppm.Get_height();
	PPM ppm2(width, height);

	auto kernel = [&](int i, int j)
	{
		double ret = 0;
		double sigma = 3, pi = 3.141592653589793;;
		if (abs(i) <= 2 && abs(j) <= 2)
		{
			double x = i, y = j;
			ret = (x * x + y * y - sigma * sigma) / (2. * pi * sigma * sigma * sigma * sigma * sigma * sigma) * exp(-(x*x + y*y) / (2. * sigma * sigma));
		}
		return ret;
		
	};

	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++)
			{
				double sum = 0;
				for (int di = -2; di <= 2; di++)
					for (int dj = -2; dj <= 2; 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] /= sum;
				//std::cout << sum << std::endl;
			}
		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;
}

imori_noise.png out.png
ぼかしが入っているので、あまりエッジが抽出出来ていない。何に使うのだ?
とにかくこれでフィルタ地獄から抜け出しました!ここからしばらくはヒストグラム操作みたいですね。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?