Ask Your Question
2

compareHist problem, type != CV_32F

asked 2013-01-30 06:37:46 -0600

tkd89 gravatar image

as in title, when i'm trying compare two histograms which are cv::MatND type and obtained by:

cv::calcHist(&image,
             1,             // histogram of 1 image only
             channels,      // the channel used
             cv::Mat(),     // no mask is used
             hist_rgb,      // the resulting histogram
             3,             // it is a 3D histogram
             histSize,      // number of bins
             ranges,        // pixel value range
             true,
             false);

and normalized by:

cv::normalize( hist_temp, hist_rgb, 1.0, 0.0, cv::NORM_L1 );

i have the following error:

OpenCV/OpenCV-2.4.3/modules/imgproc/src/histogram.cpp:1399: error: (-215) H1.type() == H2.type() && H1.type() == CV_32F in function compareHist

i check above two conditions and the problem is in: H1.type() == CV_32F, but i don't know how to fix it

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
2

answered 2013-04-29 12:21:04 -0600

Eric Greveson gravatar image

updated 2013-04-29 13:03:46 -0600

I've come across the same problem using the cv2.compareHist function in the Python API (which basically calls the same code as the C++ function once data structures have been wrapped / converted). I tried a minor modification - using a 2D array rather than a 3D array - and it worked. I think there is a bug in compareHist in histogram.cpp - as the error message says, it asserts:

H1.type() == H2.type() && H1.type() == CV_32F

but I think that H1.type() == CV_32F returns false if it's a 3D histogram, as H1.type() is no longer CV_32F - it might be something like CV_32FC3 or CV_32FC4, which is stored as a different number (see CV_MAKE_TYPE macro). I believe it could be fixed by using CV_MAT_DEPTH(H1.type()) == CV_32F, although I haven't checked the code. I'll see if I can find a suitable place to file a bug.

EDIT: I've sent a pull request to change H1.type() to H1.depth(). If this gets accepted and merged, the issue should be fixed in future OpenCV versions.

edit flag offensive delete link more

Comments

They changed it! I fixed mine by converting data like this map(np.float32, data) using numpy.float32 not bare float

DgrinderHZ gravatar imageDgrinderHZ ( 2020-09-10 06:44:40 -0600 )edit
2

answered 2013-04-29 13:50:31 -0600

updated 2013-04-29 13:51:30 -0600

As far as I know, the only thing that compareHist requests is that the data type of your output and input matrix are of type CV_32F, which means you use float data, instead of uchar, integer or double.

Basically only a typecast should suffice.

Could you add the following lines before the normalize command

hist_temp.convertTo(hist_temp, CV_32F);
hist_rgb.convertTo(hist_temp, CV_32F);

Then the following normalization will work just fine

cv::normalize( hist_temp, hist_rgb, 1.0, 0.0, cv::NORM_L1 );

Also be sure that both histograms have same size initialization before the normalization.

edit flag offensive delete link more

Comments

You're right that both matrices need to be of type CV_32F - however, the method that the compareHist function (currently) uses to check this is flawed. The test H1.type() == CV_32F will return false if the matrix is stored as e.g. a 2D, n-channel matrix. If n was 3, then H1.type() would be CV_32FC3, and CV_32FC3 != CV_32F. Hence my pull request to change to use H1.depth() - this will return CV_32F even if it is a multi-channel matrix. This bug would only be seen if you're using a histogram stored as a multi-channel cv::Mat - which is only the case for histograms of greater than 2 dimensions. I think your suggestion might indeed be the answer to the original post, though - having a matrix of the wrong type is a more likely scenario - so I'll upvote this.

Eric Greveson gravatar imageEric Greveson ( 2013-04-30 05:08:14 -0600 )edit

Yeah but as far as I know, you are not supposed to feed multiple channels at same time for normalization. 90% chance that the author of the question did not know that. He can solve it easily by using the split function and then only using the first channel as input to the normalize. Once all the channels have been normalized, he could then call mixChannels again to mix them back together.

This would be also the solution to your problem. I am guessing it is just not wanted to feed multiple channels at once to these functions, so people actually know what they doing.

StevenPuttemans gravatar imageStevenPuttemans ( 2013-04-30 08:00:18 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2013-01-30 06:37:46 -0600

Seen: 10,005 times

Last updated: Apr 29 '13