35

I am trying to find the maximum pixel value of a cv::Mat.

The Problem : *maxValue is always returning 0.

From this S.O. thread, I understand that 'max_element return iterators, not values. This is why I use *maxValue'

cv::Mat imageMatrix;

double  sigmaX = 0.0;
int ddepth = CV_16S; //  ddepth – The desired depth of the destination image


cv::GaussianBlur( [self cvMatFromUIImage:imageToProcess], imageMatrix, cv::Size(3,3), sigmaX);

cv::Laplacian(imageMatrix, imageMatrix, ddepth, 1);

std::max_element(imageMatrix.begin(),imageMatrix.end());

std::cout << "The maximum value is : " << *maxValue << std::endl;

Note : If min_element is substituted in place of max_element, and minValue in place of maxValue, *minValue will always return 0.

Community
  • 1
  • 1
Ríomhaire
  • 3,084
  • 4
  • 25
  • 40
  • Maybe imageMatrix is all zeros? Try printing it to see what it contains. –  Apr 11 '13 at 17:43
  • Thanks stardust_. I printed it out to the console and it is not. – Ríomhaire Apr 11 '13 at 17:44
  • When I attempted to use `std::max_element(imageMatrix.begin(),imageMatrix.end());` I received the error `No matching member function call to begin`. I do not fully understand the ``. – Ríomhaire Apr 11 '13 at 17:51
  • Ya I see man I thought it was a normal container. I think OpenCV has it's own containers. Maybe that's why std::max_element doesn't work on them. –  Apr 11 '13 at 18:01
  • What elements does imageMatrix contains? – shivakumar Apr 11 '13 at 18:05
  • You could use the minMaxLoc openCV function. [link]http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?#void%20minMaxLoc%28InputArray%20src,%20double*%20minVal,%20double*%20maxVal,%20Point*%20minLoc,%20Point*%20maxLoc,%20InputArray%20mask%29[/link] – TOTA Apr 11 '13 at 18:08
  • http://opencv.willowgarage.com/documentation/cpp/core_operations_on_arrays.html#cv-minmaxloc –  Apr 11 '13 at 18:09
  • http://opencv.willowgarage.com/documentation/cpp/core_operations_on_arrays.html#cv-reduce –  Apr 11 '13 at 18:12
  • Updated to show full code @shivakumar. – Ríomhaire Apr 11 '13 at 18:12
  • possible duplicate of [How to find max and min lightness values of an image in opencv?](http://stackoverflow.com/questions/14724047/how-to-find-max-and-min-lightness-values-of-an-image-in-opencv) – kiranpradeep Apr 16 '15 at 07:31

1 Answers1

69

You should use the OpenCV built-in function minMaxLoc instead of std function.

Mat m;
//Initialize m
double minVal; 
double maxVal; 
Point minLoc; 
Point maxLoc;

minMaxLoc( m, &minVal, &maxVal, &minLoc, &maxLoc );

cout << "min val: " << minVal << endl;
cout << "max val: " << maxVal << endl;
Andre Holzner
  • 18,333
  • 6
  • 54
  • 63
shivakumar
  • 3,297
  • 19
  • 28
  • 4
    Cheers @shivakumar! I used `double minVal; double maxVal; cv::minMaxLoc(imageMatrix, &minVal, &maxVal);` – Ríomhaire Apr 12 '13 at 10:55
  • 2
    minMaxLoc is quite a slow function if what you are looking for is just the maximum value in the image... It's a problem difficult to avoid when using wider purpose functions. – Antonio Apr 09 '14 at 09:30
  • @Antonio This answer tells minMaxLoc is super fast- http://stackoverflow.com/a/26409969/1180117 – kiranpradeep Apr 16 '15 at 07:27
  • 3
    @Kiran OP is apparently not interested in knowing the *location* of the max, but just the value. Now, you can use `minMaxIdx` which is the one actually mentioned to be fast (I suggest you update your answer). However, if you could have the same function to compute just the maximum, you would have half of the processing going on (not half of the memory reading though). If you have a very specific problem and you use a wider scope library function, you'll end up with some unnecessary computation, that's a general rule. – Antonio Apr 16 '15 at 08:03
  • @Ríomhaire The reason why your initial code does not work is visible in [the link posted above by Kiran](http://stackoverflow.com/a/12521957/2436175): you would need to call `std::max_element(imageMatrix.begin(),imageMatrix.end());`. However, stay with shivakumar solution, which is more efficient – Antonio Apr 16 '15 at 08:05
  • @Antonio It was not my answer. I was just referring to some body else answer. – kiranpradeep Apr 16 '15 at 08:06
  • @Kiran There is no misunderstanding. You should prefer `minMaxIdx` to `minMaxLoc` when you are not interested in the position of min and max, and therefore update your answer. – Antonio Apr 16 '15 at 08:08
  • @Antonio Thanks. I got the point on `minMaxIdx` vs `minMaxLoc`. But, I am missing the part where you are referring to `my` answer. Which answer of mine are you referring to ? – kiranpradeep Apr 16 '15 at 08:09
  • @Kiran Ah, gosh, you are right! :) I thought you had answer here :) :) – Antonio Apr 16 '15 at 08:12
  • @Antonio Ok. Also I am not in favour of `std::max_element`. I think it will fail if `Mat` is not continuous. – kiranpradeep Apr 16 '15 at 08:15
  • 1
    @Kiran Probably in the end not (I changed my opinion in the meantime :) ). I suppose the iterator is implemented in a way that checks if it reached the end of a row. I expect it just to be inefficient, but not wrong. – Antonio Apr 16 '15 at 08:19
  • It seems to be okay only to one channel `cv::Mat` – Summer Sun Sep 23 '17 at 08:28