Production-ready computer vision service for American Football field detection and Position State (PoS) fact generation
Motion Logic CV is a gRPC-based microservice that detects field boundaries, lines of scrimmage, and ball locations from video. It integrates seamlessly with the Motion Logic Platform's SOA architecture, streaming structured PoS facts to the IKB (Neo4j) for Sequent Logic reasoning.
- Field Detection: HSV-based green field segmentation with convex hull extraction
- Line of Scrimmage: Hough line transform for parallel yard line detection
- Ball Location: Edge density centroid method for ball tracking
- Coordinate Transformation: Homography-based pixel-to-field coordinate mapping
- gRPC Service: High-performance streaming RPC for real-time processing
- Protocol Buffers: Type-safe data contracts for PoS facts
- SOA Integration: Designed for Motion Logic Platform (API Gateway β CV Service β IKB β Sequent Logic)
- Docker Deployment: Containerized service with docker-compose orchestration
LineOfScrimmageState: Yard line, pixel coordinates, confidenceBallLocationState: Pixel position, field position, in-play statusFieldState: Complete field state with all detectionsFieldLine: Individual field line with classification
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β SDK Client β ββββΆ β API Gateway β ββββΆ β CV Service β
β (Python/C#) β β (nginx) β β (gRPC) β
ββββββββββββββββ ββββββββββββββββ ββββββββ¬ββββββββ
β
βΌ
ββββββββββββββββ ββββββββββββββββ
β Sequent β ββββ β IKB β
β Logic β β (Neo4j) β
ββββββββββββββββ ββββββββββββββββ
Data Flow:
- SDK clients send video frames to API Gateway
- Gateway routes to CV Service (this repo)
- CV Service processes frames and extracts PoS facts
- Facts streamed to IKB for graph storage
- Sequent Logic performs declarative reasoning on facts
# Clone repository
git clone https://github.com/motionlogic/motionlogic-computer-vision.git
cd motionlogic-computer-vision
# Install dependencies
pip install -r requirements.txt
# Generate Protocol Buffer code
python -m grpc_tools.protoc \
-I./protos \
--python_out=./motionlogic_cv/generated \
--grpc_python_out=./motionlogic_cv/generated \
protos/field_facts.protofrom motionlogic_cv import AmericanFootballDetector
import cv2
# Initialize detector
detector = AmericanFootballDetector()
# Load frame
frame = cv2.imread('football_frame.jpg')
# Detect field state
field_state = detector.detect_field_state(frame, frame_id=0)
# Access PoS facts
if field_state.line_of_scrimmage:
print(f"Line of scrimmage: {field_state.line_of_scrimmage.yard_line} yards")
print(f"Confidence: {field_state.line_of_scrimmage.confidence:.2%}")
if field_state.ball_location:
ball = field_state.ball_location
print(f"Ball at pixel ({ball.pixel_position.x}, {ball.pixel_position.y})")# Start gRPC server
python src/server.py --port 50051
# With custom configuration
python src/server.py --config config/detection_params.yamlimport grpc
from motionlogic_cv.generated import field_facts_pb2, field_facts_pb2_grpc
# Connect to service
channel = grpc.insecure_channel('localhost:50051')
stub = field_facts_pb2_grpc.FieldDetectionServiceStub(channel)
# Stream field states from video
request = field_facts_pb2.StreamFieldStatesRequest(
video_id='path/to/game.mp4',
max_frames=100,
)
for response in stub.StreamFieldStates(request):
if response.success:
state = response.field_state
print(f"Frame {state.frame_id}: {state.line_of_scrimmage.yard_line} yards")# Build image
docker build -t motionlogic-cv:latest .
# Run container
docker run -p 50051:50051 motionlogic-cv:latest
# Using docker-compose (full stack)
docker-compose up -d
# With IKB and Sequent Logic
docker-compose --profile full-stack up -d- cv-service: gRPC field detection service (port 50051)
- api-gateway: nginx reverse proxy (port 8080)
- ikb-neo4j: Neo4j graph database (ports 7474, 7687)
- sequent-engine: Sequent Logic reasoning engine
python examples/standalone_detection.py \
--input game.mp4 \
--output results.csv \
--visualize# Start server
python src/server.py
# In another terminal, run client
python examples/grpc_client.py --video game.mp4 --max-frames 100python examples/grpc_client.py --healthfield_detector:
min_line_length: 50 # Hough line minimum length
max_line_gap: 25 # Maximum gap in line segments
hough_threshold: 80 # Line detection threshold
canny_threshold1: 100 # Edge detection low threshold
canny_threshold2: 200 # Edge detection high threshold
green_lower_hsv: [35, 40, 40] # Green field HSV range
green_upper_hsv: [85, 255, 255]
white_lower_hsv: [0, 0, 200] # White line HSV range
white_upper_hsv: [180, 30, 255]motionlogic-computer-vision/
βββ motionlogic_cv/ # Core package
β βββ field_detection.py # Generic field detector
β βββ line_detection.py # Line detection (Hough)
β βββ american_football_detector.py # American Football specialization
β βββ models/ # PoS fact data models
β β βββ field_facts.py
β βββ services/ # gRPC service implementation
β β βββ field_detection_service.py
β βββ generated/ # Auto-generated Protocol Buffer code
β βββ field_facts_pb2.py
β βββ field_facts_pb2_grpc.py
βββ protos/ # Protocol Buffer definitions
β βββ field_facts.proto
βββ src/
β βββ server.py # gRPC server entry point
βββ examples/
β βββ demo.py # Generic demo (multi-sport)
β βββ standalone_detection.py # Standalone American Football detection
β βββ grpc_client.py # gRPC client example
βββ config/
β βββ detection_params.yaml # Configuration file
βββ Dockerfile # Production container
βββ docker-compose.yml # Full stack orchestration
βββ requirements.txt # Python dependencies
service FieldDetectionService {
// Detect field in single frame (unary RPC)
rpc DetectField(DetectFieldRequest) returns (DetectFieldResponse);
// Stream field states from video (server-streaming RPC)
rpc StreamFieldStates(StreamFieldStatesRequest) returns (stream StreamFieldStatesResponse);
// Health check
rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse);
}message FieldState {
int32 frame_id = 1;
LineOfScrimmageState line_of_scrimmage = 3;
BallLocationState ball_location = 4;
repeated FieldLine field_lines = 6;
repeated double homography_matrix = 7; // 3x3 matrix
}
message LineOfScrimmageState {
int32 yard_line = 1; // 0-100 yards
repeated FieldCoordinate pixel_coords = 2;
float confidence = 3; // 0.0-1.0
int32 frame_id = 4;
}
message BallLocationState {
FieldCoordinate pixel_position = 1;
FieldCoordinate field_position = 2; // Transformed to meters
float confidence = 3;
bool is_in_play = 7;
}Tested on Intel i7-10700K, 16GB RAM, no GPU:
| Metric | Value |
|---|---|
| Field Detection | ~30 FPS (1080p) |
| Line of Scrimmage | ~28 FPS |
| Ball Location | ~25 FPS |
| gRPC Overhead | <5ms per frame |
| Memory Usage | ~200MB |
Optimization Tips:
- Use
skip_framesparameter to process every Nth frame - Enable GPU with OpenCV CUDA build for 2-3x speedup
- Adjust Hough threshold for speed/accuracy tradeoff
python -m grpc_tools.protoc \
-I./protos \
--python_out=./motionlogic_cv/generated \
--grpc_python_out=./motionlogic_cv/generated \
protos/field_facts.protopytest tests/ --cov=motionlogic_cvblack motionlogic_cv/
flake8 motionlogic_cv/PoS facts are automatically ingested into Neo4j graph database:
// Example Cypher query to retrieve line of scrimmage states
MATCH (f:FieldState)-[:HAS_LOS]->(los:LineOfScrimmage)
WHERE f.video_id = 'game_001' AND f.frame_id > 1000
RETURN los.yard_line, los.confidence, f.timestamp_ms
ORDER BY f.frame_id// Example: Detect first downs
rule FirstDown(frame, old_los, new_los) :-
LineOfScrimmage(frame, new_los),
LineOfScrimmage(frame-N, old_los),
new_los.yard_line - old_los.yard_line >= 10.
We welcome contributions! Areas where you can help:
- Accuracy Improvements: Better yard line estimation, calibration
- 3D Tracking: Add Z-coordinate for ball height
- Multi-Camera: Fuse detections from multiple camera angles
- GPU Acceleration: CUDA optimizations
- Documentation: Tutorials, API guides
See CONTRIBUTING.md for guidelines.
Apache License 2.0 - See LICENSE for details.
- OpenCV - Computer vision algorithms
- gRPC - High-performance RPC framework
- Protocol Buffers - Data serialization
- Neo4j - Graph database for PoS facts
- Sequent Logic - Declarative spatiotemporal reasoning
- GitHub: https://github.com/motionlogic
- Email: hello@motionlogic.org
- Kaggle: @analyzemyteam
Built with β€οΈ by the Motion Logic community