Skip to content

Commit 937ba8b

Browse files
committed
change video file name to ball_lifting
1 parent 02bdb6d commit 937ba8b

File tree

3 files changed

+182
-0
lines changed

3 files changed

+182
-0
lines changed
File renamed without changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!--
2+
👋 Hello! This is an ml5.js example made and shared with ❤️.
3+
Learn more about the ml5.js project: https://ml5js.org/
4+
ml5.js license and Code of Conduct: https://github.com/ml5js/ml5-next-gen/blob/main/LICENSE.md
5+
6+
This example demonstrates object detection on live video through ml5.objectDetector.
7+
-->
8+
9+
<!DOCTYPE html>
10+
<html lang="en">
11+
<head>
12+
<meta charset="UTF-8" />
13+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
14+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
15+
<title>ml5.js objectDetector Example - Webcam</title>
16+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script>
17+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
18+
<script src="../../dist/ml5.js"></script>
19+
</head>
20+
<body>
21+
<main>
22+
</main>
23+
<script src="sketch.js"></script>
24+
</body>
25+
</html>
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
let video;
2+
let detector;
3+
let detections = [];
4+
5+
// Oscillators and envelopes for chords
6+
let oscList = [];
7+
let envList = [];
8+
9+
// C major scale
10+
let musicScale = [
11+
{ name: "C", freq: 261.63 },
12+
{ name: "D", freq: 293.66 },
13+
{ name: "E", freq: 329.63 },
14+
{ name: "F", freq: 349.23 },
15+
{ name: "G", freq: 392.0 },
16+
{ name: "A", freq: 440.0 },
17+
{ name: "B", freq: 493.88 },
18+
{ name: "C", freq: 523.25 }
19+
];
20+
21+
let rows = musicScale.length;
22+
let cols = 8;
23+
let cellWidth, cellHeight;
24+
let lastCell = { row: -1, col: -1 };
25+
26+
const possibleLabels = ["sports ball", "orange", "apple", "frisbee" ];
27+
28+
function preload() {
29+
detector = ml5.objectDetector("cocossd");
30+
}
31+
32+
function setup() {
33+
createCanvas(640, 480);
34+
cellWidth = width / cols;
35+
cellHeight = height / rows;
36+
textAlign(CENTER, CENTER);
37+
textSize(14);
38+
39+
// Video setup
40+
video = createCapture(VIDEO);
41+
video.size(width, height);
42+
video.hide();
43+
44+
// Start detection
45+
detector.detectStart(video, gotDetections);
46+
47+
// 3 oscillators for chord
48+
for (let i = 0; i < 3; i++) {
49+
let osc = new p5.Oscillator("triangle");
50+
osc.start();
51+
osc.amp(0);
52+
oscList.push(osc);
53+
54+
let env = new p5.Envelope();
55+
env.setADSR(0.01 + i * 0.01, 0.1, 0.3, 0.2);
56+
env.setRange(0.4, 0);
57+
envList.push(env);
58+
}
59+
}
60+
61+
// Callback function from cocossd
62+
function gotDetections(results) {
63+
detections = results;
64+
}
65+
66+
function draw() {
67+
background(30);
68+
69+
// Mirror video
70+
push();
71+
translate(width, 0);
72+
scale(-1, 1);
73+
image(video, 0, 0, width, height);
74+
pop();
75+
76+
// Draw grid
77+
stroke(80);
78+
for (let i = 0; i <= rows; i++) line(0, i * cellHeight, width, i * cellHeight);
79+
for (let j = 0; j <= cols; j++) line(j * cellWidth, 0, j * cellWidth, height);
80+
81+
// Draw note labels
82+
noStroke();
83+
fill(200);
84+
for (let i = 0; i < rows; i++) {
85+
text(musicScale[i].name, width - 20, i * cellHeight + cellHeight / 2);
86+
}
87+
88+
// Look for a sports ball detection
89+
let ballX = -100, ballY = -100;
90+
for (let i = 0; i < detections.length; i++) {
91+
let det = detections[i];
92+
if (possibleLabels.includes(det.label)) {
93+
// Center of the bounding box
94+
ballX = det.x + det.width / 2;
95+
ballY = det.y + det.height / 2;
96+
break;
97+
}
98+
}
99+
100+
if (ballX !== -100 && ballY !== -100) {
101+
// Mirror X for both display and grid calculation
102+
let mirroredX = width - ballX;
103+
104+
// Draw circle at ball position
105+
fill(255, 150, 0);
106+
noStroke();
107+
ellipse(mirroredX, ballY, 30);
108+
109+
// Determine current cell
110+
let colIndex = int(mirroredX / cellWidth);
111+
let rowIndex = int(ballY / cellHeight);
112+
113+
if (colIndex >= 0 && colIndex < cols && rowIndex >= 0 && rowIndex < rows) {
114+
fill(0, 255, 100, 100);
115+
rect(colIndex * cellWidth, rowIndex * cellHeight, cellWidth, cellHeight);
116+
117+
// Trigger chord once per cell
118+
if (rowIndex !== lastCell.row || colIndex !== lastCell.col) {
119+
playChord(rowIndex, colIndex);
120+
lastCell.row = rowIndex;
121+
lastCell.col = colIndex;
122+
}
123+
} else {
124+
lastCell = { row: -1, col: -1 };
125+
}
126+
} else {
127+
lastCell = { row: -1, col: -1 };
128+
}
129+
130+
// Optionally draw all detections
131+
noFill();
132+
stroke(0, 255, 0);
133+
strokeWeight(2);
134+
for (let i = 0; i < detections.length; i++) {
135+
let det = detections[i];
136+
let mirroredX = width - det.x - det.width; // flip bbox
137+
rect(mirroredX, det.y, det.width, det.height);
138+
noStroke();
139+
fill(255);
140+
text(det.label, mirroredX + 10, det.y + 24);
141+
}
142+
}
143+
144+
// Play chord based on row
145+
function playChord(row, col) {
146+
let root = musicScale[row].freq;
147+
let third = row + 2 < musicScale.length ? musicScale[row + 2].freq : root * 1.25;
148+
let fifth = row + 4 < musicScale.length ? musicScale[row + 4].freq : root * 1.5;
149+
let freqs = [root, third, fifth];
150+
151+
for (let i = 0; i < oscList.length; i++) {
152+
let osc = oscList[i];
153+
let env = envList[i];
154+
osc.freq(freqs[i]);
155+
env.play(osc);
156+
}
157+
}

0 commit comments

Comments
 (0)