Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting OpenCV matrix looping to JavaCV

Got the book 'Learning OpenCV' by O'Reilly not long ago, and since then I have been busy converting all of the example code I see there from OpenCV to JavaCV, usually followed by a little of my own modification too. All the while, I'm trying to keep to the pure OpenCV (C language) code as much as possible and avoid Java. For example, I implemented all of the interface elements directly through the OpenCV highgui package in JavaCV, rather than via Java Swing. By doing this I hope to both learn the OpenCV library and some C in relatively short order, as well as establishing a library of useful functions that I will be able to convert to C easily if I decide to later switch to pure OpenCV.

Anyway, I have little knowledge of C and sometimes get into trouble when dealing with pointers. The book recommends the following code as an optimal means by which to iterate through a 3-channel matrix:

float sum( const CvMat* mat ) {
    float s = 0.0f;
    for(int row=0; row<mat->rows; row++ ) {
        const float* ptr = (const float*)(mat->data.ptr + row * mat->step);
        for( col=0; col<mat->cols; col++ ) {
            s += *ptr++;
        }
    }
    return( s );
}

Here is the included explanation for this code:

When computing the pointer into the matrix, remember that the matrix element data is a union. Therefore, when de-referencing this pointer, you must indicate the correct element of the union in order to obtain the correct pointer type. Th en, to off set that pointer, you must use the step element of the matrix. As noted previously, the step element is in bytes. To be safe, it is best to do your pointer arithmetic in bytes and > then cast to the appropriate type, in this case float. Although the CVMat structure has > the concept of height and width for compatibility with the older IplImage structure, we > use the more up-to-date rows and cols instead. Finally, note that we recompute ptr for > every row rather than simply starting at the beginning and then incrementing that pointer every read. Th is might seem excessive, but because the CvMat data pointer could just point to an ROI within a larger array, there is no guarantee that the data will be > contiguous across rows.

However I am having trouble converting it to JavaCV. The ptr field (pointer) seems to be a float, which confuses me. I presume that it's not actually a 'pointer', but rather a value to which the value of each pixel is added? Or is it actually a pointer, which the s value finds the total sum of for all columns within a given row?

Anyway, I would be appreciative if someone were to post for me some JavaCV code for an equivelent loop. I know there are other ways of accessing every pixel in a CvMat, but AFAIK they are all less efficient or inaccurate.

like image 324
flamming_python Avatar asked Mar 29 '12 06:03

flamming_python


1 Answers

The particular example you provide would be optimally converted to Java as

float sum(CvMat mat) {
    final int rows = mat.rows();
    final int cols = mat.cols();
    final int step = mat.step()/4;
    FloatBuffer buf = mat.getFloatBuffer();
    float s = 0.0f;
    for (int row = 0; row < rows; row++) {
        buf.position(row * step);
        for (int col = 0; col< cols; col++) {
            s += buf.get();
        }
    }
    return s;
}
like image 107
Samuel Audet Avatar answered Nov 01 '22 13:11

Samuel Audet