OpenCV 2.4.7 Mat::convertTo() 32 位到 16 位截断

标签 opencv matrix

我注意到使用 convertTo 将矩阵从 32 位转换为 16 位“舍入”数字到上限。因此,源矩阵中大于 0x0000FFFF 的值将在目标矩阵中设置为 0xFFFF。

我的应用程序想要的是屏蔽值,在目标中仅设置值的 2 LSB。

这是一个例子:

Mat mat32;
Mat mat16;

mat32 = Mat(2,2,CV_32SC1);

for(int y = 0; y < 2; y++)
  for(int x = 0; x < 2; x++)
    mat32.at<unsigned int>(cv::Point(x,y)) = 0x0000FFFE + (y*2+x);

mat32.convertTo(mat16, CV_16UC1);

矩阵具有这些值:

32 bits matrix:
0000FFFE        0000FFFF
00010000        00010001

16 bits matrix:
0000FFFE        0000FFFF
0000FFFF        0000FFFF

在我想要的16位矩阵的第二行

00000000  00000001

我可以通过逐值扫描源矩阵并屏蔽值来做到这一点,但性能很低。

是否有执行此操作的 OpenCV 函数?

谢谢大家!

混合

最佳答案

这是可以做到的,但这需要一些肮脏的技巧,所以是否使用这种方法取决于你。所以这是可以做到的:

对于此示例,让我们创建 1000x1000 32 位矩阵并将其所有值设置为 65541 (=256*256+5)。因此,在转换之后,我们希望得到一个由五组成的矩阵。

Mat M1(1000, 1000, CV_32S, Scalar(65541));

这里是技巧:

Mat M2(1000, 1000, CV_16SC2, M1.data);

我们在与 M1 相同的内存缓冲区上创建了矩阵 M2,但 M2“认为”这是一个 2 channel 16 位图像的缓冲区。现在要做的最后一件事是将您需要的 channel 复制到您需要的地方。这可以通过 split() 或 mixChannels() 函数来完成。例如:

Mat M3(1000, 1000, CV_16S);
int fromto[] = {0,0};
Mat inpu[] = {M2}, outpu[] = {M3};
mixChannels(inpu, 1, outpu, 1, fromto, 1);
cout << M3.at<short>(10,10) << endl;

是的,我知道 mixChannels 的格式看起来很奇怪并且使代码的可读性更差,但它确实有效......如果你更喜欢 split() 函数:

vector<Mat> v;
split(M2,v);
cout << v[0].at<short>(10,10) << " " << v[1].at<short>(10,10) << endl;

关于OpenCV 2.4.7 Mat::convertTo() 32 位到 16 位截断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21160034/

相关文章:

opencv - 如何在Opencv Mat对象的每一行中找到max的索引

python - Python 中二维矩阵的单元分配,没有 numpy

c - 在C中填充二维数组的算法

java - 如何从某个位置开始迭代二维数组?

python - 在处理 MNIST 数据集时 opencv 中出现大小错误

c++ - 如何在 OpenCV 中操作 RGB 级别?

opencv - 来自单应矩阵的相对 3D 旋转

c++ - opencv3.00中Facerecognizer类的getMat()的替代方法是什么?

python - 将 float 组复制到字符串数组

MATLAB:比较两个数组的所有元素