Color Histogram doesn't seem right

Hello all:

I am trying to create a binned hsv histogram for jpg files.
The hue is binned into 72 bins, and the saturation and values are binned to 32 bins.

My opencv program is this:

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include

using namespace std;
using namespace cv;

int main( int argc, char** argv )
{
Mat src, hsv;
if ( argc != 2 ) {
cout << “Missing input image file” << endl;
return -1;
}
src = imread(argv[1], IMREAD_COLOR);
if ( !src.data ) {
cout << “Not image file!” << endl;
return -2;
}

cvtColor(src, hsv, COLOR_BGR2HSV);

// Quantize the hue to 72 levels
// and the saturation to 32 levels
// and the value to 32 levels
int hbins = 72, sbins = 32, vbins = 32;
int histSize = {hbins, vbins};

// hue varies from 0 to 179, see cvtColor
float hranges = { 0, 180 };
// saturation varies from 0 (black-gray-white) to 255 (pure spectrum color)
// luminosity value varies from 0 (black) to 255 (full bright)
float sranges = { 0, 256 };
float vranges = { 0, 256 };

// only going to use H and V not S (saturation)
const float* ranges = { hranges, vranges };

MatND hist;

// we compute the histogram from the 0-th and 2-nd channels
int channels = {0, 2}; // h,s,v are channels 0,1,2 respectively

calcHist( &hsv, 1, channels, Mat(), // do not use mask
hist, 2, histSize, ranges,
true, // the histogram is uniform
false );

// find max (or minimum values)

// double maxVal=0;
// minMaxLoc(hist, 0, &maxVal, 0, 0);

int h,s,v;
// hue values to list (red and near red)
int hh = { 0, 1, 70, 71 };
const int hhsize = 4;
for ( h = 0; h < hbins; h++ ) {
cout << “[” << h << "] " << v;
for ( v = 0; v < vbins; v++ )
{
cout << " " << hist.at(h,v);
}
cout << endl << flush;
}
/*
int scale = 10;
Mat histImg = Mat::zeros(sbinsscale, hbins10, CV_8UC3);
for( int h = 0; h < hbins; h++ )
for( int s = 0; s < sbins; s++ )
{
float binVal = hist.at(h, s);
int intensity = cvRound(binVal255/maxVal);
rectangle( histImg, Point(h
scale, s*scale),
Point( (h+1)*scale - 1, (s+1)*scale - 1),
Scalar::all(intensity),
-1 );
}
namedWindow( “Source”, 1 );
imshow( “Source”, src );
namedWindow( “H-S Histogram”, 1 );
imshow( “H-S Histogram”, histImg );
*/
// waitKey();
return (0);
}

When I run the histogram against the image file, the results don’t seem right.

I get

[0] 4198512 165759 608 174 88 74 30 19 16 14 8 9 7 8 5 5 6 5 4 7 7 6 12 11 13 13 13 19 25 40 57 117 13056
[1] 32 3 96 12 4 6 6 8 2 5 1 1 4 4 2 4 3 1 3 2 3 2 3 3 3 2 9 7 4 6 21 42 8088
[2] 32 554 88 9 6 9 3 9 7 8 7 3 5 6 6 3 5 5 4 7 5 6 7 7 10 9 9 10 12 19 29 143 12195
[3] 32 165 19 5 5 6 1 2 5 3 5 3 6 5 5 6 7 6 4 7 4 4 8 5 9 4 10 10 14 15 27 36 8907
[4] 32 157 63 8 6 4 5 5 5 6 6 3 9 5 4 6 4 5 4 3 10 1 7 5 7 4 11 8 8 19 33 98 12175
[5] 32 28 46 6 0 2 5 1 3 2 2 2 2 2 4 3 5 0 5 5 2 3 5 4 2 6 5 6 10 10 29 105 8651
[6] 32 964 22 9 1 8 8 6 8 5 10 5 5 4 3 4 6 7 3 5 4 3 4 8 5 5 7 5 8 16 10 99 13272
[7] 32 5 35 4 4 1 5 0 3 2 9 1 4 3 10 7 6 3 3 6 8 5 11 4 11 4 10 14 10 16 25 72 8656
[8] 32 525 17 2 2 4 6 2 3 1 4 8 8 5 3 2 4 8 1 3 1 5 4 7 3 5 8 10 9 14 34 173 12993
[9] 32 113 15 0 3 4 5 1 2 4 3 9 6 1 1 1 4 2 10 6 2 2 4 5 4 8 6 6 8 10 16 84 9015
[10] 32 18 12 1 0 2 3 2 4 5 5 4 4 6 1 4 6 2 7 4 5 5 8 9 10 3 8 12 17 9 33 129 12796
[11] 32 0 2 0 2 0 4 7 2 2 2 3 3 0 2 1 2 4 4 3 2 1 2 2 2 6 5 4 5 8 6 65 9428
[12] 32 1527 23 3 2 2 3 2 3 5 8 10 1 4 4 4 9 8 6 3 7 4 6 9 8 7 9 10 11 9 25 78 14431
[13] 32 0 4 5 0 1 1 1 3 2 4 2 2 1 3 2 2 2 2 1 4 3 2 3 4 6 4 4 4 8 6 22 8559
[14] 32 110 25 5 1 2 2 3 6 4 1 3 2 4 1 7 5 5 7 7 6 7 8 10 5 9 13 10 12 17 20 53 14063
[15] 32 117 9 1 2 3 2 3 1 1 3 2 4 4 7 4 6 7 6 4 2 9 3 3 7 5 8 7 9 10 19 20 8846
[16] 32 298 21 1 3 1 2 1 2 4 3 4 1 2 8 5 5 1 3 2 3 1 4 5 3 8 4 5 4 11 15 18 13591
[17] 32 19 15 3 0 0 2 1 0 0 0 1 2 1 0 1 0 1 0 1 1 2 2 0 1 1 1 1 1 3 4 3 9398
[18] 32 523 8 3 1 0 1 0 1 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12455
[19] 32 61 16 2 1 2 1 1 1 2 2 1 5 5 8 1 3 1 1 3 1 3 4 2 3 4 3 5 7 7 12 26 8586
[20] 32 680 27 3 0 2 0 1 4 1 4 2 4 5 5 5 6 8 5 3 5 8 3 10 7 11 7 9 15 13 15 25 13133
[21] 32 128 18 4 0 1 2 1 1 1 1 0 2 4 0 4 1 3 2 5 2 2 0 2 2 3 5 4 8 6 18 25 8312
[22] 32 98 58 3 2 2 4 0 2 2 2 6 3 3 7 5 3 4 9 4 5 10 5 10 7 12 10 12 14 24 34 57 12868
[23] 32 0 8 2 3 3 1 3 4 5 4 8 4 4 2 7 5 5 4 8 5 3 6 7 4 1 9 5 9 3 17 41 8279
[24] 32 12521 684 210 87 53 34 35 25 15 18 23 7 10 7 6 10 5 6 15 1 7 8 9 9 7 15 9 15 17 29 70 13037
[25] 32 20 49 6 0 3 5 5 1 4 3 5 8 7 4 3 2 8 6 4 3 4 6 3 7 8 5 10 12 16 13 42 8227
[26] 32 280 48 11 5 1 6 7 4 4 7 4 1 1 5 6 6 3 9 6 3 3 8 9 9 5 9 9 12 15 23 47 12622
[27] 32 58 32 11 4 3 2 3 1 2 4 6 4 3 4 1 2 4 6 3 2 4 5 5 3 5 4 10 3 11 15 29 8728
[28] 32 221 50 4 4 5 6 4 0 2 8 7 6 3 2 5 6 7 5 6 2 6 5 7 6 4 9 5 14 12 22 47 13164
[29] 32 10 22 2 1 2 2 8 5 3 4 3 2 1 2 2 3 6 4 2 3 6 7 4 7 7 7 10 15 17 26 50 8403
[30] 32 1657 53 3 0 5 4 4 7 7 8 7 8 4 9 5 5 5 5 4 10 1 3 11 7 8 9 11 13 16 30 55 13497
[31] 32 39 18 0 1 3 0 2 2 2 2 2 5 2 5 3 5 6 6 5 7 7 6 8 4 11 6 12 11 14 20 51 8967
[32] 32 237 30 1 4 2 1 2 3 1 2 4 1 6 2 5 8 4 6 1 8 4 2 10 3 12 9 9 10 19 29 57 13003
[33] 32 182 21 2 1 0 0 2 4 1 4 2 2 4 3 1 3 3 5 4 2 4 3 3 2 3 3 3 6 4 6 18 9091
[34] 32 36 22 2 2 2 3 1 1 1 2 5 5 6 4 5 3 3 2 3 1 5 3 6 5 7 6 10 9 14 27 45 13343
[35] 32 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 1 1 1 1 2 1 1 0 0 0 0 0 9581
[36] 32 257 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 3 1 2 7 32 14204
[37] 32 7 12 1 0 0 1 0 1 0 2 1 3 3 5 2 2 2 2 3 3 4 5 5 4 6 6 9 12 14 21 144 8537
[38] 32 89 41 1 0 0 2 4 3 7 3 7 4 5 7 5 5 8 7 4 9 6 8 6 8 7 10 10 19 17 26 120 13112
[39] 32 136 28 3 2 6 1 3 4 3 2 3 2 2 3 7 5 3 3 1 3 4 4 4 5 4 3 7 9 10 14 57 8681
[40] 32 308 56 7 2 3 5 6 2 6 5 4 4 8 2 6 7 4 6 4 11 5 9 10 13 4 14 14 17 22 51 163 12929
[41] 32 71 64 16 5 2 5 5 2 5 5 3 4 6 7 0 6 6 3 1 9 3 5 7 6 5 7 9 12 12 23 73 8507
[42] 32 436 47 26 11 11 4 5 7 7 7 3 4 6 4 5 3 6 3 3 6 5 2 6 9 3 10 10 10 21 33 164 13143
[43] 32 197 95 14 10 5 6 7 2 5 5 7 9 4 6 12 8 1 8 7 5 11 7 6 7 12 9 12 15 20 24 59 8325
[44] 32 857 119 33 18 14 8 8 10 9 8 6 5 5 6 5 6 11 4 3 6 9 7 6 8 5 12 10 13 22 43 247 12328
[45] 32 644 156 36 20 12 13 9 3 5 4 8 6 2 2 10 5 8 1 8 6 9 7 5 7 8 8 9 13 18 24 156 8364
[46] 32 369 207 55 32 23 17 12 10 7 9 7 9 7 6 3 9 8 4 7 10 6 7 9 12 8 11 12 18 19 49 215 11731
[47] 32 0 36 43 33 20 19 18 20 12 14 9 10 9 11 10 5 8 8 6 6 9 6 7 7 7 10 12 8 19 28 172 8214
[48] 32 4815 575 121 72 48 34 31 19 24 25 18 11 19 15 16 16 15 13 16 16 16 14 17 21 21 21 24 34 44 69 199 12316
[49] 32 16 132 25 14 9 7 7 8 8 7 8 6 7 5 7 2 7 5 4 8 9 10 7 7 10 10 12 13 29 44 145 7694
[50] 32 532 141 32 10 12 9 11 7 7 9 4 7 5 8 5 7 8 11 11 8 8 11 8 13 14 17 16 18 21 38 161 12610
[51] 32 72 55 5 7 6 5 2 5 5 9 10 10 8 5 8 6 5 10 6 10 7 6 11 9 7 13 11 14 16 18 81 8464
[52] 32 229 108 14 3 1 1 2 2 4 5 3 4 4 5 5 5 4 6 5 4 8 8 7 9 9 18 16 17 27 26 152 12266
[53] 32 59 75 14 7 1 5 3 1 0 0 0 0 0 1 2 1 1 1 1 1 0 0 0 0 0 0 0 2 7 27 176 8371
[54] 32 290 56 22 18 13 9 3 4 3 1 3 1 1 1 1 2 4 1 2 2 6 6 5 4 6 7 6 13 18 19 87 12486
[55] 32 21 65 20 5 7 2 6 4 2 2 5 4 2 7 2 4 1 2 3 3 4 4 3 5 9 7 11 8 19 19 73 8942
[56] 32 442 90 28 15 6 4 6 6 6 4 7 4 14 6 7 6 7 8 12 6 7 7 7 11 10 13 7 11 23 36 118 12473
[57] 32 105 20 14 6 9 5 8 9 7 7 4 3 2 3 2 8 3 6 6 8 4 9 1 9 5 12 10 12 17 33 90 8626
[58] 32 91 86 18 17 12 9 13 10 6 13 10 10 12 11 8 7 6 6 9 2 12 7 10 8 10 10 12 17 26 44 135 13417
[59] 32 0 9 12 12 7 6 7 5 6 4 4 7 4 4 6 5 5 5 3 6 5 3 5 4 7 5 9 6 10 19 53 8646
[60] 32 78 45 14 8 5 9 7 3 3 7 8 3 3 5 3 4 6 6 5 8 8 7 7 10 12 12 12 17 32 52 166 13835
[61] 32 5 33 7 6 3 3 3 2 9 3 5 4 5 3 3 9 4 2 4 3 2 5 4 3 6 6 6 5 10 19 93 8456
[62] 32 123 60 9 6 7 6 6 7 4 4 5 9 4 6 5 7 5 4 7 7 8 10 3 12 9 10 16 19 19 55 166 13155
[63] 32 53 29 5 9 6 3 4 7 1 2 5 5 4 1 0 3 11 3 2 2 4 12 5 1 7 19 3 9 24 24 127 8428
[64] 32 122 43 23 6 5 8 8 5 5 6 10 8 2 8 9 9 5 3 8 13 4 7 9 12 8 11 21 21 23 50 106 12331
[65] 32 1 47 10 11 9 7 2 8 8 8 5 3 3 4 4 8 4 4 2 3 8 5 3 7 5 6 7 9 8 19 80 9033
[66] 32 683 59 19 7 14 9 15 7 2 6 5 2 7 4 7 4 4 3 9 8 6 5 5 10 9 8 13 19 21 38 143 12614
[67] 32 0 25 14 12 4 3 4 6 6 8 8 8 3 7 9 4 6 7 7 7 8 9 6 7 14 10 13 12 17 30 94 8196
[68] 32 131 119 21 17 4 6 7 7 4 4 6 7 3 9 2 5 10 5 6 8 11 7 11 9 7 15 16 23 20 34 96 12258
[69] 32 381 79 20 9 5 2 5 7 2 3 4 2 5 7 6 5 5 2 6 4 4 6 5 8 10 8 10 10 11 29 60 8732
[70] 32 8 141 8 9 9 6 7 6 9 4 11 7 8 4 4 5 4 4 4 5 3 5 3 4 7 8 9 6 10 19 74 11991
[71] 32 0 5 10 9 5 2 4 2 4 3 6 5 4 2 3 2 5 6 6 6 4 5 4 8 4 5 7 8 7 19 45 7880

The first line [0] seems to be totally wrong.

The subsequent lines [1] to [71] contain 32 as the first entry, I don’t believe this is correct. And the last entry on each row is very large, this doesn’t seem right also.

I am running the calc-histogram C++ program over 11K+ files so I need this to work correctly.

Comments are appreciated. What do I have incorrect?

  • Randall

for some odd reason the 3rd include is not correct, it should be #include <iostream>

use code formatting, not “quoting”

Thank you for that correction.

It’s not totally wrong, I don’t know where this “4198512” in your first row is coming from but the rest seems to be right. I also don’t know if this is really the output of your code because cout << " " << hist.at(h,v); should result in an error because the data type is missing. it has to be cout << hist.at<float>(h,v); in my understanding. BTW you can also easily output a Mat with “cout << hist;”. I also don’t have this value in my output when I try your code. You can try "cout << (int)sum(hist).val[0];". If the sum of all histogram values is not the amount of width*height, then something is wrong.

But check the image you are using. You are generating a 2-dimensional [h,v] histogram. But your circle image consists of a real black border with H=0 and V=0, a colored circle with H=[0…179] and V=255 and a lot of JPEG compression. artefacts that might be close to black and have random H and V values. Split it into the H,S,V channels and display the channels in a window to understand it better.

The “165759” as first value in first row is the number of real black pixels with H,V=[0,0], the “32” as first values in the other rows are the fake blacks with random H and lowest V caused by JPEG compression; Don’t use JPG for image processing. PNG might be bigger for photos but it’s losless and makes you also losing less hair when trying to process them. The reason why your last values in the row are much bigger is that the V for the whole circle is set to 255, therefore it’s in the highest bin.

I also don’t understand why you are using 72 bins for a H range of 0…179, 180 is not dividable by 72.

5 degrees per bucket, but yes that doesn’t mesh with OpenCV’s mapping which is 2 degrees per count (0 .. 179, as stated).

such a histogram will look like a comb with a thick spine.

BadTrip:
Thank you for all your comments. I had used 72 bins for dividing the hues ranges 0…360 into containers of 5 degs each, but opencv does not use 0…360 for hues, but only 0…180. I had a mistake on the output which is why there was a stuck value in the first position after the [nn] index. I do have my C++ code doing a
" cout << setprecision(10) << hist.at(h,v) << etc" and caught this problem a couple of days ago.

Would it be worthwhile to convert the ISS photos to png before working with any image processing algorithms?

All the photos posted by NASA ISS EOL team are jpg files, quite large in size, which is why I am asking.

NO, but if you copy the red pixels only to a new image or you are using the binary mask of the lightning to find enclosing circles around blobs in it, then it would be a very bad idea to save this output or the mask as JPG instead of PNG