首页 > 解决方案 > 从 OpenCV 手部跟踪算法制作一个 dll 并放入 Unity

问题描述

我从这里获取了一个 OpenCV 手部跟踪算法 ,并从中制作了一个 dll。当我按原样启动它时,它运行良好。但是当我将它编译为 dll 并将其附加到 Unity 时,我得到了这个,运行时错误,程序已请求运行时以不寻常的方式终止它

我在trAck()导致运行时错误的行之后将 //crashs 放在 algodll.cpp 中的函数中

这就是我得到的。标题:

手势.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

算法.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

我不会在这里放 stdafx.h 和 targetver.h 的代码,因为它们是标准的 Visual Studio 生成的头文件。我的 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();

    }
}

手势.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);
    }
}

我的图像.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);

}

同样,dllmain.cpp 和 stdafx.cpp 是标准的东西,所以我不把它放在这里。

我的统一脚本:

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();


        }
    }
}

我试图删除trAck()函数内的所有代码并简单地增加一些变量 i 以测试它是否由于无限循环而崩溃,但它没有给出这个错误,它只是冻结了 Unity。此外,投入trAck()Start()没有帮助。

标签: c++opencvunity3druntime-errordllimport

解决方案


推荐阅读