Question

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.

Was it helpful?

Solution

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;
}

OTHER TIPS

Here is a variant I got to eventually through trial & error; for iterating through a 3-channel matrix and applying a very simple filter (I believe Samuel's example already covers the summing of greyscale values nicely).

static IplImage setSaturate_sv(IplImage imgIn) {
    IplImage imgOut = cvCloneImage(imgIn);
    ByteBuffer pointer = imgOut.getByteBuffer();

    int height = imgIn.height();
    int width = imgIn.width();
    int widthStep = imgIn.widthStep();
    int nChannels = imgIn.nChannels();
    int rowIndex;

    for (int row = 0; row < height; row++) {
        rowIndex = row * widthStep;
        for (int col = 0; col < width; col++) {
            pointer.put((rowIndex + (col * nChannels) + 1), (byte)255);
            pointer.put((rowIndex + (col * nChannels) + 2), (byte)255);
            pointer.put((rowIndex + (col * nChannels) + 3), /* leave alone */);
        }
    }
    return imgOut;
}   
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top