Object Detection and Recognition in JS - javascript

I wanted to develop object detection system using ml5 & p5.js,where I can upload an image and system can provide me an output image with Rectangle around objects in image. Yolo and Cocossd datasets are working fine for recognition an object in image.
Like this image object is being identified:
But these datasets are not giving me results for detection where there is text or object with text. As I am expecting system to identify each word of text as different object, like for below image :
Result should be like this:
Rectangle around K
Rectangle around F
Rectangle around C
and one Rectangle around logo of KFC
Please help regarding this or suggest any other system which i can use in PHP/Js to detect objects in image.
let img;
let detector;
function preload(){
img = loadImage('e.jpeg');
detector = ml5.objectDetector('yolo');
}
function setup() {
createCanvas(800, 800);
image(img,0,0);
detector.detect(img,gotDetections);
}
function gotDetections(error, result){
if(error){
console.log(error)
}
console.log(result)
drawResults(result);
// for (let i = 0 ; i< result.length; i++){
// let object = result[i];
// stroke(0,255,255);
// strokeWeight(4);
// noFill();
// rect(object.x ,object.y,object.width,object.height);
// }
}
function drawResults(results) {
results.forEach((result) => {
// Generates a random color for each object
const r = Math.random()*256|0;
const g = Math.random()*256|0;
const b = Math.random()*256|0;
// Draw the text
stroke(0, 0, 0);
strokeWeight(2);
textSize(16);
fill(r, g, b);
text(`${result.label} (${result.confidence.toFixed(2)}%)`, result.x, result.y - 10);
// Draw the rectangle stroke
noFill();
strokeWeight(3);
stroke(r, g, b);
rect(result.x, result.y, result.width, result.height);
});
};
html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
<script src="https://unpkg.com/ml5#latest/dist/ml5.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<main>
</main>
<script src="sketch.js"></script>
</body>
</html>

Related

Linear animation with multiple x,y coordinates

The below code is doing the animation from 2 points , Point (0,0) to Point (100,50) , which is working fine . But i need a function that takes an array of x,y coordinates and keep on running the same below script to draw path one by one . How can this be achieved .
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Chain</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.15/paper-full.js" integrity="sha512-XV5MGZ7Tv+G60rzU8P7tPUlaf0yz7SJ/ uI9CLAwyLcZKl9kzxJQFs3nsBNZVNVAwNOkBLqrzMvjGMEycDccqiA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script type="text/paperscript" canvas="canvas">
var path = new Path();
path.strokeColor = 'white';
path.add(new Point(0, 0));
path.add(new Point(100, 50));
var time = 0;
// On each frame...
function onFrame() {
console.log('Running frame ');
if (time <= 1) {
time += 0.01;
drawTmpPath(time);
}
}
var tmpPath;
function drawTmpPath(t) {
// Make sure that t is never over 1.
t = Math.min(t, 1);
// Remove the previously drawn temporary path.
if (tmpPath) {
tmpPath.remove();
}
// Draw the new temporary path from the reference one.
tmpPath = path.clone().set({
selected: false,
strokeColor: 'orange',
strokeWidth: 5
});
// Split it at the appropriate location.
var remainingPath = tmpPath.splitAt(tmpPath.length * t);
// Remove the eventual remaining part.
if (remainingPath) {
remainingPath.remove();
}
}
</script>
</head>
<body>
<canvas id="canvas" resize></canvas>
</body>
</html>

drawing within an if statement of a function in P5.JS

I want to basically make it that when the record button is pressed and the recording is taking place, that the audio that is being recorded is visualized as per the code in the draw function and then once that is done, the user would be able to save/playback the recording. I think I need to move the content of the draw function somewhere within the if statements of the canvasPressed function but I have no idea how. I'd appreciate any guidance. I am experimenting and adding different bits from different sources so my entire code might be jumbled up and wrong to begin with though the recording, playback, saving part of the code works fine on its own, it's just the drawing bit that doesn't. Thank you in advance.
let mic;
let volHistory = [];
var angle = 0;
let recorder, soundFile;
let state = 0;
function setup() {
let cnv = createCanvas(100, 100);
cnv.mousePressed(canvasPressed);
background(220);
textAlign(CENTER, CENTER);
// create an audio in
mic = new p5.AudioIn();
// prompts user to enable their browser mic
mic.start();
// create a sound recorder
recorder = new p5.SoundRecorder();
// connect the mic to the recorder
recorder.setInput(mic);
// this sound file will be used to
// playback & save the recording
soundFile = new p5.SoundFile();
text('tap to record', width/2, height/2);
}function canvasPressed() {
// ensure audio is enabled
userStartAudio();
// make sure user enabled the mic
if (state === 0 && mic.enabled) {
// record to our p5.SoundFile
recorder.record(soundFile);
background(255,0,0);
text('Recording!', width/2, height/2);
state++;
}
else if (state === 1) {
background(0,255,0);
// stop recorder and
// send result to soundFile
recorder.stop();
text('Done! Tap to play and download', width/2, height/2, width - 20);
state++;
}
else if (state === 2) {
soundFile.play(); // play the result!
save(soundFile, 'mySound.wav');
state++;
}
}
function draw() {
background(51);
let vol = mic.getLevel();
volHistory.push(vol);
translate(width/2, height/2)
noFill();
beginShape();
for (let i = 0; i < 360; i++) {
stroke(255);
let r = map(volHistory[i], 0, 1, 10, 300);
let x = r * cos(i);
let y = r * sin(i);
vertex(x, y);
}
endShape();
if(volHistory.length > 360) {
volHistory.splice(0,1);
}
// ellipse(300, 300, vol*300, vol*300);
// console.log(vol)
}
html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>

How to shift an array of posenet points?

I'm a beginner at using p5.js but I'm currently currently attempting to create a brush sketch like this
ellipse brush
though using computer vision & posenet nose tracking (essentially a nose brush)
The problem is, while it doesn't state any errors, it doesn't work.
This is my code for the ellipse brush without posenet & camera vision
let mousePosition = [];
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
//Every frame of animation
//storing the mouse position in an array
mousePosition.push({x: mouseX, y: mouseY});
//shift the array so that the older ones deletes itself
if(mousePosition.length > 100) mousePosition.shift();
//loop
for(let i = 0; i < mousePosition.length; i++) {
//if the variable is less than 50, loop function
let x = mousePosition[i].x;
let y = mousePosition[i].y;
ellipse(x, y, r,r);
var r = 20
}
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/addons/p5.dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
and this is the one with computer vision & nose tracking w/ posenet
let capture;
let poseNet;
let pose;
let text;
let pg;
let nosePosition = []
function setup() {
createCanvas(700, 700);
capture = createCapture(VIDEO);
capture.hide();
pg = createGraphics(width, height);
poseNet = ml5.poseNet(capture, modelLoaded);
poseNet.on('pose', gotPoses);
// background(255)
// color picker
}
function gotPoses(poses) {
//console.log(poses);
if (poses.length > 0) {
pose = poses[0].pose;
}
}
function modelLoaded() {
console.log('poseNet.ready');
}
function draw() {
translate(width, 0); // move to far corner
scale(-1.0, 1.0); // flip x-axis backwards
image(capture, 0, 0, width, width * capture.height /
capture.width);
image(pg, 0, 0, width, height);
if (pose) {
nosePosition.push({x:pose.nose.x ,y: pose.nose.y});
if(nosePosition.length > 100) nosePosition.shift(); {
}
for(let i = 0; i < nosePosition.length; i++) {
//if the variable is less than 50, loop function
let x = nosePosition[i].x;
let y = nosePosition[i].y;
pg.ellipse(x, y, i/5,i/5);
var r = 20 //how big the ellipse is
pg.fill(255)
pg.noStroke();
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/addons/p5.sound.min.js"></script>
<script src="https://unpkg.com/ml5#latest/dist/ml5.min.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
The second is essentially very similar to the first, as I've only changed the mouseX/Ys into the posenet Nose keypoint.
Any insight/solution would be highly appreciated!
Thank you :)
You're shifting properly, but you forgot to clear the pg graphic, which is kind of like forgetting to put background(0) in your original sketch. So instead of drawing all the ellipses on a blank background, you're drawing them on top of the previous frame.
Adding pg.clear() anywhere in draw() after you display pg on the canvas (image(pg, ...)) and before you draw the ellipses (for (...) {... ellipse(nosePosition[i].x...)}) should do the trick. Here's where I put it:
image(pg, 0, 0, width, height);
pg.clear();//HERE
if (pose) {//...

Vertices with indexArray doesn't connect triangles properly

I'm trying to create a sort of "polygon drawer" in p5.js.
My intented behaviour is that a random triangle out of three vertices gets ctreated at start and the user can use his mouse to add triangles, which automatically connect to the two closest vertices from the mouseCursor.
This allw orks fine, but sometimes when I start adding the new vertice by clicking (the current vector at the mouse get's pushed to the array of vertices and the triangle / index array get' updated), a triangle get's drawn which uses a different vertice, not the closest, second closest and the mouse cursor vector.
I have two arrays for the vertices and triangles (the later functions as an index array):
let vertices = [];
let triangles = [];
Globally I track the closest and second closest index of the vertices array:
let closest;
let secondClosest;
I start by creating a random triangle. I push each vertex' index to the triangle array and push the first one once again to complete the triangle:
function createRandomTriangle(){
for(i = 0; i < 3; i++){
let vert = createVector(random(0, width),random(0, height));
vertices.push(vert);
triangles.push(i);
}
triangles.push(0);
}
In my draw function I first draw every triangle by going through the triangles array and drawing lines from their vector equivalents in the vertices array.
I then calculate which two vertices are closest to the mouse cursor and update my globals.
As the last step I draw the trianlge from the mouse cursor as some sort of "guide".
function draw() {
background(255);
for(i = 0; i < triangles.length-1; i++){
line(vertices[triangles[i]].x, vertices[triangles[i]].y,vertices[triangles[i+1]].x, vertices[triangles[i+1]].y);
}
let mouseVector = createVector(mouseX, mouseY);
let distances = [];
for(i = 0; i < vertices.length; i++){
distances.push(mouseVector.dist(vertices[i]));
}
closest = distances.indexOf(Math.min( ...distances ));
distances[closest] = width + height;
secondClosest = distances.indexOf(Math.min( ...distances ));
line(mouseVector.x, mouseVector.y, vertices[closest].x, vertices[closest].y);
line(mouseVector.x, mouseVector.y, vertices[secondClosest].x, vertices[secondClosest].y);
line(vertices[closest].x, vertices[closest].y, vertices[secondClosest].x, vertices[secondClosest].y);
}
Now this function is probably the one causing harm, but I can't figure out why.
Once the user clicks, the mouse cursor vector get's pushed to the array of vertices, his index is pushed first to the triangles array, then the closest index, then the second closest index, then the mouse cursor index again.
function mouseClicked() {
let latestIndex = vertices.push(createVector(mouseX, mouseY)) - 1;
triangles.push(latestIndex);
triangles.push(closest);
triangles.push(secondClosest);
triangles.push(latestIndex);
}
Sometimes this method works fine and sometimes a new line suddenly appears.
I can't comprehend exactly why.
You can test thje p5.js sketch here: https://editor.p5js.org/etlam/sketches/4SAhIydAC
Here is a very basic example of how you might go about drawing a polygon. I really recommend creating a StateMaker, so you can keep track of everything, but that's more than I'm willing to go into right now.
//<![CDATA[
/* js/external.js */
let doc, htm, bod, nav, M, I, mobile, S, Q;
addEventListener('load', ()=>{
doc = document; htm = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id);
mobile = nav.userAgent.match(/Mobi/i) ? true : false;
S = (selector, within)=>{
let w = within || doc;
return w.querySelector(selector);
}
Q = (selector, within)=>{
let w = within || doc;
return w.querySelectorAll(selector);
}
rand = (min, max)=>{
let mn = min, mx = max;
if(mx === undefined){
mx = mn; mn = 0;
}
return mn+Math.floor(Math.random()*(mx-mn+1));
}
// tiny library above magic below - can put on another page using a load Event (besides // end load line)
const can = I('can'), canB = can.getBoundingClientRect();
const canW = can.width = canB.width, canH = can.height = canB.height;
const ctx = can.getContext('2d'), points = [];
ctx.lineWidth = '1px'; ctx.lineStyle = '#000'; ctx.fillStyle = '#700';
function polyFun(e){
let b = can.getBoundingClientRect();
ctx.clearRect(0, 0, canW, canH);
points.push([e.clientX-b.left, e.clientY-b.top]);
ctx.beginPath(); ctx.moveTo(...points[0]);
for(let i=1,l=points.length; i<l; i++){
ctx.lineTo(...points[i]);
}
ctx.fill(); ctx.stroke(); ctx.closePath();
}
if(mobile){
ontouchstart = e=>{
polyFun(e.touches[0]);
}
}
else{
onmousedown = polyFun;
}
}); // end load
//]]>
/* css/external.css */
*{
box-sizing:border-box; font-size:0; padding:0; margin:0;
}
html,body,#can{
width:100%; height:100%;
}
#can{
cursor:pointer;
}
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
<title>Title Here</title>
<link type='text/css' rel='stylesheet' href='css/external.css' />
<script src='js/external.js'></script>
</head>
<body>
<canvas id='can'></canvas>
</body>
</html>

How can I use JavaScript setTimeout in p5.js to illustrate a merge sort?

I created a JavaScript & p5.js illustration for a merge sort. It works perfectly, all that I want is to make it sort at given time intervals. Where do I need to put the setTimeout or setInterval function, in order to show the numbers sort at 500ms interval? This is my p5 editor link: https://editor.p5js.org/alexrotariu/sketches/m4AFV21qJ
numbers = [15, 20, 4, 1, 25, 45, 32, 4];
function doMergeSort() {
numbers = mergeSort(numbers);
}
function mergeSort(array) {
if (array.length < 2) {
return array;
}
let middle = parseInt(array.length/2);
let left = array.slice(0, middle);
let right = array.slice(middle, array.length);
return merge(mergeSort(left), mergeSort(right))
}
function merge(left, right) {
let result = [];
while (left.length && right.length) {
if (left[0] <= right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while (left.length) {
result.push(left.shift());
}
while (right.length) {
result.push(right.shift());
}
return result;
}
To answer fully I will need to see how you handle your draw method. Remember that he main loop of your application is in draw. This means that it will not change as methods are called in the draw loop, but only give you the results of everything at the end of draw and update the screen with that.
If you are calling doMergeSort() in the draw method, you will always be drawing the sorted array.
You will have to find some way to break up the merge sort algorithm so that each step is incremented by a loop through draw. This usually requires "breaking" the algorithm in sone way for the purpose of demonstrating it.
Here is a very simple example of the concept I am talking about:
Notice how circleB doesnt update for every iteration of the UpdateCircleB() for loop, it only updates once the end of Draw() is reached.
let circleA = {
y : 50,
x : 30,
r : 50
}
let circleB = {
y : 150,
x : 30,
r : 50
}
function setup() {
createCanvas(600, 200);
}
function draw() {
//Increment Purple circle using draw loop
//Every time we draw a frame, we move circle A 1 pixel to the right
circleA.x++;
//The green circle uses a for loop inside a method call to update
//Every time we draw a frame, we move circle B 50 pixels to the right
moveCircleB();
//draw purple circle
fill(152, 114, 132);
ellipse(circleA.x,circleA.y,circleA.r);
//draw green circle
fill(157, 191, 158);
ellipse(circleB.x,circleB.y,circleB.r);
}
function moveCircleB(){
for(var i = 0; i < 50; i++){
circleB.x++;
}
}
html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>

Categories