Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
830 views
in Technique[技术] by (71.8m points)

c++ - BGR to HSV and back again

The documentation does not seem to explain what the expected range of the input is for an HSV->BGR conversion. Here is some example code where I am trying to get back the original BGR value after converting it to HSV. Does anyone know which scaling is expected?

#include <iostream>

#include <opencv2/opencv.hpp>

cv::Vec3b HSVtoBGR(const cv::Vec3f& hsv)
{
    cv::Vec3f hsvAdjusted = hsv; // If we use this directly, the output is (0,0,1) which is very wrong
    //hsvAdjusted[0] *= 360.; // If we do this to bring all of the values into the range (0,1), the output is (0,1,0), which is also very wrong

    // If we do this to bring all of the values into the range (0,255), the output is (0,0,200), which is still very wrong
    hsvAdjusted[1] *= 255./360.;
    hsvAdjusted[1] *= 255.;
    hsvAdjusted[2] *= 255.;

    cv::Mat_<cv::Vec3f> hsvMat(hsvAdjusted);

    cv::Mat_<cv::Vec3f> bgrMat;

    cv::cvtColor(hsvMat, bgrMat, CV_HSV2BGR);

    cv::Vec3b bgr = static_cast<cv::Vec3b>(bgrMat(0,0));
    return bgr;
}

/** Input 0 <= B <= 255, 0 <= G <= 255, 0 <= R <= 255
  * Output 0 <= H <= 360, 0 <= S <= 1, 0 <= V <= 1  */
cv::Vec3f BGRtoHSV(const cv::Vec3b& bgr)
{
    cv::Mat3f bgrMat(static_cast<cv::Vec3f>(bgr));

    bgrMat *= 1./255.;

    cv::Mat3f hsvMat;
    cv::cvtColor(bgrMat, hsvMat, CV_BGR2HSV);

    cv::Vec3f hsv = hsvMat(0,0);

    return hsv;
}

int main()
{
    // Create a BGR color
    cv::Vec3b bgr(5, 100, 200);
    std::cout << "bgr: " << bgr << std::endl;

    // Convert BGR to HSV
    cv::Vec3f hsv = BGRtoHSV(bgr);
    std::cout << "hsv: " << hsv << std::endl; // outputs // (29.23, .976, .7843), which seems correct

    // Convert back from HSV to BGR
    cv::Vec3b bgr2 = HSVtoBGR(hsv);
    std::cout << "bgr2: " << bgr2 << std::endl;

    return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have some scaling problems in the function HSVtoBGR.

You need to multiply by 255 the result after the conversion, not before. Remember that different conversions take place for Mat of type CV_32F and CV_8U.

This should work as expected:

cv::Vec3b HSVtoBGR(const cv::Vec3f& hsv)
{
    cv::Mat_<cv::Vec3f> hsvMat(hsv);
    cv::Mat_<cv::Vec3f> bgrMat;

    cv::cvtColor(hsvMat, bgrMat, CV_HSV2BGR);

    bgrMat *= 255; // Upscale after conversion

    // Conversion to Vec3b is handled by OpenCV, no need to static_cast
    return bgrMat(0);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...