【问题标题】:Translate numpy's array reshape to OpenCV equivalent将 numpy 的数组重塑转换为等效的 OpenCV
【发布时间】:2012-12-23 10:49:26
【问题描述】:

我在将 numpy 的 ndarray 函数转换为等效函数时遇到问题 OpenCV C++ 调用将 n 维 cv::Mat 重新整形/拆分为适当的切片。 特别是我正在尝试转换 OpenCV python2 示例“texture_flow.py” (>= OpenCV 2.4.3) 到 C++。我在下面的 sn-p 中标记了有问题的行。

# [......]
img = cv2.imread(fn)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# simple width and height tuple
h, w = img.shape[:2]

eigen = cv2.cornerEigenValsAndVecs(gray, 15, 3)
print eigen.shape # prints: (height, widht, 6), i.e. 6 channels

# Problem 1:
# OpenCV's reshape function is not sufficient to do this.
# probably must be split into several steps...
eigen = eigen.reshape(h, w, 3, 2)  # [[e1, e2], v1, v2]
print eigen.shape # prints: (height, width, 3, 2)

# Problem 2:
# I assume this is meant to get the the v1 and v2 matrices 
# from the previous reshape
flow = eigen[:,:,2]
print flow.shape # prints: (height, width, 2), i.e. 2 channels

vis = img.copy()
# C++: vis.data[i] = (uchar)((192 + (int)vis.data[i]) / 2);
vis[:] = (192 + np.uint32(vis)) / 2

d = 12

# Problem 3:
# Can probably be split into 2 nested for-loops 
points =  np.dstack( np.mgrid[d/2:w:d, d/2:h:d] ).reshape(-1, 2)

# [......]

有人可以帮我将有问题的行翻译成 C++ 吗?

【问题讨论】:

    标签: c++ python arrays opencv numpy


    【解决方案1】:

    经过深思熟虑,一切都比预期的要容易。只有有趣的 numpy 数组语法让我感到困惑。 重塑 numpy 的数组只是 python 访问生成的 cv::Mat "eigen" 的单个通道的方法。 以下代码是 OpenCV 的“texture_flow.py”的 C++ 版本(取自 OpenCV 2.4.3)。生成的流图与python版本不是100%相同,但已经足够接近了。

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    int main (int argc, char** argv)
    {
        cv::TickMeter tm;
        tm.start();
        cv::Mat img = cv::imread(argv[1]);
        cv::Mat gray = cv::Mat();
        cv::cvtColor(img, gray, CV_BGR2GRAY);
        // to preserve the original image
        cv::Mat flow = gray.clone();
        int width = img.cols;
        int height = img.rows;
        int graySize = width * height;
        // "brighten" the flow image 
        // C++ version of:
        // vis[:] = (192 + np.uint32(vis)) / 2
        for (unsigned int i=0; i<graySize; ++i)
        {
             flow.data[i] = (uchar)((192 + (int)flow.data[i]) / 2);
        }
        cv::Mat eigen = cv::Mat(height, width, CV_32FC(6));
        cv::cornerEigenValsAndVecs(gray, eigen, 15, 3);
        // this is the equivalent to all the numpy's reshaping etc. to 
        // generate the flow arrays
        // simply use channel 4 and 5 as the actual flow array in C++
        std::vector<cv::Mat> channels;
        cv::split(eigen, channels);
    
        int d = 12;
        cv::Scalar col(0, 0, 0);
        // C++ version of:
        // points =  np.dstack( np.mgrid[d/2:w:d, d/2:h:d] ).reshape(-1, 2)
        // including the actual line drawing part
        for (unsigned int y=(d/2); y<flow.rows; y+=d)
        {
             for (unsigned int x=(d/2); x<flow.cols; x+=d)
             {
                 if (x < flow.cols && y < flow.rows)
                 {
                     cv::Point p(x, y);
                     float dx = channels[4].at<float>(p) * (d/2);
                     float dy = channels[5].at<float>(p) * (d/2);
                     cv::Point p0(p.x - dx, p.y - dy);
                     cv::Point p1(p.x + dx, p.y + dy);
                     cv::line(flow, p0, p1, col, 1);
                  }
             }
        }
        tm.stop();
        std::cout<<"Flow image generated in "<<tm.getTimeMilli()<<" ms."<<std::endl;
        cv::imshow("FLOW", flow);
        cv::waitKey();
        return 0;
    }
    

    【讨论】:

    • 能不能做个方法?
    猜你喜欢
    • 2011-11-27
    • 2022-01-03
    • 2023-03-14
    • 1970-01-01
    • 2016-10-15
    • 2020-02-09
    • 2020-07-17
    • 1970-01-01
    相关资源
    最近更新 更多