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 ("\n Dominant 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 ("\n Image 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 ("\n Moderation:" )
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 ("\n Safe 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