Surround video with opaque circle efficiently

I am trying to have the person in a video appear in the middle of a circle.
Like so:

Here’s my naive approach.
Find the height of the person and the middle of the person with posenet:

hPerson = dist(pose.nose.x, pose.nose.y, pose.rightAnkle.x, pose.rightAnkle.y)
middlePerson = {x:(pose.rightHip.x+pose.leftHip.x)/2,  y:(pose.rightHip.y+pose.leftHip.y)/2}

Loop over all pixels. If it’s far enough, make it black.

loadPixels();
  for (var x=0; x < width; x+=2){
    for (var y=0; y < height; y+=2){
    pix_to_middle = dist(middlePerson.x,middlePerson.y,x,y)
     if (pix_to_middle > 0.8*hPerson){
		    pixel_colour = 0;
		    pixel_location = (x + y*width)*4;
		    pixels[pixel_location + 0] = pixel_colour;
		    pixels[pixel_location + 1] = pixel_colour;
		    pixels[pixel_location + 2] = pixel_colour;
		    pixels[pixel_location + 3] = 255;
		}
	    }
	}
	updatePixels();

This works, but it seems really inefficient. Is there a better way to achieve this?

If you need better performance you could loop through each line and calculate where that line intersects the circle. Something like this.

loadPixels();
var hPersonSquared=0.64*hPerson*hPerson; //0.8*hPerson squared
for (var x=0; x < width; x+=2){
    var xDistanceSquared=(middlePerson.x-x)*(middlePerson.x-x); 
    var yIntersect=sqrt(hPersonSquared-xDistanceSquared); //use pythagoras to calculate y intersect
    for (var y=0; y < yIntersect; y+=2){
	    pixel_colour = 0;
	    pixel_location = (x + y*width)*4;
	    pixels[pixel_location + 0] = pixel_colour;
	    pixels[pixel_location + 1] = pixel_colour;
	    pixels[pixel_location + 2] = pixel_colour;
	    pixels[pixel_location + 3] = 255;
            pixel_location = (x + (height-y)*width)*4; //repeat from the other side because circles are symmetric
	    pixels[pixel_location + 0] = pixel_colour;
	    pixels[pixel_location + 1] = pixel_colour;
	    pixels[pixel_location + 2] = pixel_colour;
	    pixels[pixel_location + 3] = 255;
    }
}
updatePixels();

If you’re doing this for every frame of a video you might also consider making an array of which pixels you want to black out. Though I’m not sure if that will save much processing time.

1 Like