c++ - cv::mat CV_8U 产品错误和缓慢的 CV_32F 产品

标签 c++ opencv

我正在尝试在 2772x128 矩阵和 4000x128 矩阵之间制作一个乘积。两者都是 SIFT 描述符矩阵,使用以下代码:

Mat a = Mat(nframes, descrSize, CV_8U, DATAdescr);
Mat b = Mat(vocabulary_size, descrSize, CV_8U, vocabulary);
Mat ab =a * b.t();

问题是在计算乘积时,它会抛出错误

err_msg = 0x00cdd5e0 "..\..\..\src\opencv\modules\core\src\matmul.cpp:711: error: (-215) type == B.type() && (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2)"

解决此问题的方法是将数据类型转换为 CV_32FC1

Mat a = Mat(nframes, descrSize, CV_8U, DATAdescr);
Mat b = Mat(vocabulary_size, descrSize, CV_8U, vocabulary);
a.convertTo(a, CV_32FC1);
b.convertTo(b, CV_32FC1);
Mat ab = a * b.t();

效果很好,但是耗时太多,大约1.2秒。我想尝试相同的产品但使用整数,看看是否可以加快速度。难道我做错了什么?我看不出有什么理由不能在 CV_8U 矩阵之间进行矩阵乘积。

编辑:答案与使用其他库或解决其他方法有关。我正在考虑打开一个新线程并提出解决我的问题的建议,但是有人可以回答我最初的疑问吗?我不能将 CV_8U 或 CV32S 矩阵相乘吗?真的吗?

最佳答案

在您的 other message 中你说下面的代码需要0.9秒。

MatrixXd A = MatrixXd::Random(1000, 1000);
MatrixXd B = MatrixXd::Random(1000, 500);
MatrixXd X;

我在我的机器上尝试了一些基准测试,在 Linux 上运行的 intel core i7。我的完整基准代码如下:

#include <Eigen/Dense>
using namespace Eigen;

int
main(int argc, char *argv[])
{
  MatrixXd A = MatrixXd::Random(2772, 128);
  MatrixXd B = MatrixXd::Random(4000, 128);
  MatrixXd X = A*B.transpose();
}

我只是使用 Linux 中的 time 命令,因此运行时间包括可执行文件的启动和停止。

1/不进行优化编译(gcc 编译器):

g++ -I/usr/include/eigen3 matcal.cpp -O0 -o matcal
time ./matcal
real    0m13.177s  -> this is the time you should be looking at
user    0m13.133s
sys     0m0.022s

13秒,太慢了。顺便说一句,如果没有矩阵乘法,则需要 0.048 秒,而矩阵更大则需要 0.9 秒的示例。为什么??

使用 Eigen 进行编译器优化非常重要。 2/进行一些优化编译:

g++ -I/usr/include/eigen3 matcal.cpp -O2 -o matcal
time ./matcal
real    0m0.324s
user        0m0.298s
sys     0m0.024s

现在 0.324s,更好了!

3/切换所有优化标志(至少是我所知道的所有优化标志,我不是该领域的专家)

g++ -I/usr/include/eigen3 matcal.cpp -O3 -march=corei7 -mtune=corei7 -o matcal 
time ./matcal
real    0m0.317s
user    0m0.291s
sys     0m0.024s

0.317,接近,但增加了几毫秒(在一些测试中始终如此)。因此,在我看来,您对 Eigen 的使用确实存在问题,要么您没有切换编译器优化,要么您的编译器没有自行执行此操作。

我不是 Eigen 专家,我只使用过它几次,但我认为文档非常好,您可能应该阅读它以充分利用它。

关于与 MatLab 的性能比较,上次我读到 Eigen 时它不是多线程的,而 MatLab 可能使用多线程库。对于矩阵乘法,您可以将矩阵分成几个 block ,并使用 TBB 并行化每个 block 的乘法

关于c++ - cv::mat CV_8U 产品错误和缓慢的 CV_32F 产品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12479663/

相关文章:

android - 为Android构建OpenCV并将其与NDK结合使用

c++ - 创建附加到控制台但具有重定向标准 IO 句柄的进程

c++ - 使用SFML绘制多个形状

c++ - 具有动态设施的 syslog-daemon 或每个软件自己的记录器?

opencv - OpenCV代码错误-为RtlFreeHeap指定的地址无效

c++ - OpenCV 边界框

C++ header 保持理智

c++ - 从 vector 访问时,我的可变类的属性没有改变。 (调试)

android - Android OpenCV:手部检测

opencv - 导入错误 : No module named 'cv2' using jupyter