Compare commits

...

5 commits
0.5.0 ... main

Author SHA1 Message Date
bdfd6cba2e
fix(msin): actually fix the issue... 2025-06-26 18:57:20 +10:00
001c747103
fix(main): index out of range [-1] 2025-06-26 01:18:12 +10:00
55236c0a24
feat(analyze-frame-persistence): add flags for defining min res
This should allow for improved results, at the very least filtering out junk data
2025-06-26 00:12:17 +10:00
fa9aa2e174
bump: version 0.5.0 → 0.5.1
All checks were successful
Build and Release / build (push) Successful in 3m44s
2025-06-17 00:40:42 +10:00
50131d949b
fix(csv output): add missing frame width and height headers 2025-06-17 00:40:24 +10:00
3 changed files with 110 additions and 27 deletions

View file

@ -2,6 +2,6 @@
name = "cz_conventional_commits" name = "cz_conventional_commits"
tag_format = "$version" tag_format = "$version"
version_scheme = "semver2" version_scheme = "semver2"
version = "0.5.0" version = "0.5.1"
update_changelog_on_bump = true update_changelog_on_bump = true
major_version_zero = true major_version_zero = true

View file

@ -1,3 +1,9 @@
## 0.5.1 (2025-06-17)
### Fix
- **csv output**: add missing frame width and height headers
## 0.5.0 (2025-06-16) ## 0.5.0 (2025-06-16)
### Feat ### Feat

129
main.go
View file

@ -5,6 +5,7 @@ import (
"cmp" "cmp"
"context" "context"
"encoding/csv" "encoding/csv"
"errors"
"fmt" "fmt"
"image" "image"
"image/draw" "image/draw"
@ -100,9 +101,9 @@ func main() {
}, },
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.Float64Flag{ &cli.Uint64Flag{
Name: "tolerance", Name: "tolerance",
Usage: "Pixel difference tolerance (0-255)", Usage: "Pixel difference tolerance (0-255?)",
Value: 0, Value: 0,
}, },
&cli.StringFlag{ &cli.StringFlag{
@ -121,11 +122,35 @@ func main() {
Usage: "print out total unique frames for every second of measurements", Usage: "print out total unique frames for every second of measurements",
Value: false, 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 { 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") 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 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) video, err := vidio.NewVideo(videoPath)
if err != nil { if err != nil {
return err return err
@ -291,7 +316,7 @@ func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput strin
csvWriter = csv.NewWriter(csvFile) csvWriter = csv.NewWriter(csvFile)
defer csvWriter.Flush() defer csvWriter.Flush()
err = csvWriter.Write([]string{"frame", "average_fps", "frame_time", "unique_frame_count", "real_frame_time"}) err = csvWriter.Write([]string{"frame", "average_fps", "frame_time", "unique_frame_count", "real_frame_time", "frame_width", "frame_height"})
if err != nil { if err != nil {
return fmt.Errorf("failed to write CSV header: %v", err) return fmt.Errorf("failed to write CSV header: %v", err)
} }
@ -341,28 +366,17 @@ func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput strin
// mesure resoltion // mesure resoltion
if toggleResdet { if toggleResdet {
frameFile, err0 := os.Create("/tmp/frame.png") var lastFrameWidth int
var lastFrameHeight int
err1 := png.Encode(frameFile, currentFrame) if len(frameWidthMeasurements) != 0 {
lastFrameWidth = frameWidthMeasurements[len(frameWidthMeasurements)-1]
out, err2 := exec.Command("resdet", "-v", "1", frameFile.Name()).Output() lastFrameHeight = frameHeightMeasurements[len(frameHeightMeasurements)-1]
} else {
err3 := frameFile.Close() lastFrameWidth = currentFrame.Bounds().Max.X
lastFrameHeight = currentFrame.Bounds().Max.X
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)
} }
frameWidth, frameHeight = resdet(verbose, currentFrame, frameWidth, frameHeight, minResdetHeight, minResdetHeight, lastFrameWidth, lastFrameHeight)
frameWidth = frameWidthOut
frameHeight = frameHeightOut
} }
frameWidthMeasurements = append(frameWidthMeasurements, frameWidth) frameWidthMeasurements = append(frameWidthMeasurements, frameWidth)
@ -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() bar.Increment()
} }
@ -551,3 +592,39 @@ func analyzeFramePersistence(videoPath string, tolerance uint64, csvOutput strin
return nil 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
}