簡體   English   中英

將numpy的數組轉換為OpenCV等效轉換

[英]Translate numpy's array reshape to OpenCV equivalent

我有一個問題是將numpy的ndarray函數轉換為等效的OpenCV C ++調用,以將n維cv :: Mat重新整形/拆分成適當的切片。 特別是我試圖將OpenCV python2示例“texture_flow.py”(> = OpenCV 2.4.3)轉換為C ++。 我在下面的代碼段中標記了有問題的行。

# [......]
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 ++嗎?

在徹底考慮之后,這比預期的要容易得多。 這只是有趣的numpy數組語法令我感到困惑。 重新編寫numpy的數組只是訪問生成的cv :: Mat“eigen”的單個通道的python方式。 以下代碼是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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM