2

I took an OpenCV hand tracking algorithm from here and made a dll from it. When I launch it as it is, it works good. But when I compile it as a dll and attach it to Unity, I get this ,Runtime Error, the program has requested the Runtime to terminate it in an unusual way

I put //crashes in trAck() function in algodll.cpp after lines which cause the Runtime Error

Here's what I got. Headers:

handGesture.hpp:

#ifndef _HAND_GESTURE_
#define _HAND_GESTURE_ 

#include <opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include <vector>
#include <string>
#include "algo.hpp"
#include "myImage.hpp"

using namespace cv;
using namespace std;

class HandGesture{
    public:
        MyImage m;
        HandGesture();
        vector<vector<Point> > contours;
        vector<vector<int> >hullI;
        vector<vector<Point> >hullP;
        vector<vector<Vec4i> > defects; 
        vector <Point> fingerTips;
        Rect rect;
        void printGestureInfo(Mat src);
        int cIdx;
        int frameNumber;
        int mostFrequentFingerNumber;
        int nrOfDefects;
        Rect bRect;
        double bRect_width;
        double bRect_height;
        bool isHand;
        bool detectIfHand();
        void initVectors();
        void getFingerNumber(MyImage *m);
        void eleminateDefects(MyImage *m);
        void getFingerTips(MyImage *m);
        void drawFingerTips(MyImage *m);
    private:
        string bool2string(bool tf);
        int fontFace;
        int prevNrFingerTips;
        void checkForOneFinger(MyImage *m);
        float getAngle(Point s,Point f,Point e);    
        vector<int> fingerNumbers;
        void analyzeContours();
        string intToString(int number);
        void computeFingerNumber();
        void drawNewNumber(MyImage *m);
        void addNumberToImg(MyImage *m);
        vector<int> numbers2Display;
        void addFingerNumberToVector();
        Scalar numberColor;
        int nrNoFinger;
        float distanceP2P(Point a,Point b);
        void removeRedundantEndPoints(vector<Vec4i> newDefects,MyImage *m);
        void removeRedundantFingerTips();
};




#endif

algo.hpp:

#include <opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>


#define ORIGCOL2COL CV_BGR2HLS
#define COL2ORIGCOL CV_HLS2BGR
#define NSAMPLES 7
#define PI 3.14159

extern "C"
{
    __declspec(dllexport) void trAck();
}

#endif

myImage.hpp:

#ifndef _MYIMAGE_
#define _MYIMAGE_ 

#include <opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include <vector>

using namespace cv;
using namespace std;

class MyImage{
    public:
        MyImage(int webCamera);
        MyImage();
        Mat srcLR;
        Mat src;
        Mat bw;
        vector<Mat> bwList;
        VideoCapture cap;       
        int cameraSrc; 
        void initWebCamera(int i);
};



#endif

roi.hpp:

#ifndef ROI 
#define ROI


#include <opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>

using namespace cv;

class My_ROI{
    public:
        My_ROI();
        My_ROI(Point upper_corner, Point lower_corner,Mat src);
        Point upper_corner, lower_corner;
        Mat roi_ptr;
        Scalar color;
        int border_thickness;
        void draw_rectangle(Mat src);
};



#endif

I will not put here code for stdafx.h and targetver.h, since they are standard Visual Studio-generated headers. My cpps: algodll.cpp

#include "stdafx.h"
#include <opencv2/imgproc/imgproc.hpp>

#include<opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include "myImage.hpp"
#include "roi.hpp"
#include "handGesture.hpp"
#include <vector>
#include <cmath>
#include "algo.hpp"



using namespace cv;
using namespace std;

/* Global Variables  */
int fontFace = FONT_HERSHEY_PLAIN;
int square_len;
int avgColor[NSAMPLES][3] ;
int c_lower[NSAMPLES][3];
int c_upper[NSAMPLES][3];
int avgBGR[3];
int nrOfDefects;
int iSinceKFInit;
struct dim{int w; int h;}boundingDim;
    VideoWriter out;
Mat edges;
My_ROI roi1, roi2,roi3,roi4,roi5,roi6;
vector <My_ROI> roi;
vector <KalmanFilter> kf;
vector <Mat_<float> > measurement;

/* end global variables */

void init(MyImage *m){
    square_len=20;
    iSinceKFInit=0;
}

// change a color from one space to another
void col2origCol(int hsv[3], int bgr[3], Mat src){
    Mat avgBGRMat=src.clone();  
    for(int i=0;i<3;i++){
        avgBGRMat.data[i]=hsv[i];   
    }
    cvtColor(avgBGRMat,avgBGRMat,COL2ORIGCOL);
    for(int i=0;i<3;i++){
        bgr[i]=avgBGRMat.data[i];   
    }
}

void printText(Mat src, string text){
    int fontFace = FONT_HERSHEY_PLAIN;
    putText(src,text,Point(src.cols/2, src.rows/10),fontFace, 1.2f,Scalar(200,0,0),2);
}

void waitForPalmCover(MyImage* m){
    m->cap >> m->src;
    flip(m->src,m->src,1);
    roi.push_back(My_ROI(Point(m->src.cols/3, m->src.rows/6),Point(m->src.cols/3+square_len,m->src.rows/6+square_len),m->src));
    roi.push_back(My_ROI(Point(m->src.cols/4, m->src.rows/2),Point(m->src.cols/4+square_len,m->src.rows/2+square_len),m->src));
    roi.push_back(My_ROI(Point(m->src.cols/3, m->src.rows/1.5),Point(m->src.cols/3+square_len,m->src.rows/1.5+square_len),m->src));
    roi.push_back(My_ROI(Point(m->src.cols/2, m->src.rows/2),Point(m->src.cols/2+square_len,m->src.rows/2+square_len),m->src));
    roi.push_back(My_ROI(Point(m->src.cols/2.5, m->src.rows/2.5),Point(m->src.cols/2.5+square_len,m->src.rows/2.5+square_len),m->src));
    roi.push_back(My_ROI(Point(m->src.cols/2, m->src.rows/1.5),Point(m->src.cols/2+square_len,m->src.rows/1.5+square_len),m->src));
    roi.push_back(My_ROI(Point(m->src.cols/2.5, m->src.rows/1.8),Point(m->src.cols/2.5+square_len,m->src.rows/1.8+square_len),m->src));


    for(int i =0;i<50;i++){
        m->cap >> m->src;
        flip(m->src,m->src,1);
        for(int j=0;j<NSAMPLES;j++){
            roi[j].draw_rectangle(m->src);
        }
        string imgText=string("Cover rectangles with palm");
        printText(m->src,imgText);  

        if(i==30){
        //  imwrite("./images/waitforpalm1.jpg",m->src);
        }

        imshow("img1", m->src);
        out << m->src;
        if(cv::waitKey(30) >= 0) break;
    }
}

int getMedian(vector<int> val){
  int median;
  size_t size = val.size();
  sort(val.begin(), val.end());
  if (size  % 2 == 0)  {
      median = val[size / 2 - 1] ;
  } else{
      median = val[size / 2];
  }
  return median;
}


void getAvgColor(MyImage *m,My_ROI roi,int avg[3]){
    Mat r;
    roi.roi_ptr.copyTo(r);
    vector<int>hm;
    vector<int>sm;
    vector<int>lm;
    // generate vectors
    for(int i=2; i<r.rows-2; i++){
        for(int j=2; j<r.cols-2; j++){
            hm.push_back(r.data[r.channels()*(r.cols*i + j) + 0]) ;
            sm.push_back(r.data[r.channels()*(r.cols*i + j) + 1]) ;
            lm.push_back(r.data[r.channels()*(r.cols*i + j) + 2]) ;
        }
    }
    avg[0]=getMedian(hm);
    avg[1]=getMedian(sm);
    avg[2]=getMedian(lm);
}

void average(MyImage *m){
    m->cap >> m->src;
    flip(m->src,m->src,1);
    for(int i=0;i<30;i++){
        m->cap >> m->src;
        flip(m->src,m->src,1);
        cvtColor(m->src,m->src,ORIGCOL2COL);
        for(int j=0;j<NSAMPLES;j++){
            getAvgColor(m,roi[j],avgColor[j]);
            roi[j].draw_rectangle(m->src);
        }   
        cvtColor(m->src,m->src,COL2ORIGCOL);
        string imgText=string("Finding average color of hand");
        printText(m->src,imgText);  
        imshow("img1", m->src);
        if(cv::waitKey(30) >= 0) break;
    }
}

void initTrackbars(){
    for(int i=0;i<NSAMPLES;i++){
        c_lower[i][0]=12;
        c_upper[i][0]=7;
        c_lower[i][1]=30;
        c_upper[i][1]=40;
        c_lower[i][2]=80;
        c_upper[i][2]=80;
    }
    createTrackbar("lower1","trackbars",&c_lower[0][0],255);
    createTrackbar("lower2","trackbars",&c_lower[0][1],255);
    createTrackbar("lower3","trackbars",&c_lower[0][2],255);
    createTrackbar("upper1","trackbars",&c_upper[0][0],255);
    createTrackbar("upper2","trackbars",&c_upper[0][1],255);
    createTrackbar("upper3","trackbars",&c_upper[0][2],255);
}


void normalizeColors(MyImage * myImage){
    // copy all boundries read from trackbar
    // to all of the different boundries
    for(int i=1;i<NSAMPLES;i++){
        for(int j=0;j<3;j++){
            c_lower[i][j]=c_lower[0][j];    
            c_upper[i][j]=c_upper[0][j];    
        }   
    }
    // normalize all boundries so that 
    // threshold is whithin 0-255
    for(int i=0;i<NSAMPLES;i++){
        if((avgColor[i][0]-c_lower[i][0]) <0){
            c_lower[i][0] = avgColor[i][0] ;
        }if((avgColor[i][1]-c_lower[i][1]) <0){
            c_lower[i][1] = avgColor[i][1] ;
        }if((avgColor[i][2]-c_lower[i][2]) <0){
            c_lower[i][2] = avgColor[i][2] ;
        }if((avgColor[i][0]+c_upper[i][0]) >255){ 
            c_upper[i][0] = 255-avgColor[i][0] ;
        }if((avgColor[i][1]+c_upper[i][1]) >255){
            c_upper[i][1] = 255-avgColor[i][1] ;
        }if((avgColor[i][2]+c_upper[i][2]) >255){
            c_upper[i][2] = 255-avgColor[i][2] ;
        }
    }
}

void produceBinaries(MyImage *m){   
    Scalar lowerBound;
    Scalar upperBound;
    Mat foo;
    for(int i=0;i<NSAMPLES;i++){
        normalizeColors(m);
        lowerBound=Scalar( avgColor[i][0] - c_lower[i][0] , avgColor[i][1] - c_lower[i][1], avgColor[i][2] - c_lower[i][2] );
        upperBound=Scalar( avgColor[i][0] + c_upper[i][0] , avgColor[i][1] + c_upper[i][1], avgColor[i][2] + c_upper[i][2] );
        m->bwList.push_back(Mat(m->srcLR.rows,m->srcLR.cols,CV_8U));    
        inRange(m->srcLR,lowerBound,upperBound,m->bwList[i]);   
    }
    m->bwList[0].copyTo(m->bw);
    for(int i=1;i<NSAMPLES;i++){
        m->bw+=m->bwList[i];    
    }
    medianBlur(m->bw, m->bw,7);
}

void initWindows(MyImage m){
    namedWindow("trackbars",CV_WINDOW_KEEPRATIO);
    namedWindow("img1",CV_WINDOW_FULLSCREEN);
}

void showWindows(MyImage m){
    pyrDown(m.bw,m.bw);
    pyrDown(m.bw,m.bw);
    Rect roi( Point( 3*m.src.cols/4,0 ), m.bw.size());
    vector<Mat> channels;
    Mat result;
    for(int i=0;i<3;i++)
        channels.push_back(m.bw);
    merge(channels,result);
    result.copyTo( m.src(roi));
    imshow("img1",m.src);   
}

int findBiggestContour(vector<vector<Point> > contours){
    int indexOfBiggestContour = -1;
    int sizeOfBiggestContour = 0;
    for (int i = 0; i < contours.size(); i++){
        if(contours[i].size() > sizeOfBiggestContour){
            sizeOfBiggestContour = contours[i].size();
            indexOfBiggestContour = i;
        }
    }
    return indexOfBiggestContour;
}

void myDrawContours(MyImage *m,HandGesture *hg){
    drawContours(m->src,hg->hullP,hg->cIdx,cv::Scalar(200,0,0),2, 8, vector<Vec4i>(), 0, Point());




    rectangle(m->src,hg->bRect.tl(),hg->bRect.br(),Scalar(0,0,200));
    vector<Vec4i>::iterator d=hg->defects[hg->cIdx].begin();
    int fontFace = FONT_HERSHEY_PLAIN;


    vector<Mat> channels;
        Mat result;
        for(int i=0;i<3;i++)
            channels.push_back(m->bw);
        merge(channels,result);
    //  drawContours(result,hg->contours,hg->cIdx,cv::Scalar(0,200,0),6, 8, vector<Vec4i>(), 0, Point());
        drawContours(result,hg->hullP,hg->cIdx,cv::Scalar(0,0,250),10, 8, vector<Vec4i>(), 0, Point());


    while( d!=hg->defects[hg->cIdx].end() ) {
        Vec4i& v=(*d);
        int startidx=v[0]; Point ptStart(hg->contours[hg->cIdx][startidx] );
        int endidx=v[1]; Point ptEnd(hg->contours[hg->cIdx][endidx] );
        int faridx=v[2]; Point ptFar(hg->contours[hg->cIdx][faridx] );
        float depth = v[3] / 256;
   /*   
        line( m->src, ptStart, ptFar, Scalar(0,255,0), 1 );
        line( m->src, ptEnd, ptFar, Scalar(0,255,0), 1 );
        circle( m->src, ptFar,   4, Scalar(0,255,0), 2 );
        circle( m->src, ptEnd,   4, Scalar(0,0,255), 2 );
        circle( m->src, ptStart,   4, Scalar(255,0,0), 2 );
*/
        circle( result, ptFar,   9, Scalar(0,205,0), 5 );


        d++;

     }
//  imwrite("./images/contour_defects_before_eliminate.jpg",result);

}

void makeContours(MyImage *m, HandGesture* hg){
    Mat aBw;
    pyrUp(m->bw,m->bw);
    m->bw.copyTo(aBw);
    findContours(aBw,hg->contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
    hg->initVectors(); 
    hg->cIdx=findBiggestContour(hg->contours);
    if(hg->cIdx!=-1){
//      approxPolyDP( Mat(hg->contours[hg->cIdx]), hg->contours[hg->cIdx], 11, true );
        hg->bRect=boundingRect(Mat(hg->contours[hg->cIdx]));        
        convexHull(Mat(hg->contours[hg->cIdx]),hg->hullP[hg->cIdx],false,true);
        convexHull(Mat(hg->contours[hg->cIdx]),hg->hullI[hg->cIdx],false,false);
        approxPolyDP( Mat(hg->hullP[hg->cIdx]), hg->hullP[hg->cIdx], 18, true );
        if(hg->contours[hg->cIdx].size()>3 ){
            convexityDefects(hg->contours[hg->cIdx],hg->hullI[hg->cIdx],hg->defects[hg->cIdx]);
            hg->eleminateDefects(m);
        }
        bool isHand=hg->detectIfHand();
        hg->printGestureInfo(m->src);
        if(isHand){ 
            hg->getFingerTips(m);
            hg->drawFingerTips(m);
            myDrawContours(m,hg);
        }
    }
}

//переименовать в функцию OnStart в моей опенСВ библиотеке всё до for(;;), остальное - в некую иную функцию, и запихнуть в апдейт. Всё как дллка
extern "C" {
    void trAck() {
        MyImage m(0);
        HandGesture hg;
        init(&m);
        m.cap >> m.src;
        namedWindow("img1", CV_WINDOW_KEEPRATIO);
        out.open("out.avi", CV_FOURCC('M', 'J', 'P', 'G'), 15, m.src.size(), true);
        waitForPalmCover(&m);//crashes
        average(&m);//crashes
        destroyWindow("img1");
        initWindows(m);
        initTrackbars();
        for (;;) {
            hg.frameNumber++;
            m.cap >> m.src;
            flip(m.src, m.src, 1);
            pyrDown(m.src, m.srcLR);//crashes
            blur(m.srcLR, m.srcLR, Size(3, 3));
            cvtColor(m.srcLR, m.srcLR, ORIGCOL2COL);//crashes
            produceBinaries(&m);
            cvtColor(m.srcLR, m.srcLR, COL2ORIGCOL);//crashes
            makeContours(&m, &hg);//crashes
            hg.getFingerNumber(&m);
            showWindows(m);//crashes
            out << m.src;
            //imwrite("./images/final_result.jpg",m.src);
            if (cv::waitKey(30) == char('q')) break;
        }
        destroyAllWindows();
        out.release();
        m.cap.release();

    }
}

handGesture.cpp:

#include "stdafx.h"
#include "handGesture.hpp"

#include <opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>

using namespace cv;
using namespace std;

HandGesture::HandGesture(){
    frameNumber=0;
    nrNoFinger=0;
    fontFace = FONT_HERSHEY_PLAIN;
}

void HandGesture::initVectors(){
    hullI=vector<vector<int> >(contours.size());
    hullP=vector<vector<Point> >(contours.size());
    defects=vector<vector<Vec4i> > (contours.size());   
}

void HandGesture::analyzeContours(){
    bRect_height=bRect.height;
    bRect_width=bRect.width;
}

string HandGesture::bool2string(bool tf){
    if(tf)
        return "true";
    else
        return "false";
}

string HandGesture::intToString(int number){
        stringstream ss;
        ss << number;
        string str = ss.str();
        return str;
}

void HandGesture::printGestureInfo(Mat src){
    int fontFace = FONT_HERSHEY_PLAIN;
    Scalar fColor(245,200,200);
    int xpos=src.cols/1.5;
    int ypos=src.rows/1.6;
    float fontSize=0.7f;
    int lineChange=14;
    string info= "Figure info:";
    putText(src,info,Point(ypos,xpos),fontFace,fontSize,fColor);
    xpos+=lineChange;
    info=string("Number of defects: ") + string(intToString(nrOfDefects)) ;
    putText(src,info,Point(ypos,xpos),fontFace,fontSize  ,fColor);
    xpos+=lineChange;
    info=string("bounding box height, width ") + string(intToString(bRect_height)) + string(" , ") +  string(intToString(bRect_width)) ;
    putText(src,info,Point(ypos,xpos),fontFace,fontSize ,fColor);
    xpos+=lineChange;
    info=string("Is hand: ") + string(bool2string(isHand));
    putText(src,info,Point(ypos,xpos),fontFace,fontSize  ,fColor);
}

bool HandGesture::detectIfHand(){
    analyzeContours();
    double h = bRect_height; 
    double w = bRect_width;
    isHand=true;
    if(fingerTips.size() > 5 ){
        isHand=false;
    }else if(h==0 || w == 0){
        isHand=false;
    }else if(h/w > 4 || w/h >4){
        isHand=false;   
    }else if(bRect.x<20){
        isHand=false;   
    }   
    return isHand;
}

float HandGesture::distanceP2P(Point a, Point b){
    float d= sqrt(fabs( pow(a.x-b.x,2) + pow(a.y-b.y,2) )) ;  
    return d;
}

// remove fingertips that are too close to 
// eachother
void HandGesture::removeRedundantFingerTips(){
    vector<Point> newFingers;
    for(int i=0;i<fingerTips.size();i++){
        for(int j=i;j<fingerTips.size();j++){
            if(distanceP2P(fingerTips[i],fingerTips[j])<10 && i!=j){
            }else{
                newFingers.push_back(fingerTips[i]);    
                break;
            }   
        }   
    }
    fingerTips.swap(newFingers);
}

void HandGesture::computeFingerNumber(){
    std::sort(fingerNumbers.begin(), fingerNumbers.end());
    int frequentNr; 
    int thisNumberFreq=1;
    int highestFreq=1;
    frequentNr=fingerNumbers[0];
    for(int i=1;i<fingerNumbers.size(); i++){
        if(fingerNumbers[i-1]!=fingerNumbers[i]){
            if(thisNumberFreq>highestFreq){
                frequentNr=fingerNumbers[i-1];  
                highestFreq=thisNumberFreq;
            }
            thisNumberFreq=0;   
        }
        thisNumberFreq++;   
    }
    if(thisNumberFreq>highestFreq){
        frequentNr=fingerNumbers[fingerNumbers.size()-1];   
    }
    mostFrequentFingerNumber=frequentNr;    
}

void HandGesture::addFingerNumberToVector(){
    int i=fingerTips.size();    
    fingerNumbers.push_back(i);
}

// add the calculated number of fingers to image m->src
void HandGesture::addNumberToImg(MyImage *m){
    int xPos=10;
    int yPos=10;
    int offset=30;
    float fontSize=1.5f;
    int fontFace = FONT_HERSHEY_PLAIN;
    for(int i=0;i<numbers2Display.size();i++){
        rectangle(m->src,Point(xPos,yPos),Point(xPos+offset,yPos+offset),numberColor, 2);   
        putText(m->src, intToString(numbers2Display[i]),Point(xPos+7,yPos+offset-3),fontFace,fontSize,numberColor);
        xPos+=40;
        if(xPos>(m->src.cols-m->src.cols/3.2)){
            yPos+=40;
            xPos=10;
        }
    }
}

// calculate most frequent numbers of fingers 
// over 20 frames
void HandGesture::getFingerNumber(MyImage *m){
    removeRedundantFingerTips();
    if(bRect.height > m->src.rows/2 && nrNoFinger>12 && isHand ){
        numberColor=Scalar(0,200,0);
        addFingerNumberToVector();
        if(frameNumber>12){
            nrNoFinger=0;
            frameNumber=0;  
            computeFingerNumber();  
            numbers2Display.push_back(mostFrequentFingerNumber);
            fingerNumbers.clear();
        }else{
            frameNumber++;
        }
    }else{
        nrNoFinger++;
        numberColor=Scalar(200,200,200);
    }
    addNumberToImg(m);
}

float HandGesture::getAngle(Point s, Point f, Point e){
    float l1 = distanceP2P(f,s);
    float l2 = distanceP2P(f,e);
    float dot=(s.x-f.x)*(e.x-f.x) + (s.y-f.y)*(e.y-f.y);
    float angle = acos(dot/(l1*l2));
    angle=angle*180/PI;
    return angle;
}

void HandGesture::eleminateDefects(MyImage *m){
    int tolerance =  bRect_height/5;
    float angleTol=95;
    vector<Vec4i> newDefects;
    int startidx, endidx, faridx;
    vector<Vec4i>::iterator d=defects[cIdx].begin();
    while( d!=defects[cIdx].end() ) {
        Vec4i& v=(*d);
        startidx=v[0]; Point ptStart(contours[cIdx][startidx] );
        endidx=v[1]; Point ptEnd(contours[cIdx][endidx] );
        faridx=v[2]; Point ptFar(contours[cIdx][faridx] );
        if(distanceP2P(ptStart, ptFar) > tolerance && distanceP2P(ptEnd, ptFar) > tolerance && getAngle(ptStart, ptFar, ptEnd  ) < angleTol ){
            if( ptEnd.y > (bRect.y + bRect.height -bRect.height/4 ) ){
            }else if( ptStart.y > (bRect.y + bRect.height -bRect.height/4 ) ){
            }else {
                newDefects.push_back(v);        
            }
        }   
        d++;
    }
    nrOfDefects=newDefects.size();
    defects[cIdx].swap(newDefects);
    removeRedundantEndPoints(defects[cIdx], m);
}

// remove endpoint of convexity defects if they are at the same fingertip
void HandGesture::removeRedundantEndPoints(vector<Vec4i> newDefects,MyImage *m){
    Vec4i temp;
    float avgX, avgY;
    float tolerance=bRect_width/6;
    int startidx, endidx, faridx;
    int startidx2, endidx2;
    for(int i=0;i<newDefects.size();i++){
        for(int j=i;j<newDefects.size();j++){
            startidx=newDefects[i][0]; Point ptStart(contours[cIdx][startidx] );
            endidx=newDefects[i][1]; Point ptEnd(contours[cIdx][endidx] );
            startidx2=newDefects[j][0]; Point ptStart2(contours[cIdx][startidx2] );
            endidx2=newDefects[j][1]; Point ptEnd2(contours[cIdx][endidx2] );
            if(distanceP2P(ptStart,ptEnd2) < tolerance ){
                contours[cIdx][startidx]=ptEnd2;
                break;
            }if(distanceP2P(ptEnd,ptStart2) < tolerance ){
                contours[cIdx][startidx2]=ptEnd;
            }
        }
    }
}

// convexity defects does not check for one finger
// so another method has to check when there are no
// convexity defects
void HandGesture::checkForOneFinger(MyImage *m){
    int yTol=bRect.height/6;
    Point highestP;
    highestP.y=m->src.rows;
    vector<Point>::iterator d=contours[cIdx].begin();
    while( d!=contours[cIdx].end() ) {
        Point v=(*d);
        if(v.y<highestP.y){
            highestP=v;
            cout<<highestP.y<<endl;
        }
        d++;    
    }int n=0;
    d=hullP[cIdx].begin();
    while( d!=hullP[cIdx].end() ) {
        Point v=(*d);
            cout<<"x " << v.x << " y "<<  v.y << " highestpY " << highestP.y<< "ytol "<<yTol<<endl;
        if(v.y<highestP.y+yTol && v.y!=highestP.y && v.x!=highestP.x){
            n++;
        }
        d++;    
    }if(n==0){
        fingerTips.push_back(highestP);
    }
}

void HandGesture::drawFingerTips(MyImage *m){
    Point p;
    int k=0;
    for(int i=0;i<fingerTips.size();i++){
        p=fingerTips[i];
        putText(m->src,intToString(i),p-Point(0,30),fontFace, 1.2f,Scalar(200,200,200),2);
        circle( m->src,p,   5, Scalar(100,255,100), 4 );
     }
}

void HandGesture::getFingerTips(MyImage *m){
    fingerTips.clear();
    int i=0;
    vector<Vec4i>::iterator d=defects[cIdx].begin();
    while( d!=defects[cIdx].end() ) {
        Vec4i& v=(*d);
        int startidx=v[0]; Point ptStart(contours[cIdx][startidx] );
        int endidx=v[1]; Point ptEnd(contours[cIdx][endidx] );
        int faridx=v[2]; Point ptFar(contours[cIdx][faridx] );
        if(i==0){
            fingerTips.push_back(ptStart);
            i++;
        }
        fingerTips.push_back(ptEnd);
        d++;
        i++;
    }
    if(fingerTips.size()==0){
        checkForOneFinger(m);
    }
}

myImage.cpp:

#include "stdafx.h"
#include "myImage.hpp"

#include <opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>

using namespace cv;

MyImage::MyImage(){
}

MyImage::MyImage(int webCamera){
    cameraSrc=webCamera;
    cap=VideoCapture(webCamera);
}

roi.cpp:

#include "stdafx.h"
#include "myImage.hpp"

#include <opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include "roi.hpp"

using namespace cv;
using namespace std;

My_ROI::My_ROI(){
    upper_corner=Point(0,0);
    lower_corner=Point(0,0);

}

My_ROI::My_ROI(Point u_corner, Point l_corner, Mat src){
    upper_corner=u_corner;
    lower_corner=l_corner;
    color=Scalar(0,255,0);
    border_thickness=2;
    roi_ptr=src(Rect(u_corner.x, u_corner.y, l_corner.x-u_corner.x,l_corner.y-u_corner.y));
}

void My_ROI::draw_rectangle(Mat src){
    rectangle(src,upper_corner,lower_corner,color,border_thickness);

}

again, dllmain.cpp and stdafx.cpp are standard stuff so I do not put it here.

My Unity Script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;
using UnityEngine.UI;

public class bs : MonoBehaviour
{
    [DllImport("algodll")]
    public static extern void trAck();



   // public float speed;

    public WebCamTexture webcamTexture;
    Renderer renderer;

    // Use this for initialization
    void Start()
    {
        webcamTexture = new WebCamTexture();
        renderer = GetComponent<Renderer>();
        renderer.material.mainTexture = webcamTexture;
        webcamTexture.Play();

    }

    // Update is called once per frame
    void Update()
    {


        if (webcamTexture.isPlaying)
        {

        trAck();


        }
    }
}

I tried to remove all the code inside the trAck() function and simply increment some variable i to test whether it crashes due to an infinite loop, but it didn't give this error, it just froze the Unity. Also, putting trAck() into Start() did not help.

Hype Totec
  • 31
  • 7
  • What happens when you call `trAck()` from the `Start` function? Does it freeze, does it work? Can you try to call it once using coroutine and see if it works? – Programmer May 03 '18 at 13:57
  • 2
    Is this a [mcve]? – Artemis May 03 '18 at 14:16
  • @Programmer for `Start()` the same thing as if U run it from `Update()` - it crashes. And same for coroutine. – Hype Totec May 03 '18 at 14:22
  • @Programmer `void Start() { webcamTexture = new WebCamTexture(); renderer = GetComponent(); renderer.material.mainTexture = webcamTexture; webcamTexture.Play(); StartCoroutine(TestCoroutine()); } IEnumerator TestCoroutine() { trAck(); yield return null; }` the coroutine version – Hype Totec May 03 '18 at 14:24
  • No error in Unity Console tab? This becomes really hard to solve since it's a large. Always test plugin little by little in Unity. Don't wait until it's too big before testing it. This will help prevent problems like this. *Did you test this code with normal C++ and made sure it works before making it a plugin?* If it doesn't work outside, it won't work with or in Unity – Programmer May 03 '18 at 14:33
  • @Programmer this code works as a standalone C++ app. I tested it. As for Unity console - nothing. – Hype Totec May 03 '18 at 15:49
  • @Programmer I don't know which part exactly causes the crash, or in which proportion each part contribute to it :) so I put everything, besides autogenerated files, here – Hype Totec May 03 '18 at 15:51
  • Ok.Just making making sure that it works without Unity.What happens when you [start a new Thread](https://stackoverflow.com/questions/811224/how-to-create-a-thread) from the Start function **once** and call `trAck()` from there? Does it still crash? Does it work? – Programmer May 03 '18 at 15:58
  • @Programmer `Thread t = new Thread(new ThreadStart(trAck)); t.Start();` same result. But without Unity it really works fine - I tested it. Not the dll I made, but the original source [link](https://github.com/simena86/handDetectionCV). when making a dll out of it, I did not change any code, I just renamed main function to trAck, and main.hpp and main.cpp to algo.hpp and algodll.cpp, respectively(and also changed it everywhere it was mentioned) , and Visual Studio generated standard files like stdafx.cpp, stdafx.h, dllmain.cpp and targetver.h – Hype Totec May 03 '18 at 17:52
  • @Programmer I used exactly that part of the github algorithm, VS2013 Version, for my dll [link](https://github.com/simena86/handDetectionCV/tree/master/VS2013%20Version) – Hype Totec May 03 '18 at 17:56
  • @Programmer I found out and wrote `//crashes` after lines which cause the crash in `trAck()` function in algodll.cpp – Hype Totec May 04 '18 at 15:21
  • I plan to check this out and test it on my side when I have time today. Do you have the "out.avi" file which is referenced in your code? Also, where did you place that? – Programmer May 04 '18 at 15:26
  • @Programmer I have it, it is being automatically created by dll in the root folder of the Unity project. Just an empty .avi file – Hype Totec May 04 '18 at 16:09
  • Ok I will let you know when I do a test. I can already several issues with that code but I have to run it to make sure I covered them all. One more question. How do you use this code? What is this code supposed to do? I want to know so that I will know when I got it working – Programmer May 04 '18 at 16:14
  • @Programmer thank you. It should somehow track your hand and count detected fingers. It does the work poorly, it is not a very good algorithm; by " works fine" I mean that it does what it's supposed to do(without rating the quality of what it does) Somewhat like that [link](https://ibb.co/eZ0yKS) should be the result. – Hype Totec May 04 '18 at 16:25
  • Ok. got it. I should do the experiment by tomorrow. Will report back If I find anything – Programmer May 04 '18 at 16:28
  • @Programmer P.S. in order for the frame not to appear and dissapear numerous times , I put `trAck()` into `Start()` instead of `Update()`. When `trAck()` is in the `Start()` and all the lines which cause the crash are commented out, something like [this](https://ibb.co/ex68m7) is happening – Hype Totec May 04 '18 at 16:35
  • This took long but I finally got the original project from github to compile and run. I had OpenCV on my PC but for some reason it was crashing when I run the original project. I found out I updated my compiler. I had to re-compile the OpenCV source to match my current VS compiler. I will do an extensive test with your plugin on Monday and report back. Sorry for taking so long. – Programmer May 07 '18 at 01:05
  • @Programmer it's fine. thank you for your help again. I'll wait. – Hype Totec May 09 '18 at 10:43
  • You said `Thread t = new Thread(new ThreadStart(trAck)); t.Start();` didn't work. Are you sure about that? I just tried it with the original project and it works with `Thread t = new Thread(new ThreadStart(trAck)); t.Start();` in the `Start` function. You must remove `trAck` from the Update function and try again. In my answer, I want to show you why it is freezing and how you can display the result in Unity instead of the popup Window. – Programmer May 11 '18 at 13:44
  • But if you can't get `Thread t = new Thread(new ThreadStart(trAck)); t.Start();` to work in the `Start` function and not freeze Unity, I don't think you will be able to get my answer working....By the way, what do you mean by freeze? Can you stop the Editor when you use `Thread t = new Thread(new ThreadStart(trAck)); t.Start();` in the `Start` function? If yes then it's not freezing. – Programmer May 11 '18 at 13:46
  • @Programmer by original you mean that you just downloaded the project from the link and renamed `main()` into `trAck()` ? Which exact actions did you do when you converted the project from the link into dll? – Hype Totec May 11 '18 at 15:19
  • Yup. Wrapped it around `extern "C"` and `__declspec(dllexport)` then called it in C# with `Thread t = new Thread(new ThreadStart(trAck)); t.Start();` in the `Start` function. Remove or comment out other code in the Start function. I also changed the Configuration type from exe to dll to generate dll plugin from that project. – Programmer May 11 '18 at 15:22
  • @Programmer did you do all this with Visual Studio? – Hype Totec May 11 '18 at 15:54
  • Yes. Project--->Properties---> Configuration Properties--->General--->Configurations Type then change it to Dynamic Library(.dll). Did you remove every code from the `Start` function? – Programmer May 11 '18 at 16:00
  • @Programmer thanks very much, now it shows image from camera and the interface(text, number of defects, sqares with numbers etc) on the screen. But it doesn't yet work properly – Hype Totec May 11 '18 at 16:15
  • @Programmer but I cannot close it now ) it seems to be a minor problem, but.. – Hype Totec May 11 '18 at 16:26
  • It's not a minor problem. It's a serious one. That's why I want to add answer. You can't really close that. As for your other problem about it not detecting fingers, it's not from Unity. That's from the code since it doesn't detect too on the original project. I suggest you find another project that can actually detect fingers – Programmer May 11 '18 at 16:31
  • You can only kill it by using task manager to kill Unity. If you fix the issue of not detecting fingers, I can provide a solution that shows a proper way to do this and make it display in Unity itself, fix the not closing issue but I think that would be waste of time to do this if tracking is not working. – Programmer May 11 '18 at 16:39
  • @Programmer maybe the reason it doesn't detect fingers is that the `images` folder in the original project doesn't connect properly to an app when it's launched? I don't know, it reacts in a very poor way to the skin color and shape of a palm(I guess this is the basis of an algorithm) – Hype Totec May 11 '18 at 16:51

0 Answers0