天天看點

RGB圖像轉HSI直方圖均衡化後再轉回RGB

HSI圖像在直方圖均衡化時隻需處理I通道即可。

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace cv;
using namespace std;

Mat RGB2HSI(Mat src) {
	int lenth = src.rows;
	int width = src.cols;
	Mat hsi(lenth, width, CV_64FC3);
	for (int row = 0; row < lenth; row++)
	{
		for (int col = 0; col < width; col++)
		{
			double h, s, i, theta, num;
			double b = (double)src.at<Vec3b>(row, col)[0] / 255;
			double g = (double)src.at<Vec3b>(row, col)[1] / 255;
			double r = (double)src.at<Vec3b>(row, col)[2] / 255;
			double mi, mx;
			if (r > g && r > b)
			{
				mx = r;
				mi = min(g, b);
			}
			else
			{
				if (g > b)
				{
					mx = g;
					mi = min(r, b);
				}
				else
				{
					mx = b;
					mi = min(r, g);
				}
			}
			
			num = (r - g) * (r - g) + (r - b) * (g - b);
			theta = acos(((r - g + r - b)*0.5) / sqrt(num));
			if (g >= b)
			{
				h = theta;
			}
			else
			{
				h = 2 * 3.14 - theta;
			}
			
			h = h / (2 * 3.14);
			i = (r + g + b) / 3;
			s = 1 - mi / i;

			hsi.at<Vec3d>(row, col)[0] = h;
			hsi.at<Vec3d>(row, col)[1] = s;
			hsi.at<Vec3d>(row, col)[2] = i;
		}
	}
	return hsi;
}

Mat equal(Mat src)
{
	src.convertTo(src, CV_8UC3, 255.0);
	Mat temp1, src2;
	vector <Mat> channels;
	split(src, channels);
	//equalizeHist(channels[0], channels[0]);
	//equalizeHist(channels[1], channels[1]);
	equalizeHist(channels[2], channels[2]);
	imshow("i equal", channels[2]);
	merge(channels, temp1);
	//imshow("iqual", temp1);
	temp1.convertTo(temp1, CV_64FC3, 1 / 255.0);
	return temp1;
}

Mat HSI2RGB(Mat src) {
	int lenth = src.rows;
	int width = src.cols;
	Mat dst(lenth, width, CV_64FC3);

	for (int x = 0; x < lenth; x++)
	{
		for (int y = 0; y <width; y++)
		{
			double h = src.at<Vec3d>(x, y)[0] * 2 * 3.14;//H
			double s = src.at<Vec3d>(x, y)[1];  //S
			double i = src.at<Vec3d>(x, y)[2];  //I
			double r, g, b, num1, num2;
			if (h >= 0 && h < (3.14 * 2 / 3))
			{
				num1 = s * cos(h);
				num2 = cos(3.14 / 3 - h);

				r = 3 * i * (1 + num1 / num2) / 3;
				b = 3 * i * (1 - s) / 3;
				g = 3 * i - (r + b);
			}
			else if (h >= (3.14 * 2 / 3) && h < (3.14 * 4 / 3))
			{
				num1 = s * cos(h - 2 * 3.14 / 3);
				num2 = cos(3.14 - h);

				r = 3 * i * (1 - s) / 3;
				g = 3 * (1 + num1 / num2) / 3 * i;
				b = 3 * i - (r + g);
			}
			else if (h >= (3.14 * 4 / 3) && h <= (3.14 * 2))
			{
				num1 = s * cos(h - 4 * 3.14 / 3);
				num2 = cos(3.14 * 5 / 3 - h);

				g = 3 * (1 - s) / 3 * i;
				b = 3 * i * (1 + num1 / num2) / 3;
				r = 3 * i - (g + b);
			}
			dst.at<Vec3d>(x, y)[0] = b;
			dst.at<Vec3d>(x, y)[1] = g;
			dst.at<Vec3d>(x, y)[2] = r;
		}
	}
	return dst;
}


int main() {
	Mat src = imread("pink.jpg");

	if (src.empty())
	{
		return -1;
	}
	Mat dst, dst2, dst3;

	dst = RGB2HSI(src);
	dst2 = equal(dst);
	dst3 = HSI2RGB(dst2);

	imshow("src", src);
	imshow("RGB2HSI", dst);
	imshow("HSI2RGB", dst3);

	waitKey(0);
	return 0;
}