Last active
October 21, 2016 06:41
-
-
Save kashimAstro/3316d4b7072ca9a63bb5761c1f297bae to your computer and use it in GitHub Desktop.
Class Opencv shape detection for openframeworks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "ofMain.h" | |
#include "ofxCv.h" | |
using namespace ofxCv; | |
using namespace cv; | |
class CVShape{ | |
public: | |
Mat gray; | |
Mat bw; | |
Mat dst; | |
ofPixels pixelsRep; | |
string labelState; | |
vector<vector<Point> > contours; | |
vector<Point> approx; | |
static double angle(Point pt1, Point pt2, Point pt0) | |
{ | |
double dx1 = pt1.x - pt0.x; | |
double dy1 = pt1.y - pt0.y; | |
double dx2 = pt2.x - pt0.x; | |
double dy2 = pt2.y - pt0.y; | |
return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); | |
} | |
string getLabel(){ | |
return labelState; | |
} | |
void update(ofPixels pix){ | |
pixelsRep = pix; | |
Mat src = toCv(pixelsRep); | |
if (src.empty()) | |
ofLog()<<"Error image"; | |
cvtColor(src, gray, CV_BGR2GRAY); | |
Canny(gray, bw, 0, 50, 5); | |
findContours(bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); | |
dst = src.clone(); | |
for (int i = 0; i < contours.size(); i++) | |
{ | |
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true); | |
if (std::fabs(contourArea(contours[i])) < 100 || !isContourConvex(approx)) | |
continue; | |
if (approx.size() == 3) | |
{ | |
labelState = "TRIANGLES"; | |
} | |
else if (approx.size() >= 4 && approx.size() <= 6) | |
{ | |
int vtc = approx.size(); | |
std::vector<double> cos; | |
for (int j = 2; j < vtc+1; j++) | |
cos.push_back(angle(approx[j%vtc], approx[j-2], approx[j-1])); | |
std::sort(cos.begin(), cos.end()); | |
double mincos = cos.front(); | |
double maxcos = cos.back(); | |
if (vtc == 4 && mincos >= -0.1 && maxcos <= 0.3) | |
{ | |
labelState = "RECTANGLE"; | |
} | |
else if (vtc == 5 && mincos >= -0.34 && maxcos <= -0.27) | |
{ | |
labelState = "PENTA"; | |
} | |
else if (vtc == 6 && mincos >= -0.55 && maxcos <= -0.45){ | |
labelState = "HEXA"; | |
} | |
} | |
else | |
{ | |
double area = contourArea(contours[i]); | |
Rect r = boundingRect(contours[i]); | |
int radius = r.width / 2; | |
if (std::abs(1 - ((double)r.width / r.height)) <= 0.2 && | |
std::abs(1 - (area / (CV_PI * std::pow(radius, 2)))) <= 0.2){ | |
labelState = "CIRCLE"; | |
} | |
} | |
} | |
} | |
}; | |
#include "ofMain.h" | |
#include "ofxCv.h" | |
#include "cvshape.h" | |
class ofApp : public ofBaseApp{ | |
public: | |
CVShape cvs; | |
ofFbo fbo; | |
void setup(){ | |
ofSetVerticalSync(false); | |
fbo.allocate(300,300); | |
fbo.begin(); | |
ofClear(0,0,0,255); | |
fbo.end(); | |
} | |
void update(){ | |
ofSetWindowTitle(ofToString(ofGetFrameRate())); | |
} | |
void draw(){ | |
ofPixels pix; | |
fbo.readToPixels(pix); | |
cvs.update(pix); | |
fbo.draw(0,0); | |
ofDrawBitmapStringHighlight(cvs.getLabel(),220,20); | |
} | |
void keyPressed(int key){ | |
if(key == ' '){ | |
fbo.begin(); | |
ofClear(0,0,0,255); | |
fbo.end(); | |
} | |
} | |
void mouseDragged(int x, int y, int button){ | |
fbo.begin(); | |
ofSetColor(ofColor::red); | |
ofDrawRectangle(x,y,10,10); | |
fbo.end(); | |
} | |
}; | |
int main(){ | |
ofSetupOpenGL(300,300, OF_WINDOW); | |
ofRunApp( new ofApp()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
image sample: