Previously I mentioned the two potential pathways for my simulation.
See the Pen XWjLqpE by steven oh (@stevenohohohohoh) on CodePen.
I have updated the simulation. I added on-page buttons and input fields where I can directly change the parameters of the simulation. Respectively, "degree per frame", "x-force" and "y-force". Degree per frame is the speed of the rotation, and x, y forces just force vectors that push the ball. I also added the screen-recording function which records the screen as the button is pressed, and stops as the "stop" button is pressed. The video is then automatically downloaded.
async function startRecording() { stream = await navigator.mediaDevices.getDisplayMedia({ video: { mediaSource: "screen" }, }); recorder = new MediaRecorder(stream); const chunks = []; recorder.ondataavailable = (e) => chunks.push(e.data); recorder.onstop = (e) => { const completeBlob = new Blob(chunks, { type: chunks[0].type }); setVideo(completeBlob); }; recorder.start(); } function download(blob_url) { var fileName = "video.mp4"; var a = document.createElement("a"); a.href = blob_url; a.download = fileName; a.textContent = "DOWNLOAD " + fileName; document.getElementById("download").appendChild(a); a.click(); }The screen-recording function saves the video into a Blob. For people like me who don't know what a Blob is
A Blob is an opaque reference to, or handle for, a chunk of data. The name comes from SQL databases, where it means “Binary Large Object.” In JavaScript, Blobs often represent binary data, and they can be large, but neither is required: a Blob could also represent the contents of a small text file.
import cv2 import numpy as np import csv import pandas as pd # Open the video cap = cv2.VideoCapture('video-5.mp4') x_c = [] y_c = [] circles_all = [] i = 0 while True: success, new_frame = cap.read() # Take each frame if success: i += 1 frame = new_frame crop_img = frame[200:2000, 600:2500].copy() gray = cv2.cvtColor(crop_img, cv2.COLOR_BGR2GRAY) circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp=1.5, minDist=505, param1=75, param2=30, minRadius=8,maxRadius=30) # ensure at least some circles were found if circles is not None: # convert the (x, y) coordinates and radius of the circles to integers circles = np.round(circles[0, :]).astype("int") # loop over the (x, y) coordinates and radius of the circles for x, y, r in circles: print(x, y) x_c.append(x) y_c.append(y) circles_all.append([x, y, r]) # draw the circle in the output image, then draw a rectangle # corresponding to the center of the circle cv2.circle(crop_img, (x, y), r, (0, 255, 0), 4) cv2.rectangle(crop_img, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1) #cv2.imshow('hi', crop_img) #cv2.waitKey(0) else: crop_img = frame[200:2000, 600:2500].copy() for (x, y, r) in circles_all: # draw the circle in the output image, then draw a rectangle # corresponding to the center of the circle cv2.circle(crop_img, (x, y), 7, (255, 0, 0), -1) #cv2.rectangle(crop_img, (x - 5, y - 5),(x + 5, y + 5), (0, 128, 255), -1) cv2.imwrite('lastframe.jpg', crop_img) break print("Number of captured frames: ", i) print("The length of list is: ", len(circles_all)) cv2.destroyAllWindows() df = pd.DataFrame({ "x" : np.array(x_c), "y" : np.array(y_c)}) df.to_csv("coord.csv", index=False)
The screen recording records the whole screen, including the toolbar and tabs in the browser - this can be confusing for an Opencv program. Therefore, for each frame, I cropped the frame so only the rotating circle and the ball is left. Then, I used
HoughCirclesfunction to search for a circle with the specified parameters like min and max radius, the minimum distance between the center of this circle to another circle.etc. Gotta give credit to soysoy444 this time, he helped me debug and it was super helpful. Anyways, this program returns the x positions and y positions of the ball for each frame, and I was able to save it in a CSV file. I recorded a random example (I made the ball go in a circle) and graphed the x and y positions of the ball with respect to time.
y-position of the ball and x-position of the ball
I also recorded a projectile in a non-inertial frame. Since the coordinate system in Opencv is like the 4th quadrant in the Cartesian plane but with positive y-values, I also attached an image of the position graph with the correct Cartesian coordinates(in the 4th quadrant)
Now that I can collect data for the experiment, my next target will be to first fine-tune my data-collecting process and then begin researching more about the theory.