从 NumPy 数组到 Mat (OpenCV) 的 C++ 转换
我正在围绕 ArUco 增强现实库(基于 OpenCV)编写一个薄包装.我正在尝试构建的界面非常简单:
I am writing a thin wrapper around ArUco augmented reality library (which is based on OpenCV). An interface I am trying to build is very simple:
- Python 将图像传递给 C++ 代码;
- C++ 代码检测标记并将它们的位置和其他信息作为字典元组返回给 Python.
但是,我无法弄清楚如何在 Python 中表示图像以将其传递给 C++.对于 GUI 和相机管理,我将使用 PyQt,所以最初它将是 QImage,但我不能简单地将它传递给 OpenCV(或者我可以?).一开始,我尝试使用嵌套元组来表示每个像素的行、列和颜色,所以我最终得到了这个示例代码:
However, I couldn't figure out how to represent an image in Python to pass it to C++. For GUI and camera management I am going to use PyQt, so initially it is going to be QImage, but I can't simply pass it to OpenCV (or I can?). At first, I tried to use nested tuples to represent row, column and color of each pixel, so I ended up with this sample code:
using namespace cv;
namespace py = boost::python;
void display(py::tuple pix)
{
/*
Receive image from Python and display it.
*/
Mat img(py::len(pix), py::len(pix[0]), CV_8UC3, Scalar(0, 0, 255));
for (int y = 0; y < py::len(pix); y++)
for (int x = 0; x < py::len(pix[y]); x++)
{
Vec3b rgb;
for (int i = 0; i < 3; i++)
rgb[i] = py::extract<int>(pix[y][x][i]);
img.at<Vec3b>(Point(x, y)) = rgb;
}
imshow("Image", img);
waitKey(0);
}
BOOST_PYTHON_MODULE(aruco)
{
py::def("display", display);
}
事实证明它非常缓慢(单帧几秒钟),所以我去谷歌搜索并找到了应该更快的解决方案:使用 NumPy 数组,所以代码看起来像这样:
It turned out to be painfully slow (a few seconds for a single frame), so I went googling and found solution that should be much faster: use NumPy arrays, so the code would look something like that:
void display(py::object array)
{
Mat img;
// ... some magic here to convert NumPy array to Mat ...
imshow("Image", img);
waitKey(0);
}
但是,我不知道如何将 NumPy 数组(在 C++ 级别只是一个 Python 对象)转换为 OpenCV Mat.我将不胜感激.
However, I have no idea how to convert NumPy Array (which in C++ level is just a Python Object) to OpenCV Mat. I would appreciate any help here.
或者,也许真的不需要 NumPy,所以我可以直接将 QImage Python 对象传递给 C++ 层?或者也许有一个不同的方法来解决这个问题?任何建议表示赞赏!
Alternatively, maybe NumPy is not really needed, so I could just pass QImage Python object directly to C++ layer? Or maybe there is a different approach to this problem? Any advice is appreciated!
推荐答案
在您的情况下最好的解决方案是为 cv::Mat 对象使用自定义 boost::python 转换器.OpenCV 具有 Python 包装器,当您使用此包装器时,您正在对 Numpy 数组进行操作 - 您甚至不需要知道这些数组在跨越 c++ <-> python 边界"时被转换为 cv::Mat 对象.为简单类型编写这样的转换器很容易,但是为 cv::Mat 创建转换器并不简单.幸运的是其他人已经这样做了 - 这里是 OpenCV 2.x 和 此处 适用于 3.x.如果你不熟悉 boost::python 转换器,这篇文章 应该对您有所帮助.
希望对您有所帮助,如果您有任何问题,请告诉我们.
The best solution in your situation is using custom boost::python converter for cv::Mat object. OpenCV has Python wrapper and when you are using this wrapper you are operating on Numpy arrays - you don't even need to know that those arrays are converted to cv::Mat objects while "crossing the c++ <-> python border". Writing such converter for simple type is quite easy, however creating converter for cv::Mat isn't simple. Fortunetely someone else already did this - here is version for OpenCV 2.x and here for 3.x. If you are not familiar with boost::python converters, this article should help you.
Hope it helps, if you wil have any problems, let us know.
相关文章