0
0

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 3 years have passed since last update.

【画像処理100本ノックに挑戦】Q.5. HSV変換

Posted at

使用したライブラリ

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

Q.5. HSV変換

HSV変換を実装して、色相Hを反転せよ。

定義式の通りに変換、逆変換するだけです。


struct HSV
{
	double h, s, v;
};
struct RGB
{
	RGB(int r, int g, int b)
	{
		this->r = r;
		this->g = g;
		this->b = b;
	}
	int r, g, b;
};

HSV RGB2HSV(const RGB &rgb)
{
	HSV hsv;
	int r = rgb.r;
	int g = rgb.g;
	int b = rgb.b;
	int Max = std::max({ r, g, b });
	int Min = std::min({r, g, b});
	if (Min == Max) hsv.h = 0;
	else if (Min == b) hsv.h = 60 * (g - r)  / (double)(Max - Min) + 60;
	else if (Min == r) hsv.h = 60 * (b - g)  / (double)(Max - Min) + 180;
	else if (Min == g) hsv.h = 60 * (r - b)  / (double)(Max - Min) + 300;
	hsv.v = Max / 255.;
	hsv.s = (Max - Min) / 255.;
	return hsv;
}
RGB HSV2RGB(const HSV& hsv)
{
	double r, g, b ;
	double h = hsv.h;
	double s = hsv.s;
	double v = hsv.v;
	double c = s;
	double h2 = h / 60.;
	double x = c * (1 - fabs( fmod(h2,2)  -1 ));
	
	if (0 <= h2 && h2 < 1) r = c, g = x, b = 0;
	else if (1 <= h2 && h2 < 2) r = x, g = c, b = 0;
	else if (2 <= h2 && h2 < 3) r = 0, g = c, b = x;
	else if (3 <= h2 && h2 < 4) r = 0, g = x, b = c;
	else if (4 <= h2 && h2 < 5) r = x, g = 0, b = c;
	else if (5 <= h2 && h2 < 6) r = c, g = 0, b = x;
	else r = g = b = 0;
	r += (v - c);
	g += (v - c);
	b += (v - c);
	
	return RGB(r*255,g*255,b*255);
}

int main()
{
	PPM ppm("imori.pnm");
	int width = ppm.Get_width();
	int height = ppm.Get_height();
	PPM ppm2(width, 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');
			
			HSV hsv = RGB2HSV(RGB(r, g, b));
			if (hsv.h > 180)hsv.h -= 180;
			else hsv.h += 180;
			
			RGB rgb = HSV2RGB(hsv);
			ppm2(i, j, 'r') = rgb.r;
			ppm2(i, j, 'g') = rgb.g;
			ppm2(i, j, 'b') = rgb.b;
		}

	ppm2.Flush("out.ppm");
	return 0;
}

imori.png out.png

注意

普段グレースケール画像ばかりいじっている身としてはこういうのは新鮮。あんまりカラー画像に対する処理は興味がなかったのですが、セグメンテーションの色分けとかに使えそうな感じですね。
ついでにお遊びでカラーバーみたいなものを作ろうと思ったときに気が付いた注意点について言及してこの記事を終わりにします。作りたかったのは次のような画像です。
out.png
こういう画像を作ろうと思ったとき、RGBでは3チャンネルしかないので困るわけですが、HSVを使えばHを振ることでたくさんの色が作れます。
Q.5ではRGB -> HSV -> RGBと変換したわけですが、今回はHSV -> RGBという変換になります。この際$V \geq S$が成立しなけらばならないことに注意が必要です。これを守らないとRGBに負の値が許されてしまいます。

int main()
{
	int width = 256, height = width;
	PPM ppm(width, height);

	int N = 6;
	
	for (int i = 0; i < width; i++)
	{
		int n = i / 50;
		HSV hsv;
		hsv.h = 360. / (double)N * n;
		hsv.s = 0.5;
		double dv = (1. - hsv.s) / height;
		for (int j = 0; j < height; j++)
		{
			hsv.v = hsv.s + dv * j;
			RGB rgb = HSV2RGB(hsv);
			int r = rgb.r;
			int g = rgb.g;
			int b = rgb.b;
			ppm(i, j, 'r') = r;
			ppm(i, j, 'g') = g;
			ppm(i, j, 'b') = b;
		}

	}

	ppm.Flush("out.ppm");
	return 0;
}
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?