From 55236c0a24653cc60a6af0d6131e7e6ad9d0605d Mon Sep 17 00:00:00 2001 From: aria Date: Thu, 26 Jun 2025 00:12:17 +1000 Subject: [PATCH 1/3] feat(analyze-frame-persistence): add flags for defining min res This should allow for improved results, at the very least filtering out junk data --- main.go | 129 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 103 insertions(+), 26 deletions(-) diff --git a/main.go b/main.go index 1e3dd58..eb42745 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "cmp" "context" "encoding/csv" + "errors" "fmt" "image" "image/draw" @@ -100,9 +101,9 @@ func main() { }, }, Flags: []cli.Flag{ - &cli.Float64Flag{ + &cli.Uint64Flag{ Name: "tolerance", - Usage: "Pixel difference tolerance (0-255)", + Usage: "Pixel difference tolerance (0-255?)", Value: 0, }, &cli.StringFlag{ @@ -121,11 +122,35 @@ func main() { Usage: "print out total unique frames for every second of measurements", Value: false, }, + + &cli.BoolFlag{ + Name: "testing-log", + Usage: "make a seperate output csv in the same folder that live updates", + Value: false, + }, + + &cli.IntFlag{ + Name: "resdet-minimum-height", + Usage: "minimum possible height of detected image", + Value: 0, + }, + + &cli.IntFlag{ + Name: "resdet-minimum-width", + Usage: "minimum possible width of detected image", + Value: 0, + }, }, Action: func(ctx context.Context, cmd *cli.Command) error { - tolerance := uint64(cmd.Float64("tolerance")) + videoPath := cmd.StringArg("video") + + if videoPath == "" { + return fmt.Errorf("Must provide video path") + } + + tolerance := cmd.Uint64("tolerance") csvOutput := cmd.String("csv-output") - return analyzeFramePersistence(cmd.StringArg("video"), tolerance, csvOutput, cmd.Bool("resdet"), cmd.Bool("verbose")) + return analyzeFramePersistence(cmd.StringArg("video"), tolerance, csvOutput, cmd.Bool("resdet"), cmd.Bool("verbose"), cmd.Int("resdet-minimum-height"), cmd.Int("resdet-minimum-width"), cmd.Bool("testing-log")) }, }, }, @@ -267,7 +292,7 @@ func getImageFromFilePath(filePath string) (image.Image, error) { return image, err } -func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput string, toggleResdet bool, verbose bool) error { +func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput string, toggleResdet bool, verbose bool, minResdetHeight int, minResdetWidth int, liveCSV bool) error { video, err := vidio.NewVideo(videoPath) if err != nil { return err @@ -341,28 +366,17 @@ func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput strin // mesure resoltion if toggleResdet { - frameFile, err0 := os.Create("/tmp/frame.png") + var lastFrameWidth int + var lastFrameHeight int - err1 := png.Encode(frameFile, currentFrame) - - out, err2 := exec.Command("resdet", "-v", "1", frameFile.Name()).Output() - - err3 := frameFile.Close() - - err4 := os.Remove(frameFile.Name()) - - formattedOutput := strings.Split(string(out), " ") - - frameWidthOut, err5 := strconv.Atoi(formattedOutput[0]) - - frameHeightOut, err6 := strconv.Atoi(strings.TrimSuffix(formattedOutput[1], "\n")) - - if err := cmp.Or(err0, err1, err2, err3, err4, err5, err6); err != nil { - log.Fatal(err) + if len(frameWidthMeasurements) != 0 { + lastFrameWidth = frameWidthMeasurements[len(frameWidthMeasurements)-1] + lastFrameHeight = frameHeightMeasurements[len(frameHeightMeasurements)-1] + } else { + lastFrameWidth = currentFrame.Bounds().Max.X + lastFrameHeight = currentFrame.Bounds().Max.X } - - frameWidth = frameWidthOut - frameHeight = frameHeightOut + frameWidth, frameHeight = resdet(verbose, currentFrame, frameWidth, frameHeight, minResdetHeight, minResdetHeight, lastFrameWidth, lastFrameHeight) } frameWidthMeasurements = append(frameWidthMeasurements, frameWidth) @@ -372,7 +386,7 @@ func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput strin copy(previousFrame.Pix, currentFrame.Pix) hasFirstFrame = true uniqueFramesInCurrentSecond = 1 - totalUniqueFrames = 1 + totalUniqueFrames = 0 currentUniqueFrameDuration = 1 // Store data for first frame @@ -456,6 +470,33 @@ func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput strin } } + if liveCSV { + if _, err := os.Stat("live.csv"); errors.Is(err, os.ErrNotExist) { + f, err := os.Create("live.csv") + if err != nil { + return err + } + + _, err = f.WriteString("frame, average_fps, frame_time, unique_frame_count, real_frame_time, frame_width, frame_height\n") + if err != nil { + return err + } + + f.Close() + } + + f, err := os.OpenFile("live.csv", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return err + } + + currentFrameData := frameAnalysisData[len(frameAnalysisData)-1] + + fmt.Fprintf(f, "%v, %.2f, %.2f, %v, %.2f, %v, %v\n", currentFrameData.frameNumber, currentFrameData.effectiveFPS, currentFrameData.currentFrameTime, currentFrameData.uniqueFrameCount, currentFrameData.realFrameTime, currentFrameData.frameWidth, currentFrameData.frameHeight) + + f.Close() + } + bar.Increment() } @@ -551,3 +592,39 @@ func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput strin return nil } + +func resdet(verbose bool, currentFrame *image.RGBA, frameWidth int, frameHeight int, minHeight int, minWidth int, prevFrameWidth int, prevFrameHeight int) (int, int) { + frameFile, err0 := os.Create("/tmp/frame.png") + + err1 := png.Encode(frameFile, currentFrame) + + out, err2 := exec.Command("resdet", "-v", "1", frameFile.Name()).Output() + + err3 := frameFile.Close() + + err4 := os.Remove(frameFile.Name()) + + formattedOutput := strings.Split(string(out), " ") + + frameWidthOut, err5 := strconv.Atoi(formattedOutput[0]) + + frameHeightOut, err6 := strconv.Atoi(strings.TrimSuffix(formattedOutput[1], "\n")) + + if err := cmp.Or(err0, err1, err2, err3, err4, err5, err6); err != nil { + log.Fatal(err) + } + + if frameHeightOut > minHeight { + frameHeight = frameHeightOut + } else { + frameHeight = prevFrameHeight + } + + if frameWidthOut > minWidth { + frameWidth = frameWidthOut + } else { + frameWidth = prevFrameWidth + } + + return frameWidth, frameHeight +} From 001c747103d56cd1a0264659ebfde0380e7d9869 Mon Sep 17 00:00:00 2001 From: aria Date: Thu, 26 Jun 2025 01:18:12 +1000 Subject: [PATCH 2/3] fix(main): index out of range [-1] --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index eb42745..e3c5e01 100644 --- a/main.go +++ b/main.go @@ -514,7 +514,7 @@ func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput strin // SECOND PASS: Calculate real frame times and write CSV if csvWriter != nil { for i, frameData := range frameAnalysisData { - realFrameTimeMs := float64(uniqueFrameDurations[frameData.uniqueFrameCount-1]) * frameTimeMs + realFrameTimeMs := float64(uniqueFrameDurations[frameData.uniqueFrameCount]) * frameTimeMs err := csvWriter.Write([]string{ strconv.Itoa(frameData.frameNumber), fmt.Sprintf("%.2f", frameData.effectiveFPS), From bdfd6cba2e69f6ace40586ba4d441bcd9c4924e0 Mon Sep 17 00:00:00 2001 From: aria Date: Thu, 26 Jun 2025 18:57:20 +1000 Subject: [PATCH 3/3] fix(msin): actually fix the issue... --- main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index e3c5e01..fa1d4b3 100644 --- a/main.go +++ b/main.go @@ -386,7 +386,7 @@ func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput strin copy(previousFrame.Pix, currentFrame.Pix) hasFirstFrame = true uniqueFramesInCurrentSecond = 1 - totalUniqueFrames = 0 + totalUniqueFrames = 1 currentUniqueFrameDuration = 1 // Store data for first frame @@ -514,7 +514,7 @@ func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput strin // SECOND PASS: Calculate real frame times and write CSV if csvWriter != nil { for i, frameData := range frameAnalysisData { - realFrameTimeMs := float64(uniqueFrameDurations[frameData.uniqueFrameCount]) * frameTimeMs + realFrameTimeMs := float64(uniqueFrameDurations[frameData.uniqueFrameCount-1]) * frameTimeMs err := csvWriter.Write([]string{ strconv.Itoa(frameData.frameNumber), fmt.Sprintf("%.2f", frameData.effectiveFPS),