我不久前得到了《学习OpenCV》这本O'Reilly出版的书籍,自那以后,我一直忙于将其中所有的示例代码从OpenCV转换为JavaCV,并且通常还会进行一些我自己的修改。同时,我尽可能地遵循纯OpenCV(C语言)代码,避免Java。例如,我通过JavaCV中的OpenCV highgui包直接实现了所有界面元素,而不是通过Java Swing。通过这样做,我希望能够在相对短的时间内学习OpenCV库和一些C语言,建立一个有用的函数库,如果以后决定转向纯OpenCV,我可以轻松地将其转换为C语言。
无论如何,我对C语言知之甚少,有时在处理指针时遇到麻烦。该书推荐以下代码作为迭代3通道矩阵的最佳方法:
这里是代码的解释:
在计算矩阵指针时,记住矩阵元素数据是一个联合体。因此,在取消引用此指针时,必须指示联合体的正确元素,以便获得正确的指针类型。然后,要偏移该指针,必须使用矩阵的步骤元素。如前所述,步长元素以字节为单位。为了安全起见,最好将指针算术运算转换为字节,然后再转换为适当的类型,即float。尽管CVMat结构具有与旧的IplImage结构兼容的高度和宽度概念,但我们改用更现代的行和列。最后,请注意,我们为每一行重新计算ptr,而不是仅从开头开始,然后在每次读取时递增该指针。这可能看起来过于复杂,但由于CvMat数据指针可以指向较大数组中的ROI,因此不能保证数据在行之间连续。
然而,我在将其转换为JavaCV时遇到了问题。 ptr字段(指针)似乎是一个浮点数,这让我感到困惑。我认为它实际上不是一个“指针”,而是将每个像素的值相加的值?或者它实际上是一个指针,s值在给定行内找到所有列的总和?
无论如何,如果有人为我发布一些JavaCV代码以进行等效循环,我将不胜感激。我知道还有其他访问每个像素的CvMat的方法,但据我所知,它们都不够高效或准确。
无论如何,我对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 );
}
这里是代码的解释:
在计算矩阵指针时,记住矩阵元素数据是一个联合体。因此,在取消引用此指针时,必须指示联合体的正确元素,以便获得正确的指针类型。然后,要偏移该指针,必须使用矩阵的步骤元素。如前所述,步长元素以字节为单位。为了安全起见,最好将指针算术运算转换为字节,然后再转换为适当的类型,即float。尽管CVMat结构具有与旧的IplImage结构兼容的高度和宽度概念,但我们改用更现代的行和列。最后,请注意,我们为每一行重新计算ptr,而不是仅从开头开始,然后在每次读取时递增该指针。这可能看起来过于复杂,但由于CvMat数据指针可以指向较大数组中的ROI,因此不能保证数据在行之间连续。
然而,我在将其转换为JavaCV时遇到了问题。 ptr字段(指针)似乎是一个浮点数,这让我感到困惑。我认为它实际上不是一个“指针”,而是将每个像素的值相加的值?或者它实际上是一个指针,s值在给定行内找到所有列的总和?
无论如何,如果有人为我发布一些JavaCV代码以进行等效循环,我将不胜感激。我知道还有其他访问每个像素的CvMat的方法,但据我所知,它们都不够高效或准确。
ptr[x]
等于(const float*)(mat->data.ptr + row * mat->step)[x];
。ptr被初始化为给定像素并递增,因此[x]
不是必需的,只需使用*
进行解引用,相当于[0]
。 - Mark Jeronimusptr++
发生时,不会使指定的像素值增加,而是会导致指针指向下一个像素吗?如果是后者,那么实际的像素值何时何地被分配给s
?太多问题了。 - flamming_pythonmat
是矩阵。->data
是从mat中获取的数据字段。.ptr
是从data中获取的ptr字段,它是一个char*(指向字符的指针,可以是单个或数组)。+ row * mat->step
对指针执行算术运算,以指向x、y=0、row的指定数组索引。(const float*)
将其强制转换为[不允许更改的float指针]。指针值不会改变,但在使用它时,将访问float而不是char,并且在执行指针算术时,现在假定一个元素是float的长度(4个字节),因此ptr++会增加4。 - Mark Jeronimus