Skip to content

Instantly share code, notes, and snippets.

@kashimAstro
Last active October 21, 2016 06:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kashimAstro/3316d4b7072ca9a63bb5761c1f297bae to your computer and use it in GitHub Desktop.
Save kashimAstro/3316d4b7072ca9a63bb5761c1f297bae to your computer and use it in GitHub Desktop.
Class Opencv shape detection for openframeworks
#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());
}
@kashimAstro
Copy link
Author

image sample:

shapecv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment