OpenCV’s TextureFlow Example in C++
2013-03-29 – 22:15
Since version 2.4.3 OpenCV has a nice example for generating a texture flow image from an input image. This generates a grid-like distributed edge-gradient image from the input. Unfortunately this example is in Python with no C++ translation available. A while ago I have made an attempt to translate this to C++. The result is not 100% identical to the Python variant, but close enough:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | #include <opencv2/opencv.hpp> #include 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*3); ++i) { img.data[i] = (uchar)((192 + (int)img.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 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(p) * (d/2); float dy = channels[5].at(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; } |
(I have once asked for a solution for this at Stackoverflow and finally ended up answering my own question. The purpose of this (redundant) post here is that I can find it again easily without having to bother Stackoverflow’s search function (unfortunately this requires some quite specific search-/keywords due to my bad tagging… ) )