Skip to content

Commit 1db29e0

Browse files
committed
feat: add colors, quality, and moderation to results
1 parent bc3487c commit 1db29e0

7 files changed

Lines changed: 756 additions & 104 deletions

File tree

commands/detect.go

Lines changed: 157 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"sort"
78
"strings"
89

910
"github.com/razzkumar/imgx/detection"
@@ -147,7 +148,7 @@ func detectAction(ctx context.Context, cmd *cli.Command) error {
147148
return outputDetectionJSON(result)
148149
}
149150

150-
return outputDetectionPretty(result)
151+
return outputDetectionPretty(result, float32(cmd.Float64("confidence")))
151152
}
152153

153154
// outputDetectionJSON outputs detection results as JSON
@@ -161,14 +162,26 @@ func outputDetectionJSON(result *detection.DetectionResult) error {
161162
}
162163

163164
// outputDetectionPretty outputs detection results in a human-readable format
164-
func outputDetectionPretty(result *detection.DetectionResult) error {
165+
func outputDetectionPretty(result *detection.DetectionResult, minConfidence float32) error {
165166
fmt.Printf("=== Object Detection Results (%s) ===\n\n", result.Provider)
166167

167168
// Labels
168169
if len(result.Labels) > 0 {
169170
fmt.Println("Labels:")
170-
for i, label := range result.Labels {
171-
fmt.Printf(" %d. %s (%.1f%% confidence)\n", i+1, label.Name, label.Confidence*100)
171+
count := 0
172+
for _, label := range result.Labels {
173+
if label.Confidence > 0 && label.Confidence < minConfidence {
174+
continue
175+
}
176+
count++
177+
if label.Confidence > 0 {
178+
fmt.Printf(" %d. %s (%.1f%% confidence)\n", count, label.Name, label.Confidence*100)
179+
} else {
180+
fmt.Printf(" %d. %s\n", count, label.Name)
181+
}
182+
}
183+
if count == 0 {
184+
fmt.Println(" (no labels above confidence threshold)")
172185
}
173186
fmt.Println()
174187
}
@@ -261,7 +274,13 @@ func outputDetectionPretty(result *detection.DetectionResult) error {
261274
// Properties
262275
if len(result.Properties) > 0 {
263276
fmt.Println("Properties:")
264-
for key, value := range result.Properties {
277+
keys := make([]string, 0, len(result.Properties))
278+
for key := range result.Properties {
279+
keys = append(keys, key)
280+
}
281+
sort.Strings(keys)
282+
for _, key := range keys {
283+
value := result.Properties[key]
265284
fmt.Printf(" %s: %s\n", key, value)
266285
}
267286
fmt.Println()
@@ -286,6 +305,139 @@ func outputDetectionPretty(result *detection.DetectionResult) error {
286305
fmt.Printf("Overall Confidence: %.1f%%\n", result.Confidence*100)
287306
}
288307

308+
// Dominant colors
309+
if len(result.Colors) > 0 {
310+
fmt.Println("\nDominant Colors:")
311+
colors := append([]detection.ColorInfo(nil), result.Colors...)
312+
sort.SliceStable(colors, func(i, j int) bool {
313+
return colors[i].Percentage > colors[j].Percentage
314+
})
315+
maxColors := len(colors)
316+
if maxColors > 5 {
317+
maxColors = 5
318+
}
319+
for i := 0; i < maxColors; i++ {
320+
c := colors[i]
321+
name := c.Name
322+
if name == "" {
323+
if c.Hex != "" {
324+
name = c.Hex
325+
} else if c.RGB != "" {
326+
name = c.RGB
327+
} else {
328+
name = fmt.Sprintf("Color %d", i+1)
329+
}
330+
}
331+
details := []string{}
332+
if c.Hex != "" && !strings.EqualFold(name, c.Hex) {
333+
details = append(details, c.Hex)
334+
}
335+
if c.RGB != "" && !strings.EqualFold(name, c.RGB) {
336+
details = append(details, c.RGB)
337+
}
338+
if c.Percentage > 0 {
339+
value := c.Percentage
340+
if value <= 1 {
341+
value = value * 100
342+
}
343+
details = append(details, fmt.Sprintf("%.1f%%", value))
344+
}
345+
if len(details) > 0 {
346+
fmt.Printf(" - %s (%s)\n", name, strings.Join(details, ", "))
347+
} else {
348+
fmt.Printf(" - %s\n", name)
349+
}
350+
}
351+
}
352+
353+
// Image quality
354+
if result.ImageQuality != nil {
355+
fmt.Println("\nImage Quality:")
356+
q := result.ImageQuality
357+
if q.Brightness != 0 {
358+
fmt.Printf(" Brightness: %.2f\n", q.Brightness)
359+
}
360+
if q.Contrast != 0 {
361+
fmt.Printf(" Contrast: %.2f\n", q.Contrast)
362+
}
363+
if q.Sharpness != 0 {
364+
fmt.Printf(" Sharpness: %.2f\n", q.Sharpness)
365+
}
366+
if q.ForegroundBrightness != 0 || q.ForegroundSharpness != 0 || q.ForegroundColor != "" {
367+
fmt.Println(" Foreground:")
368+
if q.ForegroundBrightness != 0 {
369+
fmt.Printf(" Brightness: %.2f\n", q.ForegroundBrightness)
370+
}
371+
if q.ForegroundSharpness != 0 {
372+
fmt.Printf(" Sharpness: %.2f\n", q.ForegroundSharpness)
373+
}
374+
if q.ForegroundColor != "" {
375+
fmt.Printf(" Color: %s\n", q.ForegroundColor)
376+
}
377+
}
378+
if q.BackgroundBrightness != 0 || q.BackgroundSharpness != 0 || q.BackgroundColor != "" {
379+
fmt.Println(" Background:")
380+
if q.BackgroundBrightness != 0 {
381+
fmt.Printf(" Brightness: %.2f\n", q.BackgroundBrightness)
382+
}
383+
if q.BackgroundSharpness != 0 {
384+
fmt.Printf(" Sharpness: %.2f\n", q.BackgroundSharpness)
385+
}
386+
if q.BackgroundColor != "" {
387+
fmt.Printf(" Color: %s\n", q.BackgroundColor)
388+
}
389+
}
390+
}
391+
392+
// Moderation labels
393+
if len(result.Moderation) > 0 {
394+
fmt.Println("\nModeration:")
395+
for _, label := range result.Moderation {
396+
parts := []string{}
397+
if label.Parent != "" {
398+
parts = append(parts, fmt.Sprintf("parent: %s", label.Parent))
399+
}
400+
if label.Severity != "" {
401+
parts = append(parts, fmt.Sprintf("severity: %s", label.Severity))
402+
}
403+
if label.Confidence > 0 {
404+
parts = append(parts, fmt.Sprintf("confidence: %.1f%%", label.Confidence*100))
405+
}
406+
if len(parts) > 0 {
407+
fmt.Printf(" - %s (%s)\n", label.Name, strings.Join(parts, ", "))
408+
} else {
409+
fmt.Printf(" - %s\n", label.Name)
410+
}
411+
}
412+
}
413+
414+
// Safe search summary
415+
if result.SafeSearch != nil {
416+
fmt.Println("\nSafe Search Summary:")
417+
if len(result.SafeSearch.Labels) > 0 {
418+
for _, label := range result.SafeSearch.Labels {
419+
parts := []string{}
420+
if label.Severity != "" {
421+
parts = append(parts, label.Severity)
422+
}
423+
if label.Confidence > 0 {
424+
parts = append(parts, fmt.Sprintf("%.1f%%", label.Confidence*100))
425+
}
426+
if label.Parent != "" {
427+
parts = append(parts, fmt.Sprintf("parent: %s", label.Parent))
428+
}
429+
if len(parts) > 0 {
430+
fmt.Printf(" - %s (%s)\n", label.Name, strings.Join(parts, ", "))
431+
} else {
432+
fmt.Printf(" - %s\n", label.Name)
433+
}
434+
}
435+
}
436+
if note := strings.TrimSpace(result.SafeSearch.Notes); note != "" {
437+
fmt.Printf(" Notes: %s\n", note)
438+
}
439+
}
440+
289441
// Raw response (if requested)
290442
if result.RawResponse != "" {
291443
fmt.Println("\n=== Raw API Response ===")

0 commit comments

Comments
 (0)