Hi,
lol. If it is of any comfort for you, I have narcolepsy (to a quite severe degree)
I run your code using some silhoute videos (from the same repo that had zach’s code i shared) and there are several problems.
There is a problem there with the vector class, when it changed from ofVec3f to glm::vec3 as the default. The latter does not have much member functions, but it happens to have a length() function which always returns 3.
Then when you moved the analize() code into your app, you missed using the correct ofPolyline.
In short, the code in analize() that you have in your app does nothing at all, but it is due to some small errors in the copypaste process.
#pragma once
#include "ofMain.h"
#include "ofxBox2d.h"
#include "ofxGui.h"
#include "ofxCv.h"
class ofApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
void exit();
void keyPressed(int key);
void keyReleased(int key);
void mouseMoved(int x, int y);
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseEntered(int x, int y);
void mouseExited(int x, int y);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
ofPolyline smoothPoly(const ofPolyline& polyline);
void analyze(const ofPolyline& curFrame);
void updateKinect(bool isDepthCam);
void updateContours(bool isDepthCam);
void drawKinect(bool isDepthCam);
//void oscSendRoll
float clip(float n, float lower, float upper);
//ofPolyline m_curFrame;
ofPolyline m_prevFrame;
ofPolyline m_resampleSmoothed;
ofxPanel m_panel;
ofParameter<int> m_threshold;
ofParameter<int> m_minArea;
ofParameter<int> m_maxArea;
ofParameter<float> m_nearClip;
ofParameter<float> m_farClip;
ofParameter<float> m_screenScaler;
ofParameter<int> m_polylinePointCount;
ofParameter<int> m_smoothingSize;
ofParameter<float> m_smoothingShape;
ofParameter<float> smoothingFactor = {"Smoothing Factor", 0.25, 0.0, 1.0};
ofParameter<bool> bDrawSmoothed = {"Draw Smoothed", true};
//int m_polylinePointCount = 104;
ofVideoPlayer m_kinect;
//ofVideoGrabber kinect;
ofImage m_grayImage;
ofxCv::ContourFinder m_contour;
int angle;
int m_camWidth;
int m_camHeight;
std::deque<ofPolyline> m_polys;
ofxBox2d m_box2d;
vector<shared_ptr<ofxBox2dCircle>> m_circles;
ofPolyline m_previousPoly;
int m_size = 2;
//int width, height;
float m_screenWidth = 20; //*should* set this via oF but setting it manually for now
int movLoaded = 0;
void loadMov(int movNum);
};
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup()
{
m_panel.setup("","", 20, 50);
m_panel.add(m_threshold.set("threshold", 15, 0, 100));
m_panel.add(m_minArea.set("minArea", 13, 0, 200));
m_panel.add(m_maxArea.set("maxArea", 199, 0, 200));
// m_panel.add(m_nearClip.set("near clip", 885.0, 500.0, 4000.0));
// m_panel.add(m_farClip.set("far clip", 1045.0, 1000.0, 10000.0));
m_panel.add(m_screenScaler.set("screen scale", 3.02, 0.5, 4.0));
m_panel.add(m_polylinePointCount.set("polyline point count", 180, 0, 650));
m_panel.add(m_smoothingSize.set("smoothing size", 2, 0, 30));
m_panel.add(m_smoothingShape.set("smoothing shape", 0.0, 0.0, 1.0));
m_panel.add(bDrawSmoothed);
m_panel.add(smoothingFactor);
loadMov(1);
m_box2d.init();
m_box2d.setGravity(0, 30);
m_box2d.createGround(0.0f, m_kinect.getHeight(), m_kinect.getWidth(), m_kinect.getHeight());
m_box2d.createBounds(ofRectangle(0, 0, m_kinect.getWidth(), m_kinect.getHeight()));
m_box2d.enableEvents();
// ofAddListener(m_box2d.contactStartEvents, this, &ofApp::contactStart);
// ofAddListener(m_box2d.contactEndEvents, this, &ofApp::contactEnd);
m_polys.resize(m_polylinePointCount);
/*for (int i = 0; i < m_polys.size(); i++)
{
for (int j = 0; j < m_polylinePointCount; j++)
{
m_polys[i].addVertex(0, 0, 0);
}
//cout << m_polys[i].size() << endl;
}*/
}
void ofApp::loadMov(int movNum){
if(movNum >=0 && movNum <7){
string mov = "movs/" +ofToString(movNum+1) +".mov";
if(m_kinect.load(mov)){
cout << "loaded : " << mov << endl;
cout << "movNum : " << movNum << endl;
movLoaded = movNum;
m_kinect.setLoopState(OF_LOOP_NORMAL);
m_kinect.play();
}
}
}
//--------------------------------------------------------------
void ofApp::update() {
m_box2d.update();
updateKinect(true);
updateContours(true);
}
//--------------------------------------------------------------
void ofApp::draw() {
ofPushMatrix();
ofScale(m_size, m_size);
ofSetRectMode(OF_RECTMODE_CORNER);
ofSetColor(255);
drawKinect(true);
for (ofPolyline const& p : m_contour.getPolylines()) //THE PROBLEM...
{
ofSetLineWidth(5);
ofSetColor(ofColor(255,0,0));
ofNoFill();
// ofSetLineWidth(1);
// ofSetColor(0, 0, 0);
// ofFill();
ofPolyline s = p.getSmoothed(m_smoothingSize, m_smoothingShape);
// if(bUseAnalyze){
// ofPolyline smoothedPoly = analyze(s);
if(bDrawSmoothed){
analyze(s);
m_resampleSmoothed.draw();
if(m_resampleSmoothed.size()){
ofSetColor(ofColor:: yellow);
ofDrawCircle(m_resampleSmoothed.getVertices()[0], 5);
}
}else{
p.draw();
if(p.size()){
ofSetColor(ofColor:: yellow);
ofDrawCircle(p.getVertices()[0], 5);
}
}
// createContourEdge(smoothedPoly);
// }else{
// ofPolyline smoothedPoly = smoothPoly(s);
// createContourEdge(smoothedPoly);
// }
}
//m_contourEdge->resize(m_size);
//m_contourEdge->draw(); //...IS IN HERE.
ofSetColor(255);
for (auto circle : m_circles)
{
circle->draw();
}
//panel.setSize(panel.getWidth() / size, panel.getHeight() / size);
//panel.setPosition(panel.getPosition().x / size, panel.getPosition().y / size);
ofPopMatrix();
m_panel.draw();
ofDrawBitmapStringHighlight("FPS: " + ofToString(ofGetFrameRate()), 20, 20);
}
void ofApp::exit() {
// m_kinect.setCameraTiltAngle(15.0);
m_kinect.close();
}
float ofApp::clip(float n, float lower, float upper) {
return std::max(lower, std::min(n, upper));
}
void ofApp::drawKinect(bool isDepthCam)
{
m_kinect.draw(0, 0);
}
void ofApp::updateKinect(bool isDepthCam)
{
m_kinect.update();
}
void ofApp::updateContours(bool isDepthCam)
{
if (!m_kinect.isFrameNew())
{
return;
}
m_contour.setMinAreaRadius(m_minArea);
m_contour.setMaxAreaRadius(m_maxArea);
//
// m_grayImage.setFromPixels(m_kinect.getDepthPixels());
// m_contour.findContours(m_grayImage);
//
//m_contour.setTargetColor(m_trackingColor);
m_contour.setThreshold(m_threshold);
m_contour.findContours(m_kinect);
}
ofPolyline ofApp::smoothPoly(const ofPolyline& _polyline)
{
auto polyline = _polyline.getResampledByCount(m_polylinePointCount /* + 1*/);
//cout << polyline.size() << endl;
glm::vec3 first_vert = { 0,0,0 };
if (m_polys.size() > 0 && m_polys[0].size() > 0)
{
first_vert = m_polys[0].getVertices()[0];
}
size_t first_index = 0;
float min_dist = std::numeric_limits<float>::max();
for (size_t i = 0; i < polyline.size(); ++i)
{
auto d = glm::distance2(polyline[i], first_vert);
if (d < min_dist)
{
min_dist = d;
first_index = i;
}
}
if (first_index > 0)
{
vector<glm::vec3> rearrangedVerts;
rearrangedVerts.insert(rearrangedVerts.begin(), polyline.begin() + first_index, polyline.end());
rearrangedVerts.insert(rearrangedVerts.end(), polyline.begin(), polyline.begin() + first_index);
ofPolyline rearrangedPoly;
rearrangedPoly.addVertices(rearrangedVerts);
m_polys.push_front(rearrangedPoly);
}
else
{
m_polys.push_front(polyline);
}
m_polys.pop_back();
ofPolyline averaged;
//cout << m_polys.size() << endl;
for (size_t i = 0; i < m_polylinePointCount; ++i)
{
glm::vec3 avg;
for (size_t j = 0; j < m_polys.size(); ++j)
{
//cout << m_polys[j].size() << endl;
//cout << m_polys[j][i] << endl;
if (i < m_polys[j].size())
{
avg += m_polys[j][i];
}
//cout << "vertex[" << j << "][" << i << "] added" << endl;
}
avg /= m_polys.size();
averaged.addVertex(avg);
}
return averaged;
}
void ofApp::analyze(const ofPolyline& curFrame) {
// ofPolyline line = curFrame;
ofPolyline resampled = curFrame.getResampledByCount(m_polylinePointCount);
// A++ if you fix getResampledByCount end points !
//
//
//
while (resampled.size() < m_polylinePointCount) {
resampled.getVertices().push_back(resampled[resampled.size() - 1]);
}
//
if (m_prevFrame.size() > 0) {
// cout << ",,,,,\n";
// if you want to make this faster
// you will get an A +
// this is pretty slow :(
// but it works.
int smallestStart = -1;
float smallestAvgLen = 10000000;
float fCount = m_polylinePointCount.get();
auto p_count = m_polylinePointCount.get();
for (int i = 0; i < p_count; i++) {
float avgLen = 0;
for (int j = 0; j < p_count; j++) {
avgLen += glm::distance2(resampled[(j + i) % p_count], m_prevFrame[j]) / fCount;
//
}
if (avgLen < smallestAvgLen) {
smallestAvgLen = avgLen;
smallestStart = i;
}
}
ofPolyline temp;
for (int i = 0; i < p_count; i++) {
temp.addVertex(resampled[(i + smallestStart) % p_count]);
}
resampled = temp;
}
m_prevFrame = resampled;
// ofPolyline tempT = resampled.getResampledByCount(100);
//
// while (tempT.size() < 100) {
// tempT.getVertices().push_back(tempT[tempT.size() - 1]);
// }
ofPolyline & tempT = resampled;
if (m_resampleSmoothed.size() == 0 || ofIsFloatEqual(smoothingFactor.get(), 1.0f)) {
m_resampleSmoothed = tempT;
}
else {
for (int i = 0; i < tempT.size(); i++) {
m_resampleSmoothed[i] = (1.0 - smoothingFactor) * m_resampleSmoothed[i] + (smoothingFactor.get() * tempT[i]);
}
}
//if you want this function to return something it should be m_resampleSmoothed rather than resampled
// return resampled;
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key) {
switch (key)
{
case 'c':
m_circles.clear();
break;
case 'd':
break;
}
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key) {
if(key == OF_KEY_LEFT){
loadMov(((movLoaded +1)%7));
}else if(key == OF_KEY_RIGHT){
loadMov(((movLoaded -1 + 7)%7));
}
}
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y) {
}
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button) {
}
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button) {
/*auto circle = make_shared <ofxBox2dCircle>();
circle->setPhysics(3.0, 0.5, 0.1);
circle->setup(m_box2d.getWorld(), x / m_size, y / m_size, 32);
m_circles.push_back(circle);*/
}
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button) {
}
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y) {
}
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y) {
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h) {
}
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg) {
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo) {
}
Using analize with the code above you get a quite stable first point.
Pull smoothingFactor
all the way up to 1 if you want to have the polyline stuck to the silhouette.
I hope this helps.