Ask Your Question

MrOzBarry's profile - activity

2015-08-21 08:58:59 -0600 received badge  Famous Question (source)
2014-05-27 07:30:20 -0600 received badge  Notable Question (source)
2013-12-17 02:07:50 -0600 received badge  Popular Question (source)
2013-03-13 13:13:53 -0600 commented question OpenCV reliably detect finger tips in webcam video

Thanks for the link, that might be useful!

2013-03-13 07:30:16 -0600 asked a question OpenCV reliably detect finger tips in webcam video

I am developing an application that tracks fingers on a desktop/laptop keyboard for touch typing exercises. For demo purposes, I am detecting skin by thresholding the HSV hue value, which is working fairly well, and gives me a good image to work with:

hue image

From here, I am grabbing a contour that is fairly accurate (although sometimes it is segmented, not sure how to deal with that yet), I get a convex hull of this threshold which is as accurate as the contour allows, and then detect convexity defects to try and find fingers and edges.

The problem I have is that I need to be able to identify at least the pinky, ring, middle, and index fingers (thumb doesn't matter so much), but my results often times only find one or two fingers on each hand.

Here is my relevant code:

void FingerMap::findFingers( const cv::Mat& mask, Rect leftRegion, Rect rightRegion )
{
    cv::Mat grey_eql, grey_eql_smooth;

    cv::blur( mask, grey_eql_smooth, cv::Size(3, 3) );

    cv::Mat left, right;

    left = grey_eql_smooth.clone()( (const cv::Rect&)leftRegion );
    right = grey_eql_smooth.clone()( (const cv::Rect&)rightRegion );

    findFingersHand( "left-hand", left, fingers[0], leftRegion.topleft() );
    findFingersHand( "right-hand", right, fingers[1], rightRegion.topleft() );

    cv::imshow( "foreground-smoothed", grey_eql_smooth );
    cv::imshow( "fingerContour", copy );
}

void FingerMap::findFingersHand( const std::string& label, cv::Mat& maskPortion, std::vector<cv::Point2f>& fingerPositions, cv::Point offset )
{
    cv::Mat thresh;
    std::vector< std::vector< cv::Point > > contours;
    std::vector< cv::Vec4i > hierarchy;

    cv::threshold( maskPortion, thresh, 150.0, 255, cv::THRESH_BINARY /*| CV_THRESH_OTSU*/ );

    cv::findContours(
        thresh,
        contours,
        hierarchy,
        /*CV_RETR_CCOMP*/ CV_RETR_EXTERNAL,
        CV_CHAIN_APPROX_SIMPLE,
        offset
    );

    int count=0;
    std::vector<cv::Point2f> possibleFingers;
    double largestArea[2] = { 500.0, 500.0 };
    int largestAreaIndex[2] = { -1, -1 };
    for(unsigned int c=0; c < contours.size(); c++)
    {
        if ( contours[c].size() < 3 ) continue;
        double area = cv::contourArea( contours[c] );
        if ( area > largestArea[0] )
        {
            largestArea[1] = largestArea[0];
            largestAreaIndex[1] = largestAreaIndex[0];
            largestArea[0] = area;
            largestAreaIndex[0] = (int)c;
        }
        else if ( area > largestArea[1] )
        {
            largestArea[1] = area;
            largestAreaIndex[1] = (int)c;
        }
    }

    for(unsigned int id=0; id < 2; id++)
    {
        if ( largestAreaIndex[id] == -1 )
        {
            continue;
        }
        std::vector<int> hull;
        std::vector<cv::Vec4i> defects;
        cv::convexHull( cv::Mat( contours[ largestAreaIndex[id] ] ), hull, false );

        cv::convexityDefects( contours[ largestAreaIndex[id] ], hull, defects );
        for(unsigned int i=1; i < (defects.size()-1); i++)
        {
            if ( ( defects[i][3] / 256.0f ) < 10.0f ) continue; // ?
            possibleFingers.push_back( contours[ largestAreaIndex[id] ][ defects[i][0] ] );
            possibleFingers.push_back( contours[ largestAreaIndex[id] ][ defects[i][1] ] );
        }
    }

    // Find grouped possible fingers
    int maskHeight = maskPortion.size().height - 20;
    if ( possibleFingers.size() > 0 )
    {
        fingerPositions.clear();
        unsigned int fingerStart = 0;
        for(unsigned int pf=1; pf < possibleFingers.size(); pf++)
        {
            if ( ( possibleFingers[pf-1].y >= maskHeight ) || ( possibleFingers[pf].y >= maskHeight ) ) continue;
            float d = distance( possibleFingers[pf-1], possibleFingers[pf] );
            if ( d > 15.0f )
            {
                cv::Point fingerPoint = possibleFingers[fingerStart];
                float numPoints = 1.0f;
                for(unsigned int j=fingerStart+1; j < pf; j++)
                {
                    add( fingerPoint, possibleFingers[j] );
                    numPoints++;
                }
                divide( fingerPoint, numPoints );
                fingerPoint.y += 15;

                fingerPositions.push_back( fingerPoint );

                fingerStart = pf;
            }
        }
    }
}

Any ideas for improvements?

2013-03-12 13:15:46 -0600 commented question Building OpenCV from git on CygWin

It's just a regular usb webcam. I did some googling and it suggested that my usb webcam is not reachable through cygwin since it won't detect dshow or videoInput as valid options.

2013-03-12 07:04:09 -0600 commented answer Building OpenCV from git on CygWin

Well, I'm not using Code::Blocks, or an old version of mingw =/

2013-03-12 07:02:34 -0600 commented question Building OpenCV from git on CygWin

Updated with my mingw32 compiler version.

2013-03-12 07:01:29 -0600 received badge  Editor (source)
2013-03-11 15:58:57 -0600 asked a question Building OpenCV from git on CygWin

Here is my build log:

[ 14%] Building CXX object
modules/core/CMakeFiles/opencv_core.dir/src/algorithm.cpp.o
cd /home/Cineclick/opencv/build/modules/core && /usr/bin/c++.exe -Dopencv_core_EXPORTS -DHAVE_CVCONFIG_H -DHAVE_QT -DHAVE_QT_OPENGL -DCVAPI_EXPORTS -W -Wall -Wformat -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -march=i686 -fomit-frame-pointer -msse -msse2 -msse3 -mfpmath=sse -ffunction-sections -O2 -DNDEBUG  -DNDEBUG -I/home/Cineclick/opencv/modules/core/test
-I/home/Cineclick/opencv/modules/features2d/include
-I/home/Cineclick/opencv/modules/highgui/include
-I/home/Cineclick/opencv/modules/flann/include
-I/home/Cineclick/opencv/modules/imgproc/include
-I/home/Cineclick/opencv/modules/core/include
-I/home/Cineclick/opencv/modules/ts/include
-I/home/Cineclick/opencv/build/modules/core
-I/home/Cineclick/opencv/modules/core/src
-I/home/Cineclick/opencv/modules/gpu/include
-I/home/Cineclick/opencv/build    -o CMakeFiles/opencv_core.dir/src/algorithm.cpp.o
-c /home/Cineclick/opencv/modules/core/src/algorithm.cpp
In file included from
/home/Cineclick/opencv/modules/core/include/opencv2/core/core.hpp:4691,
                 from /home/Cineclick/opencv/modules/core/src/precomp.hpp:50,
                 from /home/Cineclick/opencv/modules/core/src/algorithm.cpp:43:
/home/Cineclick/opencv/modules/core/include/opencv2/core/operations.hpp:4024:
error: got 2 template parameters for `void cv::AlgorithmInfo::addParam(cv::Algorithm&, const char*, cv::Ptr<T>&, bool, cv::Ptr<T> (cv::Algorithm::*)(), void (cv::Algorithm::*)(const cv::Ptr<T>&), const std::string&)'
/home/Cineclick/opencv/modules/core/include/opencv2/core/operations.hpp:4024:
error:   but 1 required /home/Cineclick/opencv/modules/core/include/opencv2/core/operations.hpp:4033:
error: redefinition of `void cv::AlgorithmInfo::addParam(cv::Algorithm&, const char*, cv::Ptr<T>&, bool, cv::Ptr<T> (cv::Algorithm::*)(), void (cv::Algorithm::*)(const cv::Ptr<T>&), const std::string&)'
/home/Cineclick/opencv/modules/core/include/opencv2/core/operations.hpp:4024:
error: `void cv::AlgorithmInfo::addParam(cv::Algorithm&,
const char*, cv::Ptr<T>&, bool, cv::Ptr<T> (cv::Algorithm::*)(), void (cv::Algorithm::*)(const cv::Ptr<T>&), const std::string&)' previously
declared here modules/core/CMakeFiles/opencv_core.dir/build.make:60: recipe for target `modules/core/CMakeFiles/opencv_core.dir/src/algorithm.cpp.o'
failed make[2]: ***
[modules/core/CMakeFiles/opencv_core.dir/src/algorithm.cpp.o]
Error 1 make[2]: Leaving directory
`/home/Cineclick/opencv/build'
CMakeFiles/Makefile2:724: recipe for target `modules/core/CMakeFiles/opencv_core.dir/all' failed make[1]: ***
[modules/core/CMakeFiles/opencv_core.dir/all]
Error 2 make[1]: Leaving directory `/home/Cineclick/opencv/build'
Makefile:119: recipe for target `all'
failed make: *** [all] Error 2

Any ideas how to get this working?

Edit:

$ /usr/bin/i686-pc-mingw32-c++ -v
Using built-in specs.
COLLECT_GCC=/usr/bin/i686-pc-mingw32-c++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-mingw32/4.5.2/lto-wrapper.exe
Target: i686-pc-mingw32
Configured with: /usr/src/packages/mingw-gcc/mingw-gcc-4.5.2-1/src/gcc-4.5.2/configure --srcdir=/usr/src/packages/mingw-gcc/mingw-gcc-4.5.2-1/src/gcc-4.5.2 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/lib --datadir=/usr/share --localstatedir=/var --sysconfdir=/etc --datarootdir=/usr/share --docdir=/usr/share/doc/mingw-gcc -C --build=i686-pc-cygwin --host=i686-pc-cygwin --target=i686-pc-mingw32 --with-sysroot ...
(more)