import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import gab.opencv.*;
import processing.video.*;
import controlP5.*;
import java.awt.Rectangle;
Movie video;
OpenCV opencv;
ControlP5 cp5;
// HSV Threshold variables (linked to sliders)
int minH = 0, maxH = 179;
int minS = 0, maxS = 30; // Low saturation for white
int minV = 200, maxV = 255; // High value/brightness for white
ArrayList<PVector> path = new ArrayList<PVector>();
//Mat hsv;
//Mat mask;
void setup() {
size(1466, 412); // Double width to show both views
video = new Movie(this, "IMG_0339.MOV");
video.loop();
// hsv = new Mat();
// mask = new Mat();
opencv = new OpenCV(this, 733, 412);
cp5 = new ControlP5(this);
// Add Sliders for real-time tuning
int y = 20;
cp5.addSlider("minH").setPosition(20, y).setRange(0, 179);
cp5.addSlider("maxH").setPosition(20, y+=20).setRange(0, 179);
cp5.addSlider("minS").setPosition(20, y+=20).setRange(0, 255);
cp5.addSlider("maxS").setPosition(20, y+=20).setRange(0, 255);
cp5.addSlider("minV").setPosition(20, y+=20).setRange(0, 255);
cp5.addSlider("maxV").setPosition(20, y+=20).setRange(0, 255);
}
void draw() {
if (video.available()) {
video.read();
image(video,0,0);
opencv.loadImage(video);
// opencv.toCV(hsv);
// 1. Convert to HSV and Threshold
opencv.useColor(HSB);
// opencv.threshold(220);
// opencv.convert(HSB);
opencv.setGray(opencv.getH());
// opencv.threshold(200);
// Scalar min = new Scalar(0, 100, 100);
// Scalar max = new Scalar(50, 255, 255);
// Correct method: takes Scalar objects [6]
opencv.inRange(minH, maxH);
// Core.inRange(hsv, min, max, mask);
// opencv.inRange(0,255);
// 2. Capture the binary mask for display
PImage maskImage = opencv.getSnapshot();
// 3. Track the ball (finding the largest white contour)
ArrayList<Contour> contours = opencv.findContours();
// 3. Find the LARGEST contour instead of just the first one
Contour ball = null;
double maxArea = 0;
for (Contour c : contours) {
if (c.area() > maxArea) {
maxArea = c.area();
ball = c;
}
}
if (ball != null) {
Rectangle r = ball.getBoundingBox();
// Adjust size check based on your video resolution
if (r.width < 100 && r.height < 100) {
path.add(new PVector(r.x + r.width/2, r.y + r.height/2));
}
}
/* if (contours.size() > 0) {
Contour ball = contours.get(0); // Assumes ball is the most prominent object
Rectangle r = ball.getBoundingBox();
// Only add point if it meets a reasonable size for a golf ball
// if (r.width < 50 && r.height < 50) {
if (r.width < 100 && r.height < 100) {
path.add(new PVector(r.x + r.width/2, r.y + r.height/2));
}
} */
// 4. Visual Output
image(video, 0, 0, 733, 412); // Left: Original Video
image(maskImage, 733, 0, 733, 412); // Right: What OpenCV sees
image(video, 0, 0, 733, 412); // Left: Original Video
image(maskImage, 733, 0, 733, 412); // Right: What OpenCV sees
// Draw the tracer line on the original video
drawTracer();
}
}
void drawTracer() {
noFill();
stroke(255, 0, 0); // Red tracer line
strokeWeight(3);
beginShape();
for (PVector p : path) {
vertex(p.x, p.y);
}
endShape();
}