Build H-value histogram of HSV image: wrong parameters?
Hi,
I want to build histogram of Hue value of HSV image.
My initial image:
This is what Photoshop gives for it (just to have some reference, I suppose its not real HSV):
Histogram that I've got:
As soon as there are majority of green color and also some Red and Blue spots present, I suppose "colored" version should looks something like that:
Few peaks of red, blue and high peak of green.
1) Am I correct in this assumption?
Now I want to check this with simple HSV selection. And I've got ranges:
160...200 for red strip
110..170 for blue strip
Blue strip range is kind of expected result, but red confused me.
After I checked color in picture editor, I've got this. (in this software H channel is in range 0 ... 360)
Red:
Blue:
2) "Red" ranges should be 0...10 % of scale (or at 90...100 %), why on color selection its ~70...80% ?
As far as I know OpenCV v2.x.x used 0...127 for H channel, but later it was updated. Some sources says its 180, some its 255.
3) Does range 0...255 is correct for H-channel in OpenCV 4.1.2?
I cant figure out this... My HSV selection and histogram building based in assumption that range is 0...255
Are there any glance errors in my code?
HSV selector:
Mat HSVSelection(Mat& img_input, const char* window_name){
Mat camera_HSV;
Mat camera_HSV_th;
static int iLowH = 0;
static int iHighH = 255;
static int iLowS = 0;
static int iHighS = 255;
static int iLowV = 0;
static int iHighV = 255;
//create a window
namedWindow(window_name, CV_WINDOW_AUTOSIZE);
//Create trackbars in window
cvCreateTrackbar("Low_H", window_name, &iLowH, 255); //Hue (0 - 255)
cvCreateTrackbar("High_H", window_name, &iHighH, 255);
cvCreateTrackbar("Low_S", window_name, &iLowS, 255); //Saturation (0 - 255)
cvCreateTrackbar("High_S", window_name, &iHighS, 255);
cvCreateTrackbar("Low_V", window_name, &iLowV, 255); //Value (0 - 255)
cvCreateTrackbar("High_V", window_name, &iHighV, 255);
//Convert the captured frame from BGR to HSV
cvtColor(img_input, camera_HSV, COLOR_BGR2HSV);
//Threshold the image
inRange(camera_HSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), camera_HSV_th);
return camera_HSV_th;
}
Histogram:
int bins = 255;
void buildHistogram(Mat& camera_input)
{
Mat hue;
Mat hist;
hue.create(camera_input.size(), camera_input.depth());
int ch[] = { 0, 0 };
mixChannels(&camera_input, 1, &hue, 1, ch, 1);
int histSize = MAX(bins, 2);
float hue_range[] = { 0, 255 }; // CORRECT RANGE?
const float* ranges = { hue_range };
calcHist(&hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false);
normalize(hist, hist, 0, histSize, NORM_MINMAX, -1, Mat()); // can be always normalizeto to [0 , 255]?
int w = 400, h = 400;
int bin_w = cvRound((double)w / histSize);
Mat histImg = Mat::zeros(h, w, CV_8UC3);
for (int i = 0; i < bins; i++)
{
int px_qty = cvRound(hist.at<float>(i)*h / 255.0);
rectangle(histImg, Point(i*bin_w, h), Point((i + 1)*bin_w, h - px_qty),
COLOR_WHITE,
FILLED);
}
imshow("HISTOGRAM", histImg);
}
hue is in [0..180] (it has to fit into a byte) in opencv