OpenCV C ++-将HSI图像转换为BGR

时间:2020-05-16 11:07:46

标签: c++ opencv bgr

我必须实现两种算法来转换BGR <-> HSI,而无需使用OpenCV例程。我按照《数字图像处理》 (冈萨雷斯-伍兹)this topic中的公式正确实现了BGR2HSI算法:

#define rad(x) (x * M_PI / 180.0)

#define deg(x) (x * 180.0 / M_PI)

Mat BGR2HSI(Mat src) {
Mat out = Mat::zeros(src.rows, src.cols, src.type());

for (int i = 0; i < src.rows; i++)
    for (int j = 0; j < src.cols; j++) {
        double b = src.at<Vec3b>(i,j)[0];   // B (blu)
        double g = src.at<Vec3b>(i,j)[1];   // G (green)
        double r = src.at<Vec3b>(i,j)[2];   // R (red)
        double theta = (b != 0 && g != 0 && r != 0) ? deg(acos(0.5 * ((r-g) + (r-b)) / sqrt((pow(r-g,2)) + ((r-b)*(g-b))))) : 0;
        out.at<Vec3b>(i,j)[0] = (b <= g) ? theta : 360 - theta; // H (hue)
        out.at<Vec3b>(i,j)[1] = (b != 0 && g != 0 && r != 0) ? (1.0 - 3*(min(min(b,g),r)/(b + g + r))) * 100 : 0;   // S (saturation)
        out.at<Vec3b>(i,j)[2] = (b + g + r) / 3;    // I (intensity)
    }

return out;
}

我对此算法有疑问:我不知道为什么必须将饱和度公式乘以100。此外,我定义了rad()deg()函数,因为我知道cmath例程使用辐射,但是似乎OpenCV使用度数,如果我做错了,请更正。

另一方面,我仍然遵循本书的公式编写了此HSI2BGR函数,但它不起作用:

Mat HSI2BGR(Mat src) {
Mat out = Mat::zeros(src.size(), src.type());

for (int i = 0; i < src.rows; i++)
    for (int j = 0; j < src.cols; j++) {
        double H = src.at<Vec3b>(i,j)[0];   // componente H
        double S = src.at<Vec3b>(i,j)[1];   // componente S
        double I = src.at<Vec3b>(i,j)[2];   // componente I
        H *= 360;
        if (H >= 240 && H < 360) {
            H -= 240;
            double g = out.at<Vec3b>(i,j)[1] = I * (1.0 - S);   // green
            double b = out.at<Vec3b>(i,j)[0] = I * (1.0 + (S * deg(cos(rad(H))))/(deg(cos(rad(60 - H)))));  // blu
            out.at<Vec3b>(i,j)[2] = 31 - (g + b);   // red
        }
        else
            if (H >= 120 && H < 240) {
                H -= 120;
                double r = out.at<Vec3b>(i,j)[2] = I * (1.0 - S);   // red
                double g = out.at<Vec3b>(i,j)[1] = I * (1.0 + (S * deg(cos(rad(H))))/(deg(cos(rad(60 - H)))));  // green
                out.at<Vec3b>(i,j)[0] = 31 - (r + g);   // blu
            }
            else {
                double b = out.at<Vec3b>(i,j)[0] = I * (1.0 - S);   // blu
                double r = out.at<Vec3b>(i,j)[2] = I * (1.0 + (S * deg(cos(rad(H))))/(deg(cos(rad(60 - H)))));  // red
                out.at<Vec3b>(i,j)[1] = 31 - (r + b);   // green
            }
    }
return out;
}

Results of algorithms

0 个答案:

没有答案
相关问题