mercredi 6 mai 2015

ROI-based KLT optical tracker in opencv

How can i add roi-based selection in lkdemo.pp( klt optical flow tracker opencv example) source code? I want select roi in the first frame and track feature point that selected in roi.

sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss

#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <ctype.h>

using namespace cv;
using namespace std;

static void help()
{
    // print a welcome message, and the OpenCV version
    cout << "\nThis is a demo of Lukas-Kanade optical flow lkdemo(),\n"
            "Using OpenCV version " << CV_VERSION << endl;

}

Point2f point;
bool addRemovePt = false;

static void onMouse( int event, int x, int y, int , void* )
{
    if( event == CV_EVENT_LBUTTONDOWN )
    {
        point = Point2f((float)x, (float)y);
        addRemovePt = true;
    }
}

int main( int argc, char** argv )
{
    help();

    VideoCapture cap(CV_CAP_ANY);
    TermCriteria termcrit(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 20, 0.03);
    Size subPixWinSize(10,10), winSize(61,61);

    const int MAX_COUNT = 500;
    bool needToInit = false;
    bool nightMode = false;

    //if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
        //cap.open(argc == 2 ? argv[1][0] - '0' : 0);
    //else if( argc == 2 )
        //cap.open(argv[1]);

    if( !cap.isOpened() )
    {
        cout << "Could not initialize capturing...\n";
        return 0;
    }

    namedWindow( "LK Demo", 1 );
    setMouseCallback( "LK Demo", onMouse, 0 );

    Mat gray, prevGray, image;
    vector<Point2f> points[2];

    for(;;)
    {
        Mat frame;
        cap >> frame;
        if( frame.empty() )
            break;

        frame.copyTo(image);
        cvtColor(image, gray, COLOR_RGB2GRAY);

        if( nightMode )
            image = Scalar::all(0);

        if( needToInit )
        {
            // automatic initialization
            goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.04);
            cornerSubPix(gray, points[1], subPixWinSize, Size(-1,-1), termcrit);
            addRemovePt = false;
        }
        else if( !points[0].empty() )
        {
            vector<uchar> status;
            vector<float> err;
            if(prevGray.empty())
                gray.copyTo(prevGray);
            calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize,10, termcrit, 0, 0.001);
            size_t i, k;
            for( i = k = 0; i < points[1].size(); i++ )
            {
                if( addRemovePt )
                {
                    if( norm(point - points[1][i]) <= 5 )
                    {
                        addRemovePt = false;
                        continue;
                    }
                }

                if( !status[i] )
                    continue;

                points[1][k++] = points[1][i];
                circle( image, points[1][i], 3, Scalar(0,255,0), -1, 8);
            }
            points[1].resize(k);
        }

        if( addRemovePt && points[1].size() < (size_t)MAX_COUNT )
        {
            vector<Point2f> tmp;
            tmp.push_back(point);
            cornerSubPix( gray, tmp, winSize, cvSize(-1,-1), termcrit);
            points[1].push_back(tmp[0]);
            addRemovePt = false;
        }

        needToInit = false;
        imshow("LK Demo", image);

        char c = (char)waitKey(10);
        if( c == 27 )
            break;
        switch( c )
        {
        case 'r':
            needToInit = true;
            break;
        case 'c':
            points[0].clear();
            points[1].clear();
            break;
        case 'n':
            nightMode = !nightMode;
            break;
        }

        std::swap(points[1], points[0]);
        cv::swap(prevGray, gray);
    }

    return 0;
}

Counting the basic operations of a given program

I am looking at the following: Operations Counting Example

Which is supposed to present the operations count of the following pseudocode:

Algorithm prefixAverages(A)
 Input array A of n numbers
 Output array B of n numbers such that B[i] is the average
 of elements A[0], A[1], … , A[i]

for i = 0 to n - 1 do
   b = 0
   for j = 0 to i do
       b = b + A[j]
       j++;
   B[i] = b / (i + 1)
return B

But I don't see how the counts on the inner for loop are reached. It says that for case i=0; j=0; the inner for loop runs twice? But it strikes me that it should only run once to see that 0 < 0. Can anyone provide insight into where the given operations count comes from or provide their own operations count?

This is under the assumption that primitive operations are:

  • Assignment
  • Array access
  • Mathematical operators (+, -, /, *)
  • Comparison
  • Increment/Decrement (math in disguise)
  • Return statements

Let me know if anything is unclear or you need more information

White Flicker after CombineRgn function

It seems the flickering is generated by the CombineRgn function, but I really have no idea why this happens, since i've never used regions that much I'm possibly missing some knowledge on the matter.

Some events in the program triggers the addition of little rectangles to the main region, here's the code that handles that:

        HRGN ActualRegion = CreateRectRgn(0, 0, 0, 0);
        GetWindowRgn(hwnd, ActualRegion);
        HRGN AddedRect = CreateRectRgn(//long code that creates a rectangle)
        CombineRgn(ActualRegion, ActualRegion, AddedRect, RGN_OR);

        SetWindowRgn(hwnd, ActualRegion, FALSE);
        InvalidateRect(hwnd, NULL, FALSE);

White Flickering appears only after the invalidation if new regions where combined to the main one.

Here's how I'm implementing double buffering in WM_PAINT:

PLEASE NOTE that on creation i'm enabling the DWM blur behind function with an invalid region (different from the Main one) which means that everything painted with BLACK_BRUSH will result in a 100% "invisible" portion of the program

        RECT r; GetClientRect(hwnd, &r);

        PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps);
        HDC MemDc = CreateCompatibleDC(hdc);
        HBITMAP hBmp = CreateCompatibleBitmap(hdc, r.right, r.bottom);
        HBITMAP hOld = (HBITMAP)SelectObject(MemDc, hBmp);

        //Making sure this dc is filled with "invisible" pixels to display
        SelectObject(MemDc, GetStockObject(BLACK_BRUSH));
        Rectangle(MemDc, //arbitrary values that matches the entire screen);

        BitBlt(hdc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), MemDc, 0, 0,        SRCCOPY);

        //clean-up
        SelectObject(MemDc, hOld);
        DeleteObject(hBmp);
        DeleteDC(MemDc);
        EndPaint(hwnd, &ps);

WM_ERASEBKGND obviously returns TRUE without further handling, the WNDCLASSEX instance of the window has a default BLACK_BRUSH as the hbrBackground field.

I also tried to intercept and return TRUE from WM_NCPAINT message.

I'm doing everything necessary to avoid intermediate drawcalls, everything handled inside the WM_PAINT uses a backbuffer, also i'd like to mention i'm not working with images/bitmaps. Everything is drawn with gdi/gdi+, and in no place i'm actually issuing a "white" redraw that may possibly cause said flicker. I'm a bit lost here

Is it something that i'm possibly missing ? I can't really understand what may be causing white flickering in this scenario

Can not declare more than 1.5Million threads in C++

I have run into an issue where I can't declare more than 1.5 million threads. My code compiles fine, but terminates immediately, as soon as I change 1.5 to 1.6 Million. Here is a part of code that is giving me grief.

#include <thread>
#include <mutex>

void run_parallel(arg1, arg2)
{
....
}

int main(int argc, char *argv[]) {

thread t[9000000];
int x =0;
for(int i=0; i< 3000; i++)
    for (int j=0; j<3000; j++)
    {
    t[x] = thread(run_parallel, arg,arg2)
    t[x].join();
    x++;
    }
}

As you can see, I clearly need 9,000,000 threads to run this, but it is not executing. Any help would be mi=uch appreciated.

Is my normal interpolation perspectively correct

I am trying to implement a software renderer

It looks like this, it seems my interpolated normal is not perspectively correct enter image description here

I use scanline conversion and calculate normal with following steps:

Assume we are now drawing line AB (A B have same y value in screen space)

  1. Calculating normal of B by interpolating normals of Top vertex and bottom vertex. (Alpha and Beta value is retrieve from top and bottom in screen space)

  2. to calculate A is similar

  3. draw line AB. Calculating the normals of fragments by interpolating normals of A and B

  4. calc light contribution

Sorry for my bad english, hope the picture helps

enter image description here

If I am doing wrong, how to do correct interpolation?

Return type of decltype when applied to ternary(?:) expression

When I look into a code snippet for a possible implementation of std::common_type

template <class ...T> struct common_type;

template <class T>
struct common_type<T> {
    typedef decay_t<T> type;
};

template <class T, class U>
struct common_type<T, U> {
    typedef decay_t<decltype(true ? declval<T>() : declval<U>())> type;
};

template <class T, class U, class... V>
struct common_type<T, U, V...> {
    typedef common_type_t<common_type_t<T, U>, V...> type;
};

The part how to get a common type for two template argument makes me confused.It is a usage of ternary operator with decltype.

As I known, whether to return the second or third operand is decided by the value of first operand. In this snippet, the first operand is true which means the return value of expression will always be declval<T>(). If it is what i thought which make no sense... Therefore, I have tried the following test

int iii = 2;
float fff = 3.3;
std::cout << typeid(decltype(false? std::move(iii):std::move(fff))).name() << std::endl;
std::cout << typeid(decltype(std::move(iii))).name() << std::endl;
std::cout << typeid(decltype(false ? iii : fff)).name() << std::endl;
std::cout << typeid(decltype(true ? iii : fff)).name() << std::endl;

// [02:23:37][ryu@C++_test]$ g++ -std=c++14 -g common_type.cpp
// output 
// f
// i
// f
// f

Comparing with the running result, The result what i though should be like as follows

int iii = 2;
float fff = 3.3;
std::cout << typeid(decltype(false ? iii : fff)).name() << std::endl; // should return i;
std::cout << typeid(decltype(true ? iii : fff)).name() << std::endl;  // should return f;

Anyone when can help to explain why the running result is different ?

In other words, what's the return result of decltype when it is applied on a ternary expression?

Ambiguous call to abs

I have a custom data type that in practice can be either float or double. On every OS except OSX, I am able to successfully build this C++11 template:

template< class REAL_T >
inline REAL_T inhouse_abs( REAL_T i_val )
{
    return (REAL_T)std::abs( (REAL_T)i_val );
}

However, clang 6.0 (3.5 LLVM) reports an ambiguous function call. If I change abs to fabs, the error is resolved on OSX, but now an identical error shows up on my Linux clang, gcc, and Visual Studio.

Any ideas?