Attention! Mouse virus detected!

OpenCV’s TextureFlow Example in C++

2013-03-29 – 22:15
OpenCV's TextureFlow example screenshot (C++ variant)

OpenCV’s TextureFlow example screenshot (C++ variant)

 

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… ) )

Post a Comment

Insert a smiley:


To prevent spam and comments of people who don't
know about mathematics you have to enter the result
into the field on the right side.
Hint: Possible answers are '-3', '-2', '0', '1' and '6x'.
Some challenges have more than one correct answer!

Please note: Comments will be approved manually!
It may take a few hours to check if yours
is legitimate even after solving the captcha..
Spam protection

Captcha