mediapipe를 통해 손의 움직임을 인식하고,
손 동작을 인식하는 코드를 만들어 동작마다 의미를 부여하고,
이러한 동작마다 각각의 이벤트가 발생하게끔 하는 코드이다.
"수화"를 인식해서 해당 수화에 맞는 이미지들이 화면에 나타나서 돌아다니는 코드이다.
개선한 코드는 p5.js로 이루어져 있는 이벤트 코드들이다.
이벤트가 발생하는 코드 부분을 개선하였는데,
개선하기 전 코드는 이러했다.
let capture;
let img = [];
let images = [];
function preload() {
for (let i = 0; i < 8; i++) {
img[i] = loadImage("img/" + i + ".png");
}
}
function setup() {
createCanvas(640, 480);
capture = createCapture(VIDEO);
capture.hide();
for (let i = 0; i < img.length; i++) {
images[i] = new Img(
i,
random(50, width - 50),
random(50, height - 50),
random(-1, 1),
random(-0.1, 0.1),
random(-1, 1),
random(-1, 1)
);
}
}
function draw() {
imageMode(CORNER);
background(0); //카메라 사용할 경우 주석처리
if (count > img.length + 1) {
count = 0;
}
if (count == 1) {
for (let i = 0; i < 1; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
}
} else if (count == 2) {
for (let i = 0; i < 2; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
}
} else if (count == 3) {
for (let i = 2; i < 3; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
}
} else if (count == 4) {
for (let i = 3; i < 4; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
}
} else if (count == 5) {
for (let i = 3; i < 5; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
}
} else if (count == 6) {
for (let i = 3; i < 6; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
}
} else if (count == 7) {
for (let i = 3; i < 7; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
}
} else if (count == 8) {
for (let i = 3; i < 8; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
}
} else if (count == 9) {
for (let i = 0; i < img.length; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
}
}
console.log(count);
}
function mousePressed() {
count++;
}
class Img {
constructor(i, x, y, angle, inc, xSpeed, ySpeed) {
this.i = i;
this.x = x;
this.y = y;
this.angle = angle;
this.inc = inc;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
}
draw() {
imageMode(CENTER);
push();
fill(255);
translate(this.x, this.y);
rotate(this.angle);
image(img[this.i], 0, 0, img[this.i].width, img[this.i].height);
pop();
}
move() {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (
this.x > width - img[this.i].width / 2 ||
this.x < img[this.i].width / 2
) {
this.xSpeed = this.xSpeed * -1;
}
if (
this.y > height - img[this.i].height / 2 ||
this.y < img[this.i].height / 2
) {
this.ySpeed = this.ySpeed * -1;
}
}
rotate() {
this.angle += this.inc;
}
}
코드를 간단하게 설명하자면 수화는 단어 단위로 인식되고, 문장 단위로 쌓인다.
즉, "사랑해요" "이 한마디"와 같이 수화는 2개로 인식되는데,
이는 문장 단위로 "사랑해요"(이벤트 1 실행) "이 한마디"(이벤트 1+2 실행) 와 같이 이벤트들이 쌓이게 된다.
다음 문장으로 넘어가면 쌓여있던 이벤트들은 종료되고 새로운 다음 수화에 관한 이벤트가 실행된다.
개선한 코드는 수화가 쌓이는 부분이였다.
코드를 보다보니, for문이 반복되는데, 이를 하나의 for문에 묶고 시작과 끝 부분만 달리하면 되지 않을까? 라는 생각에 코드를 개선하게 되었다.
let capture;
let img = [];
let images = [];
let start = 0;
let canvas1;
function preload() {
for (let i = 0; i < 8; i++) {
img[i] = loadImage("img/" + i + ".png");
}
}
function setup() {
canvas1 = createCanvas(640, 480);
canvas1.id("canvas1");
capture = createCapture(VIDEO);
capture.hide();
for (let i = 0; i < img.length; i++) {
images[i] = new Img(
i,
random(50, width - 50),
random(50, height - 50),
random(-1, 1),
random(-0.1, 0.1),
random(-1, 1),
random(-1, 1)
);
}
}
function draw() {
imageMode(CORNER);
tint(100); // 영상 틴트
image(capture, 0, 0, width, (width * capture.height) / capture.width);
noTint(); // 이미지에는 틴트 안 씌워진다
if (count > img.length + 1) {
count = 0;
start = 0;
}
if (count < 9) {
for (let i = start; i < count; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
if (i === 2) start = 2;
if (i === 3) start = 3;
if (i === 7) start = 7;
if (i === 8) start = 8;
}
}
if (count === 9) {
for (let i = 0; i < 8; i++) {
images[i].draw();
images[i].rotate();
images[i].move();
}
}
console.log(count);
}
function mousePressed() {
count++;
}
class Img {
constructor(i, x, y, angle, inc, xSpeed, ySpeed) {
this.i = i;
this.x = x;
this.y = y;
this.angle = angle;
this.inc = inc;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
}
draw() {
imageMode(CENTER);
push();
fill(255);
translate(this.x, this.y);
rotate(this.angle);
image(img[this.i], 0, 0, img[this.i].width, img[this.i].height);
pop();
}
move() {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (
this.x > width - img[this.i].width / 2 ||
this.x < img[this.i].width / 2
) {
this.xSpeed = this.xSpeed * -1;
}
if (
this.y > height - img[this.i].height / 2 ||
this.y < img[this.i].height / 2
) {
this.ySpeed = this.ySpeed * -1;
}
}
rotate() {
this.angle += this.inc;
}
}
개선 결과 코드가 훨씬 깔끔해지고, 직관적이게 바뀌었다.