问题
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;
}
回答1:
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);
}
回答2:
Run the code below separately. You'll be able to control the RGB values and get the corresponding HSV scaling.
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
char RGB_window[30] = "RGB Window";
char HSV_window[30] = "HSV Window";
Mat src,hsv;
static void onMouse( int event, int x, int y, int f, void* ){
Mat image=src.clone();
Vec3b rgb=image.at<Vec3b>(y,x);
int B=rgb.val[0];
int G=rgb.val[1];
int R=rgb.val[2];
Mat HSV;
Mat RGB=image(Rect(x,y,1,1));//capture that pixel in its own ROI
cvtColor(RGB, HSV,CV_BGR2HSV);
Vec3b hsv=HSV.at<Vec3b>(0,0);
int H=hsv.val[0];
int S=hsv.val[1];
int V=hsv.val[2];
char name[30];
sprintf(name,"B=%d",B);
putText(image,name, Point(150,40) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );
sprintf(name,"G=%d",G);
putText(image,name, Point(150,80) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );
sprintf(name,"R=%d",R);
putText(image,name, Point(150,120) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );
sprintf(name,"H=%d",H);
putText(image,name, Point(25,40) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );
sprintf(name,"S=%d",S);
putText(image,name, Point(25,80) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );
sprintf(name,"V=%d",V);
putText(image,name, Point(25,120) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,255,0), 2,8,false );
sprintf(name,"X=%d",x);
putText(image,name, Point(25,300) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,0,255), 2,8,false );
sprintf(name,"Y=%d",y);
putText(image,name, Point(25,340) , FONT_HERSHEY_SIMPLEX, .7, Scalar(0,0,255), 2,8,false );
//namedWindow("Ref HSV",WINDOW_NORMAL);
Mat ref(50,50,CV_8UC3,Scalar(H,S,V));
//imwrite("hsv.jpg",image);
imshow( RGB_window, image );
//imshow( "Ref HSV",ref);
}
int main()
{
//VideoCapture cap(0);
static int Bs=0,Gs=0,Rs=0;
namedWindow("colourCtrl");
//src = imread("bgr.png",1);
for(;;)
{
//cap>>src;
createTrackbar("B","colourCtrl",&Bs,255);
createTrackbar("G","colourCtrl",&Gs,255);
createTrackbar("R","colourCtrl",&Rs,255);
Mat refRGB(500,500,CV_8UC3,Scalar(Bs,Gs,Rs));
src=refRGB;
cvtColor(src,hsv,CV_BGR2HSV);
imshow(RGB_window,src);
imshow(HSV_window,hsv);
setMouseCallback( RGB_window, onMouse, 0 );
setMouseCallback( HSV_window, onMouse, 0 );
char c=waitKey(10);
if(c=='b')
{break;}
}
return 0;
}
来源:https://stackoverflow.com/questions/35737942/bgr-to-hsv-and-back-again