【问题标题】:Converting OpenCV matrix looping to JavaCV将 OpenCV 矩阵循环转换为 JavaCV
【发布时间】:2012-03-29 06:53:26
【问题描述】:

不久前得到了 O'Reilly 的《Learning OpenCV》一书,从那时起,我一直忙于将我在其中看到的所有示例代码从 OpenCV 转换为 JavaCV,通常还会进行一些我自己的修改。一直以来,我都在尝试尽可能地使用纯 OpenCV(C 语言)代码并避免使用 Java。例如,我直接通过 JavaCV 中的 OpenCV highgui 包实现了所有界面元素,而不是通过 Java Swing。通过这样做,我希望在相对较短的时间内学习 OpenCV 库和一些 C,以及建立一个有用的函数库,如果我决定以后切换到纯 OpenCV,我将能够轻松地将其转换为 C。

无论如何,我对 C 的了解很少,在处理指针时有时会遇到麻烦。本书推荐以下代码作为迭代 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 );
}

下面是这段代码的解释:

当计算指向矩阵的指针时,记住矩阵元素数据 是一个工会。因此,在取消引用该指针时,必须指明正确的 union 的元素以获得正确的指针类型。然后,抵消那个 指针,必须使用矩阵的步长元素。如前所述,步骤 元素以字节为单位。为了安全起见,最好以字节为单位进行指针运算,然后将 > 转换为适当的类型,在本例中为浮点数。尽管 CVMat 结构具有 > 高度和宽度的概念以与旧的 IplImage 结构兼容,但我们 > 使用更新的行和列代替。最后,请注意,我们为 > 每一行重新计算 ptr,而不是简单地从开头开始然后递增该指针 每次阅读。这似乎有点过分,但因为 CvMat 数据指针可能只是 指向更大数组中的 ROI,无法保证数据将 > 跨行连续。

但是,我无法将其转换为 JavaCV。 ptr 字段(指针)似乎是一个浮点数,这让我感到困惑。我认为它实际上不是一个“指针”,而是一个添加每个像素值的值?或者它实际上是一个指针,s 值找到给定行内所有列的总和?

无论如何,如果有人为我发布一些用于等效循环的 JavaCV 代码,我将不胜感激。我知道还有其他方法可以访问 CvMat 中的每个像素,但据我所知,它们的效率都较低或不准确。

【问题讨论】:

  • 从示例中我可以看出,矩阵被寻址为二维、灰度、浮点数据类型。所有像素值相加为 s,这将成为累积亮度。 ptr 实际上是一个指向数组任意点的指针,ptr[x] 等于(const float*)(mat-&gt;data.ptr + row * mat-&gt;step)[x];。 ptr 为给定像素初始化并递增,因此[x] 不是必需的,它只是用* 取消引用,等于[0]
  • @zom 指针如何递增?根据我对代码的理解,指针被分配了像素的值?还是分配了像素的位置?如果是前面的情况,那么当ptr++操作发生时,分配的像素值会不会增加,而不是导致指针指向下一个像素?如果是后一种情况,那么像素的实际值何时何地分配给s?这么多问题。
  • 先阅读这个:c-faq.com/ptrs/index.html
  • 至于那个长句,读成这样:mat是矩阵。 -&gt;data 是 mat 中的数据字段。 .ptr 是 data 中的 ptr 字段,它是一个 char*(指向字符的指针,可以是单数或数组)。 + row * mat-&gt;step 对指向 x,y=0,row 的指定数组索引的指针执行算术运算。 (const float*) 转换为 [指向不允许更改的浮动的指针]。指针值不变,但使用时访问的是float,而不是char,在进行指针运算时,现在假设一个元素是float的长度(4字节)所以ptr++加4。跨度>

标签: java c pointers opencv javacv


【解决方案1】:

您提供的特定示例将被最佳转换为 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;
}

【讨论】:

  • 感谢 Sam,很高兴得到 JavaCV 开发人员本人的回答!我已经解决了这个问题
  • 好的,太好了!但无论如何你都应该接受答案,如果它回答了你最初发布的问题......
【解决方案2】:

这是我最终通过反复试验得到的一个变体;用于遍历 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;
}   

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    相关资源
    最近更新 更多