Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

minMaxLoc datatype

I have been stumped by this for quite some time. could you please help me to know, what datatype does the minMaxLoc() in Opencv consider, while finding the max, min vlaues of a Mat variable? I got a certain value from the function, but I have no idea wat that value actually represents, and in what data type?

    Laplacian(src_gray,dst,ddepth,kernel_size,scale,delta,BORDER_DEFAULT);
    minMaxLoc(dst,&min,&estimate,&minLoc,&maxLoc,noArray());

The value of 'estimate' is somewhere around 1000's, while if I try to access the value of 'dst' Mat variable, using

    dst.at<datatype>(k,l)

Am getting vague values, starting from 124, 125 for uchar, to 2,xxx,xxx,xxx if I use long int. What is the value actually given by the minMaxLoc function? Please help me.

like image 701
Lakshmi Narayanan Avatar asked Jan 16 '13 17:01

Lakshmi Narayanan


2 Answers

min and estimate should be of type double and I would imagine they are correct. The issue is probably with you accessing

dst.at<datatype>(k,l)

As Abhishek Thakur mentioned, the output depends on your input. If you are ever confused about the type of a matrix you can look at dst.type() which returns an integer corresponding to the list defined in types_c.h starting at line 557. The definitions for single channel types or "depths" are

#define CV_8U   0
#define CV_8S   1 
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6

You can see the formula used to calculate the other type identifiers on line 573

#define CV_CN_SHIFT   3
#define CV_DEPTH_MAX  (1 << CV_CN_SHIFT)

#define CV_MAT_DEPTH_MASK       (CV_DEPTH_MAX - 1)
#define CV_MAT_DEPTH(flags)     ((flags) & CV_MAT_DEPTH_MASK)

#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))

for example

#define CV_8UC4 CV_MAKETYPE(CV_8U,4)

has type

0+((4-1) << 3) == 24

so for a 4 channel uchar image, type() will return 24. From the above you can see that the depth of a type is represented by the last 3 bits of the type integer. If all you want is the depth (you don't care how many channels it has) you can get that directly with dst.depth()

like image 185
Hammer Avatar answered Sep 28 '22 09:09

Hammer


Hammer answer is very clear and it shows you a nice tips: always check the datatypes and be aware of types_c.h, check it out every time you want!

Anyway, minMaxLoc returns a double but it already do the cast for you. If you give a uchar Mat objects as input array it will set the 2 double variables as double in the range 0-255 (the uchar range!).

See this example:

#include <opencv2/core/core.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int /*argc*/, char** /*argv*/) {

    double m, M;
    Point p_min, p_max;
    Mat img;

    // let's do with uchar Mat
    img = (Mat_<uchar>(3,3) << 0,1,2,3,4,5,6,7,255); 
    cout << img << endl;
    minMaxLoc(img, &m, &M, &p_min, &p_max);
    cout << "min: " << m << " at " << p_min << endl;
    cout << "max: " << M << " at " << p_max << endl;
    cout << (int)img.at<uchar>(p_max.y, p_max.x) << endl; // cast to int otherwise cout will print an ASCII (uchar)

    // now with float Mat
    img = (Mat_<float>(3,3) << 0.1f,1.2f,2,3000.2f,4,5,6,7,255); 
    cout << img << endl;
    minMaxLoc(img, &m, &M, &p_min, &p_max);
    cout << "min: " << m << " at " << p_min << endl;
    cout << "max: " << M << " at " << p_max << endl;
    cout << img.at<float>(p_max.y, p_max.x) << endl;

    return 0;
}

now, in the code you posted you define the destination type in the ddepth. You can specify ddepth as a opencv constant datatypes, like:

ddepth = CV_8UC1

in this case the cv::Laplacian will return a uchar Mat.

So, be always aware of what kind of data are you handling. If you are working with colour image you'd probabilly better to use Mat::at<Scalar>().

like image 38
nkint Avatar answered Sep 28 '22 09:09

nkint