I am coding a terminal based game in c++ using the ncurses library, and I would like the enemy class to be able to access the players location which I can access from within my main function using p->yLoc and p->xLoc, however, I cannot access these variables from within my enemy::move function, as it just returns the error p was not declared in this scope.
Here is my code:
enemy.h:
#ifndef _ENEMY_H_
#define _ENEMY_H_
#include "player.h"
#include <unistd.h>
void Enemy::move(){
int playerY, playerX;
int yMv, xMv;
while (1){
playerY = p->yLoc;
playerX = p->xLoc;
if (playerY > yLoc) {
mvdown();
} else if (playerY < yLoc) {
mvup();
}
if (playerX > xLoc){
mvright();
} else if (playerX < xLoc) {
mvleft();
}
sleep(1);
}
}
player.h
#ifndef _PLAYER_H_
#define _PLAYER_H_
class Player {
public:
Player(WINDOW * win, int y, int x, char c);
void mvup();
void mvdown();
void mvleft();
void mvright();
int getmv();
void display();
int xLoc, yLoc, xMax, yMax;
private:
char character;
WINDOW * curwin;
};
Player::Player(WINDOW * win, int y, int x, char c){
curwin = win;
yLoc = y;
xLoc = x;
getmaxyx(curwin, yMax, xMax);
keypad(curwin, true);
character = c;
}
main.cpp
#include <ncurses.h>
#include "player.h"
#include <string>
#include <ctime>
#include <cstdlib>
#include "enemy.h"
#include <thread>
using namespace std; // I understand this is bad practice
int main(){
// starts ncurses
initscr();
noecho();
cbreak();
int yMax, xMax;
getmaxyx(stdscr, yMax, xMax);
WINDOW * playwin = newwin(20, 50, (yMax/2)-10, 10);
box(playwin, 0, 0);
refresh();
wrefresh(playwin);
if (nodelay (playwin, 1) == ERR) {
// an error has occurred
}
Player * p = new Player(playwin, 1, 1, '#'); // params: (window to display in, starting y, starting x, character to display)
Enemy * e = new Enemy(playwin, 10, 10, 'x'); // same here
thread enemyLoop(&Enemy::move, e); // start the movement for the enemy in a different thread
while(p->getmv() != 'x'){ // leave the game with the key x
// updates the location of the two sprites, and refreshes the window.
p->display();
e->display();
wrefresh(playwin);
}
endwin();
return 0;
}
If Enemy::move is supposed to know about the other players location then you have to pass the player as argument:
void Enemy::move(const Player &p)
e->move(*p);
Then the function can access the players position.
Note: why are you allocating the player and enemy on the heap. there really is no need for that.
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.
I am writing a board game using C++ (with SFML2.2 library, Xcode 6.1.1). I created two classes: block and board. The idea is to create a 4x4 vector of blocks inside board. The codes are below:
In block.h
#ifndef __Game1024__block__
#define __Game1024__block__
#include <stdio.h>
#include <iostream>
#endif /* defined(__Game1024__block__) */
using namespace std;
class block{
public:
sf::RectangleShape rect;
sf::Text text;
block();
block(const int X,const int Y,const double size, const double blockSize, const double charSize, const int value, const sf::Color fillColor, const sf::Color textColor);
};
In block.cpp
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <string>
#include <sstream>
#include "block.h"
using namespace std;
block::block(){}
block::block(const int X,const int Y,const double size, const double blockSize, const double charSize, const int value, const sf::Color fillColor, const sf::Color textColor){
double centerX = (X+0.5)*size;
double centerY = (Y+0.5)*size;
stringstream ss;
ss << value;
string sval = ss.str();
rect.setSize(sf::Vector2f(blockSize,blockSize));
rect.setOrigin(blockSize/2.0, blockSize/2.0);
rect.setPosition(centerX, centerY);
rect.setFillColor(fillColor);
text.setStyle(sf::Text::Bold);
text.setCharacterSize(charSize);
text.setString(sval);
text.setColor(textColor);
text.setOrigin(text.getLocalBounds().width/2.0, text.getLocalBounds().height);
text.setPosition(centerX, centerY);
}
In board.h
#ifndef __Game1024__board__
#define __Game1024__board__
#include <stdio.h>
#endif /* defined(__Game1024__board__) */
#include <vector>
#include "block.h"
using namespace std;
class board{
private:
int winSizeX;
int winSizeY;
int margin;
double charSize;
public:
vector<vector<block>> matrix;
board();
board(int winSizeX_,int winSizeY_,int margin_, double charSize_);
void draw();
};
And in board.cpp
#include "board.h"
//#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "block.h"
using namespace std;
board::board(){}
board::board(int winSizeX_,int winSizeY_,int margin_, double charSize_){
winSizeX = winSizeX_;
winSizeY = winSizeY_;
margin = margin_;
charSize = charSize_;
matrix = vector<vector<block>>(4,vector<block>(4));
double size = winSizeX/4.0; // = 256
double blockSize = size - 2*margin;
const sf::Color fillColor = sf::Color::Red;
const sf::Color textColor = sf::Color::White;
sf::Font font;
if(!font.loadFromFile("./sansation.ttf")){
exit(EXIT_FAILURE);
};
for (int i = 0; i < 4; ++i){
for (int j = 0; j < 4; ++j){
int value = 4*j + i + 1;
matrix[i][j] = block(i,j,size,blockSize, charSize,value,fillColor,textColor);
matrix[i][j].text.setFont(font);
matrix[i][j].text.setOrigin(matrix[i][j].text.getLocalBounds().width/2.0,b[i][j].text.getLocalBounds().height);
}
}
}
The error comes from board.cpp
matrix[i][j] = block(i,j,size,blockSize, charSize,value,fillColor,textColor);
One weird thing is when I typed matrix[i][j] = block, the autofill of my IDE (Xcode) will generate
matrix[i][j] = block(<#const int X#>, <#const int Y#>, <#const double size#>, <#const double blockSize#>, <#const double charSize#>, <#const int value#>, <#const int fillColor#>, <#const int textColor#>)
The last two arguments of constructor block are changed from type sf::Color into int.
If I create a 4x4 vector of blocks in the main.cpp file and call the constructor of block, there is no error...
Any help?
Thanks in advance!
[Update] I attached the scrrenshot of the error message
Thanks #molbdnilo
I made a stupid mistake that I forgot to include the SFML header in "block.h"
#include <SFML/Graphics.hpp>
Now problem solved! Thanks for all advices. I am new to C++ projects, please feel free to speak out all my bad practices in the code. Very helpful!