简体   繁体   English

将OpenCV矩阵循环转换为JavaCV

[英]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. 不久前收到了O'Reilly的书“ Learning OpenCV”,从那时起,我一直在忙于将我在那看到的所有示例代码从OpenCV转换为JavaCV,通常还要进行一些自己的修改。 All the while, I'm trying to keep to the pure OpenCV (C language) code as much as possible and avoid Java. 一直以来,我都在努力保持纯OpenCV(C语言)代码,并避免使用Java。 For example, I implemented all of the interface elements directly through the OpenCV highgui package in JavaCV, rather than via Java Swing. 例如,我直接通过JavaCV中的OpenCV highgui包而不是通过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. 通过这样做,我希望能以相对较短的顺序学习OpenCV库和一些C,并且希望建立有用的函数库,如果以后决定切换到纯OpenCV,我将能够轻松地将其转换为C。

Anyway, I have little knowledge of C and sometimes get into trouble when dealing with pointers. 无论如何,我几乎不了解C,有时在处理指针时会遇到麻烦。 The book recommends the following code as an optimal means by which to iterate through a 3-channel matrix: 该书推荐以下代码作为迭代3通道矩阵的最佳方法:

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. 因此,要取消设置该指针,必须使用矩阵的step元素。 As noted previously, the step element is in bytes. 如前所述,step元素以字节为单位。 To be safe, it is best to do your pointer arithmetic in bytes and > then cast to the appropriate type, in this case float. 为了安全起见,最好以字节为单位进行指针算术运算,然后>强制转换为适当的类型,在这种情况下为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. 尽管CVMat结构具有高度和宽度的概念以与较早的IplImage结构兼容,但我们还是使用了最新的行和列。 Finally, note that we recompute ptr for > every row rather than simply starting at the beginning and then incrementing that pointer every read. 最后,请注意,我们重新计算了>每行的ptr,而不是简单地从头开始,然后在每次读取时递增该指针。 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. 看起来似乎有些多余,但是由于CvMat数据指针只能指向更大数组中的ROI,因此不能保证数据在行之间>连续。

However I am having trouble converting it to JavaCV. 但是我在将其转换为JavaCV时遇到了麻烦。 The ptr field (pointer) seems to be a float, which confuses me. ptr字段(指针)似乎是浮点数,这使我感到困惑。 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? 还是实际上是一个指针,其s值会找到给定行内所有列的总和?

Anyway, I would be appreciative if someone were to post for me some JavaCV code for an equivelent loop. 无论如何,如果有人为我发布一些JavaCV代码来实现等价循环,我将不胜感激。 I know there are other ways of accessing every pixel in a CvMat, but AFAIK they are all less efficient or inaccurate. 我知道还有其他方法可以访问CvMat中的每个像素,但AFAIK都效率较低或不准确。

The particular example you provide would be optimally converted to Java as 您提供的特定示例将最佳地转换为Java,如下所示:

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

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). 遍历3通道矩阵并应用非常简单的滤波器(我相信Samuel的示例已经很好地涵盖了灰度值的求和)。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM