Вы находитесь на странице: 1из 5

Разработка интерактивных систем на OpenFrameworks, весна 2010

систем на OpenFrameworks, весна 2010 УрГУ / ИММ Проект

УрГУ / ИММ

Проект "2d-скульптура"

/ ИММ Проект "2d-скульптура" Скульптор воплощает свой

Скульптор воплощает свой замысел, вырезая из синего квадратного куска материи 50x50 лишнее. В его распоряжении два инструмента: красный резец и зелёная ручка для вращения изделия.

Исходный код проекта (testApp.cpp):

#include "testApp.h"

//1. Рабочее тело bool body[50][50]; float d=7;

float ang=0; //Угол поворота

//2. Переменные для захвата видео-кадров ofVideoGrabber grabber; const int w=640;//320; const int h=480;//200;

//3. Лезвие и ручка для вращения рабочего тела ofPoint blade, handle; unsigned char outImage[w*h*3]; //Обработанные байты изображения ofTexture outImageTexture; //Текстура для их выведения на экран

//--------------------------------------------------------------

void testApp::setup(){ //1. Исходное состояние рабочего тела for(int i=0; i<50; i++) for(int j=0; j<50; j++) body[i][j]=true;

//2.

grabber.initGrabber(w,h);

//3.

outImageTexture.allocate(w, h, GL_RGB);

ofBackground(255,255,255); //Белый фон

}

//--------------------------------------------------------------

void testApp::update(){ //2. Захват кадра grabber.grabFrame();

//3. Нахождение красных и зелёных пикселей с помощью пороговой обработки if (grabber.isFrameNew()){ unsigned char *input=grabber.getPixels(); for(int y=0; y<h; y++) for(int x=0; x<w; x++) { int r=input[3*(x+w*y)+0]; int g=input[3*(x+w*y)+1]; int b=input[3*(x+w*y)+2];

//По умолчанию чёрная

outImage[3*(x+w*y)+0]=0;

outImage[3*(x+w*y)+1]=0;

outImage[3*(x+w*y)+2]=0;

if ( r>g+50 && r>b+50 ) { //Красный пиксель

outImage[3*(x+w*y)+0]=255;

} else if ( g>r+100 && g>b+100 ) { //Зелёный

пиксель

outImage[3*(x+w*y)+1]=255;

}

}

outImageTexture.loadData(outImage, w, h, GL_RGB);

}

//3. Нахождение зелёной ручки вращения и красного лезвия

blade=ofPoint(0,0);

ofPoint oldhandle(handle); //Запоминаем старое положение ручки вращения

handle=ofPoint(0,0);

int n_blade=0, n_handle=0; for(int y=0; y<h; y++) for(int x=0; x<w; x++) { int b=outImage[3*(x+w*y)+2]; if (outImage[3*(x+w*y)+0]==255) {//Красная точка blade.x+=x; blade.y+=y; n_blade++; } else if (outImage[3*(x+w*y)+1]==255) {//Зелёная точка handle.x+=x; handle.y+=y; n_handle++;

}

}

if (n_blade>50) { //Число красных пикселей достаточно велико, чтобы утверждать, что это не шум blade.x/=n_blade; blade.y/=n_blade; } else {

blade.set(0,0);

}

if (n_handle>50) { //Число зелёных пикселей достаточно велико, чтобы утверждать, что это не шум

handle.x/=n_handle;

handle.y/=n_handle;

} else { handle=oldhandle;

}

//printf("nred=%d

ngreed=%d\n", n_blade, n_handle);

//Вычисление угла вращения, соответствующего положению ручки double len=sqrt((handle.x-w/2)*(handle.x-w/2)+(handle.y-h/

2)*(handle.y-h/2));

double cosang=(handle.x-w/2)/len; ang=acos(cosang); if (handle.y-h/2<0)

}

ang*=-1;

//--------------------------------------------------------------

void testApp::draw(){

//2. Рисование захваченного виде-кадра

ofSetColor(255,255,255);

grabber.draw(w, h, w, h); grabber.draw(0, 0);

//3. Отображение результатов пороговой обработки справа outImageTexture.draw(w, 0, w, h);

//3. Рисование ручки

ofSetColor(0,255,0);

ofNoFill(); //ofCircle(handle.x, handle.y, 20); ofCircle(handle.x+w, handle.y, 20); ofCircle(handle.x+w, handle.y+h, 20);

//3. Рисование лезвия ofSetColor( 255, 0, 0 ); ofCircle(blade.x+w, blade.y, 20); ofCircle(blade.x+w, blade.y+h, 20); ofFill(); ofCircle(blade.x, blade.y, 2*d);

//1. Рисование рабочего тела синим цветом ofSetColor( 0, 0, 255 ); for(int i=0; i<50; i++) for(int j=0; j<50; j++) if (body[i][j]) { double x=(i-25)*d;

double y=(j-25)*d; double X=w/2+x*cos(ang)-y*sin(ang); double Y=h/2+x*sin(ang)+y*cos(ang); //ofCircle(X, Y, d/2);

//3. Редактирование рабочего тела if ((X-blade.x)*(X-blade.x)+(Y-blade.y)*(Y-

blade.y)<4*d*d)

}

body[i][j]=false;

else {

ofCircle(X, Y, d/2);

}

//Линия, показывающая угол повота ofLine(w/2+d*30*cos(ang), h/2+30*d*sin(ang), w/2+d*40*cos(ang),

h/2+40*d*sin(ang));

}

//--------------------------------------------------------------

void testApp::keyPressed(int key){ //Восстановление рабочего тела for(int i=0; i<50; i++) for(int j=0; j<50; j++) body[i][j]=true;

}