gpt4 book ai didi

java - OpenCV 的 Java 绑定(bind) Mat.get() 给出了奇怪的结果

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:57:38 26 4
gpt4 key购买 nike

我有一个 8UC1 Mat 图像。我正在尝试将其转换为具有 [x][y] 坐标的 Java 2D 字节数组。到目前为止,这是我所拥有的:

byte[][] arr = new byte[mat.cols()][mat.rows()];
for (int colIndex = 0; colIndex < mat.cols(); colIndex++) {
mat.get(0, colIndex, arr[colIndex]);
}

但是,这给了我完全困惑的结果。例如带有 .dump() 的垫子,如下所示:

[255, 255, 255, 255, 255, 255, 255, 255, 255, 255;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
255, 255, 255, 255, 255, 255, 255, 255, 255, 255;
255, 255, 255, 255, 255, 255, 255, 255, 255, 255;
255, 255, 255, 255, 255, 255, 255, 255, 255, 255]

给我这个(不要介意 -1,没关系):

-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 
-1 -1 -1 -1 -1 -1 -1 -1 -1 0
-1 -1 -1 -1 -1 -1 -1 -1 0 0
-1 -1 -1 -1 -1 -1 -1 0 0 0
-1 -1 -1 -1 -1 -1 0 0 0 0

最佳答案

是关于Mat内部的内存布局和Mat.get的使用方式。
问题中的代码试图构建一个二维数组,其中第一个索引索引列,第二个索引索引行。
并且所述代码正在调用 Mat.get 期望在每次调用时填充一列。

内存布局。
对于单个 channel 的二维矩阵,在这种情况下,opencv 按行存储其值。并且每一行都被填充到一些适当的对齐方式。
为了便于解释,我们假设一行占用的 10 个字节被填充为总共 16 个字节。
我们的矩阵将像这样存储:

Position 0  : 255,255,255,255,255,255,255,255,255,255,?,?,?,?,?,?,  
Position 16 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,?,?,?,?,?,?,
Position 32 : 255,255,255,255,255,255,255,255,255,255,?,?,?,?,?,?,
Position 48 : 255,255,255,255,255,255,255,255,255,255,?,?,?,?,?,?,
Position 64 : 255,255,255,255,255,255,255,255,255,255,?,?,?,?,?,?,

位置相对于元素在 (0,0) 的位置。从该图中应该清楚,最后一个元素,即 (4,9) 处的元素,位于位置 73。
?表示未使用的值。所以我们不能对那里的值(value)做出任何保证。
Mat 也有可能使用大小为 0 的填充,并且在我对该代码所做的测试中就是这种情况。然后布局是这样的(布局2)

Position 0  : 255,255,255,255,255,255,255,255,255,255
Position 10 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Position 20 : 255,255,255,255,255,255,255,255,255,255
Position 30 : 255,255,255,255,255,255,255,255,255,255
Position 40 : 255,255,255,255,255,255,255,255,255,255

Mat.get
这实际上是猜测,因为 documentation不完整。我必须检查来源才能确定。
Mat.get(int i, int j, byte[] arr) 用存储的值填充数组 arr,从 (i,j) 开始,直到数组已满。
那么,当我们用值为 9 的 colIndex 调用 mat.get(0, colIndex, arr[colIndex]) 时会发生什么?
在上表中,(0,9) 处的元素位于位置 9。arr[colIndex] 是一个大小为 5 的数组,因此它将填充从位置 9 到13,它们是:[ 255,?,?,?,? ] 与布局 1 和 [255, 0, 0, 0, 0] 与布局 2。这就是为什么 OP 程序输出的最后一列是 [255, 0, 0, 0, 0]。请注意,在布局 2 中,当您按行顺序读取一行的最后一个元素并想要更多元素时,下一个元素将是下一行的第一个元素。
arr[9] 应该包含一列,第 10 列。但是对 Mat.get 的调用不会用这样的列填充它,而是用 (0,9) 处的值和按行顺序(而不是列顺序)跟随的值填充它,由于填充(布局 1),这些值未指定或者是下一行(布局 2)中的那些。

将第一个索引保留为列,将第二个索引保留为行的丑陋解决方案:

class SimpleSample
{

static
{
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}

public static void printArr( byte[][] arr )
{
for ( int y=0; y<arr[0].length; ++y )
{
for ( int x=0; x<arr.length; ++x )
System.out.print( arr[x][y] + ", " );
System.out.println("");
}

}

public static void main(String[] args)
{
Mat mat = new Mat(5, 10, CvType.CV_8UC1, new Scalar(255));
mat.row(1).setTo(new Scalar(0));
System.out.println( mat.dump() );
byte[][] arr = new byte[mat.cols()][mat.rows()];

byte[] tmp = new byte[1];
for ( int i=0; i<mat.rows(); ++i )
{
for ( int j=0; j<mat.cols(); ++j )
{
mat.get(i, j, tmp);
arr[j][i] = tmp[0];
}
}
printArr(arr);
}

}

我们得到了预期的输出:

[255, 255, 255, 255, 255, 255, 255, 255, 255, 255;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
255, 255, 255, 255, 255, 255, 255, 255, 255, 255;
255, 255, 255, 255, 255, 255, 255, 255, 255, 255;
255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

将 arr 的第一个索引更改为行,将第二个索引更改为列的解决方案。

class SimpleSample
{

static
{
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}

public static void printArr( byte[][] arr )
{
for ( int y=0; y<arr.length; ++y )
{
for ( int x=0; x<arr[y].length; ++x )
System.out.print( arr[y][x] + ", " ); // Was arr[x][y] in prev code.
System.out.println("");
}

}

public static void main(String[] args)
{
Mat mat = new Mat(5, 10, CvType.CV_8UC1, new Scalar(255));
mat.row(1).setTo(new Scalar(0));
System.out.println( mat.dump() );
byte[][] arr = new byte[mat.rows()][mat.cols()];

for ( int i=0; i<mat.rows(); ++i )
mat.get(i, 0, arr[i]);
printArr(arr);
}
}

我们得到相同的输出。
请注意,虽然这里我们必须将 arr 用作 arr[y][x](第一行,第二列,如 opencv 中一样),但这可能不是 OP 想要的。

关于java - OpenCV 的 Java 绑定(bind) Mat.get() 给出了奇怪的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32610057/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com