pulse-monitor/backups/backup_20251122/test_rotation.go

203 lines
5.9 KiB
Go

package main
import (
"fmt"
"log"
"os"
"gocv.io/x/gocv"
)
// Global DEBUG flag
var DEBUG = false
func main() {
// Parse command line args
if len(os.Args) > 1 && os.Args[1] == "/debug" {
DEBUG = true
fmt.Println("DEBUG mode enabled\n")
}
// Hardcode RTSP URL
streamURL := "rtsp://tapohass:!!Helder06@192.168.2.183:554/stream1"
fmt.Println("Rotation Detection System")
fmt.Println("========================")
fmt.Println("Processing frames...\n")
// Open RTSP stream
stream, err := gocv.OpenVideoCapture(streamURL)
if err != nil {
log.Fatalf("Failed to open stream: %v", err)
}
defer stream.Close()
// Initialize detection state
rotation := 9999.0 // Sentinel value for "not detected"
width := 0 // 0 means "not detected"
// Frame processing counters
framesSkipped := 0
framesProcessed := 0
detectionAttempts := 0
totalFramesRead := 0
SKIP_COUNT := 7 // Process every 8th frame
MAX_DETECTION_ATTEMPTS := 100 // Give up after 100 attempts
RE_DETECT_AFTER := 0 // Re-detect after N frames (0 = disabled)
// Main processing loop
frame := gocv.NewMat()
defer frame.Close()
for {
// Acquire a frame
if ok := stream.Read(&frame); !ok || frame.Empty() {
log.Fatal("Failed to read frame from stream")
}
totalFramesRead++
// Preprocess frame to binary
binary := PreprocessFrame(frame)
// If rotation is 9999 or width is 0, detect bands/width/rotation
if rotation == 9999 || width == 0 {
detectionAttempts++
// Give up if too many attempts
if detectionAttempts > MAX_DETECTION_ATTEMPTS {
fmt.Printf("❌ Detection failed after %d attempts. Exiting.\n", MAX_DETECTION_ATTEMPTS)
break
}
result := DetectRotationAndWidth(binary)
if result.Success {
rotation = result.Rotation
width = result.Width
fmt.Printf("✓ DETECTION SUCCESSFUL (frame %d, attempt #%d): Width=%dpx, Rotation=%.3f°\n\n",
totalFramesRead, detectionAttempts, width, rotation)
detectionAttempts = 0 // Reset counter
} else {
// Show detection attempts with frame info
if detectionAttempts <= 5 {
if DEBUG {
fmt.Printf("Frame %d: Detection attempt #%d failed\n", totalFramesRead, detectionAttempts)
}
} else {
fmt.Printf("⚠ Frame %d: Detection attempt #%d failed - retrying...\n", totalFramesRead, detectionAttempts)
}
// Clean up and continue to next frame
binary.Close()
// Skip a few frames to ensure display has changed
for skip := 0; skip < 3; skip++ {
if ok := stream.Read(&frame); !ok {
break
}
}
continue
}
}
// If rotation != 9999 and width != 0 and we've skipped enough frames
if rotation != 9999 && width != 0 && framesSkipped >= SKIP_COUNT {
framesProcessed++
// Rotate the image to correct orientation
rotated := RotateImage(binary, rotation)
defer rotated.Close()
// Calculate scale factor based on detected width
scaleFactor := 860.0 / float64(width)
// Scale to 860px width using the scale factor
scaled := ScaleByFactor(rotated, scaleFactor)
defer scaled.Close()
fmt.Printf("Frame #%d processed: Rotated %.3f°, Scaled from %dpx to 860px (factor: %.3f)\n",
framesProcessed, rotation, width, scaleFactor)
// Re-detect bands on the scaled image
// Scale the 80px minimum height by the same factor
scaledMinHeight := int(80.0 * scaleFactor)
bands := DetectBands(scaled, scaledMinHeight)
if DEBUG {
fmt.Printf(" Using scaled minimum height: %dpx (80px * %.3f)\n", scaledMinHeight, scaleFactor)
fmt.Printf(" Found %d bands on scaled image:\n", len(bands))
for i, band := range bands {
fmt.Printf(" Band #%d: Y range [%d-%d], Height: %dpx\n",
i+1, band.minY, band.maxY, band.maxY-band.minY)
}
}
// We should have exactly 2 bands: graph and digits
if len(bands) == 2 {
// First band should be graph (taller), second should be digits
graphBand := bands[0]
digitBand := bands[1]
// Verify graph band is taller
graphHeight := graphBand.maxY - graphBand.minY
digitHeight := digitBand.maxY - digitBand.minY
if graphHeight < digitHeight {
// Swap if needed
graphBand, digitBand = digitBand, graphBand
}
fmt.Printf(" ✓ Graph band: Y [%d-%d], Height: %dpx\n",
graphBand.minY, graphBand.maxY, graphBand.maxY-graphBand.minY)
fmt.Printf(" ✓ Digit band: Y [%d-%d], Height: %dpx\n",
digitBand.minY, digitBand.maxY, digitBand.maxY-digitBand.minY)
// Extract just the digit band region for OCR
digitRegion := ExtractBandRegion(scaled, digitBand)
defer digitRegion.Close()
// Save visualization if in DEBUG mode
if DEBUG && framesProcessed <= 5 {
// Simple visualization with just 2 bands
VisualizeSimpleBands(scaled, graphBand, digitBand,
fmt.Sprintf("debug_frame_%03d_bands.png", framesProcessed))
// Save just the digit region
digitFilename := fmt.Sprintf("debug_frame_%03d_digits.png", framesProcessed)
gocv.IMWrite(digitFilename, digitRegion)
fmt.Printf("DEBUG: Saved digit region to %s\n", digitFilename)
}
// TODO: Run OCR on digitRegion here
} else {
fmt.Printf(" ⚠ Expected 2 bands, found %d bands (>%dpx height)\n", len(bands), scaledMinHeight)
}
// Save debug images if in DEBUG mode
if DEBUG && framesProcessed <= 5 {
filename := fmt.Sprintf("debug_frame_%03d_scaled.png", framesProcessed)
gocv.IMWrite(filename, scaled)
fmt.Printf("DEBUG: Saved %s\n", filename)
}
// TODO: Add OCR processing on 'scaled' image here in later phase
framesSkipped = 0
// Optional: Force re-detection after N frames to adapt to changes
if RE_DETECT_AFTER > 0 && framesProcessed >= RE_DETECT_AFTER {
fmt.Printf("\n🔄 Re-detecting after %d frames...\n", RE_DETECT_AFTER)
rotation = 9999
width = 0
framesProcessed = 0
}
} else {
framesSkipped++
}
// Clean up
binary.Close()
}
fmt.Println("\nProgram terminated.")
}