Перевести преобразование массива numpy в эквивалент OpenCV

У меня возникла проблема, чтобы перевести функции Nndy 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 ++?

5

Решение

После тщательного обдумывания все оказалось проще, чем ожидалось. Меня смущал только забавный синтаксис с массивами.
Изменение формы массивов numpy — это просто способ python для доступа к отдельным каналам результирующего cv :: Mat «eigen».
Следующий код является C ++-версией OpenCV «texture_flow.py» (взятой из OpenCV 2.4.3). Полученное изображение потока не на 100% идентично версии Python, но оно достаточно близко.

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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]