2013-01-09 20 views
5

Sto riscontrando un problema nel tradurre le funzioni di ndarray di numpy nell'equivalente chiamate OpenCV C++ per rimodellare/dividere un cv :: Mat n-dimensionale in sezioni appropriate. In particolare sto provando a convertire l'esempio OpenCV python2 "texture_flow.py" (> = OpenCV 2.4.3) in C++. Ho segnato le linee in questione nello snippet qui sotto.Traduci la matrice di numpy reshape in equivalente OpenCV

# [......] 
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) 

# [......] 

Qualcuno può aiutarmi a tradurre le linee in questione in C++?

risposta

2

Dopo averlo pensato a lungo, è stato tutto più facile del previsto. È solo la divertente sintassi di array numpy che mi ha confuso. Rimodellamento degli array di numpy è solo il modo python per accedere ai singoli canali del risultante cv :: Mat "eigen". Il seguente codice è la versione C++ di OpenCV "texture_flow.py" (presa da OpenCV 2.4.3). L'immagine del flusso risultante non è identica al 100% alla versione python, ma è abbastanza vicina.

#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; 
}