使用 C++ 在 OpenCV 中将 HSI 转换为 RGB 时增加强度
Increasing Intensity when converting HSI to RGB in OpenCV using C++
更新我问的问题。我已经成功地从 RGB 转换为 HSI,然后再转换回来。我的教授指示我在输出图像之前通过将 ((1.0 - I) / 2.0) 添加到 I(强度)来增加图像强度。当我这样做时,它似乎会导致溢出,因此我对 RGB 等进行了所有检查。如果我减去上面的公式,它会成功地使图像变暗而不会出现溢出问题。我似乎无法确定此溢出的原因,也不知道如何纠正它。我起初以为它与 R = G = B 的值有关,但我通过输出这些变量并调试确认情况并非如此。造成这种情况的原因是饱和度 S 等于零。当 S = 0 时,我知道色调 H 是无关紧要的。任何帮助将不胜感激!
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#define M_PI (3.14159265358979323846)
using namespace cv;
int main(int argc, char * argv[])
{
if (argc <= 1)
{
std::cerr << "Not enough arguments." << std::endl;
return (1);
}
Mat img = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
std::cout << img.channels() << std::endl;
if (img.empty())
{
std::cerr << "Unable to open the image " << argv[1] << "." << std::endl;
return (1);
}
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
imshow("Original Image", img);
Mat hsi(img.rows, img.cols, img.type());
Mat newBGRimg = Mat::zeros(img.rows, img.cols, img.type());
double B, G, R, H, S, I, b, g, re;
int intB = 0, intG = 0, intR = 0;
for (int r = 0; r < img.rows; r++)
{
for (int c = 0; c < img.cols; c++)
{
b = img.at<Vec3b>(r, c)[0];
g = img.at<Vec3b>(r, c)[1];
re = img.at<Vec3b>(r, c)[2];
// Normalize colors
B = b / 255;
G = g / 255;
R = re / 255;
// BGR to HSI
double theta = acos((((R - G) + (R - B)) / 2) / (sqrt((pow((R - G), 2)) + ((R - B)*(G - B) + 0.0001))));
if (B <= G)
{
H = theta;
}
if (B > G)
{
H = (2 * M_PI) - theta;
}
if (H < 0)
H = 0;
if (H > 2 * M_PI)
H = 2 * M_PI;
double min = std::min({ B, G, R });
S = 1 - (3 * min) / (B + G + R); // / (B + G + R)
if (S < 0)
S = 0;
if (S > 1)
S = 1;
I = (B + G + R) / 3;
I = I + ((1.0 - I) / 2.0);
if (I < 0)
I = 0;
if (I > 1)
I = 1;
// HSI to BGR
if (H >= 0 && H < (2 * M_PI / 3))
{
B = I * (1 - S);
R = I * (1 + ((S * cos(H)) / (cos((M_PI / 3) - H))));
G = (3 * I) - (R + B);
B *= 255;
G *= 255;
R *= 255;
if (B > 255)
B = 255;
if (G > 255)
G = 255;
if (R > 255)
R = 255;
if (B < 0)
B = 0;
if (G < 0)
G = 0;
if (R < 0)
R = 0;
intB = (int)round(B);
intG = (int)round(G);
intR = (int)round(R);
//std::cout << intB << " " << intG << " " << intG << " " << r << " " << c << std::endl;
newBGRimg.at<Vec3b>(r, c)[0] = intB;
newBGRimg.at<Vec3b>(r, c)[1] = intG;
newBGRimg.at<Vec3b>(r, c)[2] = intR;
}
else if (H >= (2 * M_PI / 3) && H < (4 * M_PI / 3))
{
H = H - (2 * M_PI) / 3;
R = I * (1 - S);
G = I * (1 + ((S * cos(H)) / (cos((M_PI / 3) - H))));
B = (3 * I) - (R + G);
B *= 255;
G *= 255;
R *= 255;
if (B > 255)
B = 255;
if (G > 255)
G = 255;
if (R > 255)
R = 255;
if (B < 0)
B = 0;
if (G < 0)
G = 0;
if (R < 0)
R = 0;
intB = (int)round(B);
intG = (int)round(G);
intR = (int)round(R);
newBGRimg.at<Vec3b>(r, c)[0] = intB;
newBGRimg.at<Vec3b>(r, c)[1] = intG;
newBGRimg.at<Vec3b>(r, c)[2] = intR;
}
else if (H >= (4 * M_PI / 3))
{
H = H - (4 * M_PI) / 3;
G = I * (1 - S);
B = I * (1 + ((S * cos(H)) / (cos((M_PI / 3 - H)))));
R = (3 * I) - (G + B);
B *= 255;
G *= 255;
R *= 255;
if (B > 255)
B = 255;
if (G > 255)
G = 255;
if (R > 255)
R = 255;
if (B < 0)
B = 0;
if (G < 0)
G = 0;
if (R < 0)
R = 0;
intB = (int)round(B);
intG = (int)round(G);
intR = (int)round(R);
newBGRimg.at<Vec3b>(r, c)[0] = intB;
newBGRimg.at<Vec3b>(r, c)[1] = intG;
newBGRimg.at<Vec3b>(r, c)[2] = intR;
}
}
}
namedWindow("New RGB Image", CV_WINDOW_AUTOSIZE);
imshow("New RGB Image", newBGRimg);
imwrite("hsi-to-rgb.jpg", newBGRimg);
waitKey(0);
return 0;
}
在我的原始代码中,我试图使用 for ex 规范化 BGR 值。 B/B+G+R 根据 DI 第三版补充 material。 .这应该是 B/255 以将其标准化为 [0,1]。我认为这本书在建议这种规范化方法时是不正确的。
更新我问的问题。我已经成功地从 RGB 转换为 HSI,然后再转换回来。我的教授指示我在输出图像之前通过将 ((1.0 - I) / 2.0) 添加到 I(强度)来增加图像强度。当我这样做时,它似乎会导致溢出,因此我对 RGB 等进行了所有检查。如果我减去上面的公式,它会成功地使图像变暗而不会出现溢出问题。我似乎无法确定此溢出的原因,也不知道如何纠正它。我起初以为它与 R = G = B 的值有关,但我通过输出这些变量并调试确认情况并非如此。造成这种情况的原因是饱和度 S 等于零。当 S = 0 时,我知道色调 H 是无关紧要的。任何帮助将不胜感激!
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#define M_PI (3.14159265358979323846)
using namespace cv;
int main(int argc, char * argv[])
{
if (argc <= 1)
{
std::cerr << "Not enough arguments." << std::endl;
return (1);
}
Mat img = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
std::cout << img.channels() << std::endl;
if (img.empty())
{
std::cerr << "Unable to open the image " << argv[1] << "." << std::endl;
return (1);
}
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
imshow("Original Image", img);
Mat hsi(img.rows, img.cols, img.type());
Mat newBGRimg = Mat::zeros(img.rows, img.cols, img.type());
double B, G, R, H, S, I, b, g, re;
int intB = 0, intG = 0, intR = 0;
for (int r = 0; r < img.rows; r++)
{
for (int c = 0; c < img.cols; c++)
{
b = img.at<Vec3b>(r, c)[0];
g = img.at<Vec3b>(r, c)[1];
re = img.at<Vec3b>(r, c)[2];
// Normalize colors
B = b / 255;
G = g / 255;
R = re / 255;
// BGR to HSI
double theta = acos((((R - G) + (R - B)) / 2) / (sqrt((pow((R - G), 2)) + ((R - B)*(G - B) + 0.0001))));
if (B <= G)
{
H = theta;
}
if (B > G)
{
H = (2 * M_PI) - theta;
}
if (H < 0)
H = 0;
if (H > 2 * M_PI)
H = 2 * M_PI;
double min = std::min({ B, G, R });
S = 1 - (3 * min) / (B + G + R); // / (B + G + R)
if (S < 0)
S = 0;
if (S > 1)
S = 1;
I = (B + G + R) / 3;
I = I + ((1.0 - I) / 2.0);
if (I < 0)
I = 0;
if (I > 1)
I = 1;
// HSI to BGR
if (H >= 0 && H < (2 * M_PI / 3))
{
B = I * (1 - S);
R = I * (1 + ((S * cos(H)) / (cos((M_PI / 3) - H))));
G = (3 * I) - (R + B);
B *= 255;
G *= 255;
R *= 255;
if (B > 255)
B = 255;
if (G > 255)
G = 255;
if (R > 255)
R = 255;
if (B < 0)
B = 0;
if (G < 0)
G = 0;
if (R < 0)
R = 0;
intB = (int)round(B);
intG = (int)round(G);
intR = (int)round(R);
//std::cout << intB << " " << intG << " " << intG << " " << r << " " << c << std::endl;
newBGRimg.at<Vec3b>(r, c)[0] = intB;
newBGRimg.at<Vec3b>(r, c)[1] = intG;
newBGRimg.at<Vec3b>(r, c)[2] = intR;
}
else if (H >= (2 * M_PI / 3) && H < (4 * M_PI / 3))
{
H = H - (2 * M_PI) / 3;
R = I * (1 - S);
G = I * (1 + ((S * cos(H)) / (cos((M_PI / 3) - H))));
B = (3 * I) - (R + G);
B *= 255;
G *= 255;
R *= 255;
if (B > 255)
B = 255;
if (G > 255)
G = 255;
if (R > 255)
R = 255;
if (B < 0)
B = 0;
if (G < 0)
G = 0;
if (R < 0)
R = 0;
intB = (int)round(B);
intG = (int)round(G);
intR = (int)round(R);
newBGRimg.at<Vec3b>(r, c)[0] = intB;
newBGRimg.at<Vec3b>(r, c)[1] = intG;
newBGRimg.at<Vec3b>(r, c)[2] = intR;
}
else if (H >= (4 * M_PI / 3))
{
H = H - (4 * M_PI) / 3;
G = I * (1 - S);
B = I * (1 + ((S * cos(H)) / (cos((M_PI / 3 - H)))));
R = (3 * I) - (G + B);
B *= 255;
G *= 255;
R *= 255;
if (B > 255)
B = 255;
if (G > 255)
G = 255;
if (R > 255)
R = 255;
if (B < 0)
B = 0;
if (G < 0)
G = 0;
if (R < 0)
R = 0;
intB = (int)round(B);
intG = (int)round(G);
intR = (int)round(R);
newBGRimg.at<Vec3b>(r, c)[0] = intB;
newBGRimg.at<Vec3b>(r, c)[1] = intG;
newBGRimg.at<Vec3b>(r, c)[2] = intR;
}
}
}
namedWindow("New RGB Image", CV_WINDOW_AUTOSIZE);
imshow("New RGB Image", newBGRimg);
imwrite("hsi-to-rgb.jpg", newBGRimg);
waitKey(0);
return 0;
}
在我的原始代码中,我试图使用 for ex 规范化 BGR 值。 B/B+G+R 根据 DI 第三版补充 material。 .这应该是 B/255 以将其标准化为 [0,1]。我认为这本书在建议这种规范化方法时是不正确的。