首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BGR OpenCV Mat到特征张量的映射

BGR OpenCV Mat到特征张量的映射
EN

Stack Overflow用户
提问于 2019-06-09 11:22:38
回答 2查看 1.3K关注 0票数 1

我正在尝试将OpenCV 3通道Mat转换成三维特征张量。

到目前为止,我可以通过以下方式转换1通道灰度表:

代码语言:javascript
复制
    cv::Mat mat = cv::imread("/image/path.png", cv::IMREAD_GRAYSCALE);
    Eigen::MatrixXd myMatrix;
    cv::cv2eigen(mat, myMatrix);

我试图将BGR垫转换为张量垫的尝试是:

代码语言:javascript
复制
    cv::Mat mat = cv::imread("/image/path.png", cv::IMREAD_COLOR);
    Eigen::MatrixXd temp;
    cv::cv2eigen(mat, temp);
    Eigen::Tensor<double, 3> myTensor = Eigen::TensorMap<Eigen::Tensor<double, 3>>(temp.data(), 3, mat.rows, mat.cols);

但是,我得到了以下错误:

代码语言:javascript
复制
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: OpenCV(4.1.0) /tmp/opencv-20190505-12101-14vk1fh/opencv-4.1.0/modules/core/src/matrix_wrap.cpp:1195:
error: (-215:Assertion failed) !fixedType() || ((Mat*)obj)->type() == mtype in function 'create'

在行:cv::cv2eigen(mat, temp);

任何帮助都是非常感谢的!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-09 16:05:56

答案可能会让你失望。

经过12页,我的结论是,你必须分开RGB到单个通道垫,然后转换为特征矩阵。或者创建您自己的特征类型和opencv转换功能。

在OpenCV中,它是这样测试的。它只允许单通道灰度图像。

代码语言:javascript
复制
https://github.com/daviddoria/Examples/blob/master/c%2B%2B/OpenCV/ConvertToEigen/ConvertToEigen.cxx

在OpenCV中,它是这样实现的。对于定制类型(即cv::标量到本征std::vector ),您没有太多的选择。

代码语言:javascript
复制
https://github.com/stonier/opencv2/blob/master/modules/core/include/opencv2/core/eigen.hpp

根据这篇文章,

代码语言:javascript
复制
https://stackoverflow.com/questions/32277887/using-eigen-array-of-arrays-for-rgb-images

我认为本征不是以这种方式使用的(向量是“标量”类型)。

它们在处理RGB图像时也存在一定的困难。

请注意,Opencv标量和特征标量有不同的含义。

如果并且只有当您使用自己的数据类型

因此,您可以选择将3通道信息存储在3个特征矩阵中,并且可以使用默认的本征路由和opencv路由。

代码语言:javascript
复制
Mat src = imread("img.png",CV_LOAD_IMAGE_COLOR); //load  image
Mat bgr[3];   //destination array
split(src,bgr);//split source    
//Note: OpenCV uses BGR color order
imshow("blue.png",bgr[0]); //blue channel
imshow("green.png",bgr[1]); //green channel
imshow("red.png",bgr[2]); //red channel
Eigen::MatrixXd bm,gm,rm;
cv::cv2eigen(bgr[0], bm); 
cv::cv2eigen(bgr[1], gm); 
cv::cv2eigen(bgr[2], rm);

或者您可以定义自己的类型并编写自己版本的opencv cv2eigen函数。

自定义特征类型如下。它不会很漂亮

代码语言:javascript
复制
https://eigen.tuxfamily.org/dox/TopicCustomizing_CustomScalar.html
https://eigen.tuxfamily.org/dox/TopicNewExpressionType.html

重写您自己的cv2eigen_custom函数,类似于

代码语言:javascript
复制
https://github.com/stonier/opencv2/blob/master/modules/core/include/opencv2/core/eigen.hpp

祝你好运。

编辑

因为你需要张量。忘记cv函数

代码语言:javascript
复制
Mat image;
image = imread(argv[1], CV_LOAD_IMAGE_COLOR); 
Tensor<float, 3> t_3d(image.rows, image.cols, 3);

// t_3d(i, j, k) where i is row j is column and k is channel. 
for (int i = 0; i < image.rows; i++) 
  for (int j = 0; j < image.cols; j++) 
  {
       t_3d(i, j, 0) = (float)image.at<cv::Vec3b>(i,j)[0]; 
       t_3d(i, j, 1) = (float)image.at<cv::Vec3b>(i,j)[1];
       t_3d(i, j, 2) = (float)image.at<cv::Vec3b>(i,j)[2];
       //cv ref Mat.at<data_Type>(row_num, col_num)
  }

当心我,因为他们对订单不确定。我只根据引用来编写代码。没有为它进行编译。

也要注意图像类型到张量类型的转换问题。有时候你可能得不到你想要的。

这段代码原则上应该解决你的问题。

编辑2

遵循这个例子

代码语言:javascript
复制
int storage[128];  // 2 x 4 x 2 x 8 = 128
TensorMap<Tensor<int, 4>> t_4d(storage, 2, 4, 2, 8);

适用于你的案件是

代码语言:javascript
复制
cv::Mat frame=imread('myimg.ppm');
TensorMap<Tensor<float, 3>> t_3d(frame.data, image.rows, image.cols, 3);

问题是我不确定这会不会成功。即使它有效,您仍然需要弄清楚内部数据是如何组织的,这样才能正确地得到形状。祝好运

票数 1
EN

Stack Overflow用户

发布于 2020-06-16 06:25:06

更新的答案- OpenCV现在对特征::张量具有转换函数,这将解决您的问题。我也需要同样的功能,所以我为项目做出了贡献,供大家使用。请参阅这里的文件:

eigen.html

注意:如果您想要RGB顺序,在转换到特征::张量之前,仍然需要重新排序OpenCV中的通道。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56514170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档