gsamservice/example/main.go
2025-08-29 09:53:07 +02:00

246 lines
5.0 KiB
Go

package main
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httputil"
"os"
"time"
)
var (
url = "http://localhost:13337"
fromText = "/gsam2/image/maskfromtext"
fromBboxes = "/gsam2/image/maskfrombboxes"
fromPoints = "/gsam2/image/maskfrompoints"
image = "truck.jpg"
)
type (
Point struct {
X int `json:"x"`
Y int `json:"y"`
Include bool `json:"include"`
}
BoundingBox struct {
UpperLeft [2]int `json:"upper_left"`
LowerRight [2]int `json:"lower_right"`
}
MaskFromTextRequest struct {
Image string `json:"image"`
Text string `json:"text"`
}
MaskFromBBoxRequest struct {
Image string `json:"image"`
Bboxes []BoundingBox `json:"bboxes"`
}
MaskFromPointsRequest struct {
Image string `json:"image"`
Points []Point `json:"points"`
}
MaskResult struct {
Mask string `json:"mask"`
Score float64 `json:"score"`
BBox BoundingBox `json:"bbox"`
// fields, only populated in responses for MaskFromTextRequests
ClassName string `json:"class_name"`
DinoBBox BoundingBox `json:"dino_bbox"`
CenterOfMass [2]float64 `json:"center_of_mass"`
}
MaskResponse struct {
Masks []MaskResult `json:"masks"`
Image string `json:"image"`
}
)
func main() {
// ensure the out directory exists
os.Mkdir("out", 0755)
// load the sample image and base64 encode it
dat, err := os.ReadFile(image)
if err != nil {
fmt.Println(err)
return
}
// post to the different endpoints
c := &http.Client{Timeout: time.Minute}
encImage := base64.StdEncoding.EncodeToString(dat)
// from text
err = doFromText(c, "fromtext", encImage, "truck. tire.")
if err != nil {
fmt.Printf("error %s", err)
return
}
// from bboxes
err = doFromBboxes(c, "frombboxes", encImage, []BoundingBox{
{
UpperLeft: [2]int{75, 275},
LowerRight: [2]int{1725, 850},
},
{
UpperLeft: [2]int{425, 600},
LowerRight: [2]int{700, 875},
},
{
UpperLeft: [2]int{1375, 550},
LowerRight: [2]int{1650, 800},
},
{
UpperLeft: [2]int{1240, 675},
LowerRight: [2]int{1400, 750},
},
})
if err != nil {
fmt.Printf("error %s", err)
return
}
// from points
err = doFromPoints(c, "frompoints", encImage, []Point{
{X: 500, Y: 375, Include: true},
{X: 1125, Y: 625, Include: true},
{X: 575, Y: 750, Include: false},
})
if err != nil {
fmt.Printf("error %s", err)
return
}
}
func do(c *http.Client, req *http.Request, outname string) error {
dump, err := httputil.DumpRequest(req, false)
if err != nil {
return err
}
fmt.Println("request: ", string(dump))
resp, err := c.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode >= 300 {
dump, err := httputil.DumpResponse(resp, true)
if err != nil {
return err
}
fmt.Println("response: ", string(dump))
defer resp.Body.Close()
} else {
dump, err := httputil.DumpResponse(resp, false)
if err != nil {
return err
}
fmt.Println("response: ", string(dump))
}
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
maskResp := MaskResponse{}
err = json.Unmarshal(bodyBytes, &maskResp)
if err != nil {
return err
}
// write the masks to a file
for _, mask := range maskResp.Masks {
dec, err := base64.StdEncoding.DecodeString(mask.Mask)
if err != nil {
return err
}
class := ""
if mask.ClassName != "" {
class = "-" + mask.ClassName
}
os.WriteFile(fmt.Sprintf("out/%s%s-%.4f.jpg", outname, class, mask.Score), dec, 0644)
}
dec, err := base64.StdEncoding.DecodeString(maskResp.Image)
if err != nil {
return err
}
os.WriteFile(fmt.Sprintf("out/%s.jpg", outname), dec, 0644)
return nil
}
func doFromText(c *http.Client, outname string, encImage string, text string) error {
req, err := http.NewRequest("POST", url+fromText, nil)
if err != nil {
return err
}
req.Header.Add("Accept", `application/json`)
body := MaskFromTextRequest{
Image: encImage,
Text: text,
}
jsonBody, err := json.Marshal(body)
if err != nil {
return err
}
req.Body = io.NopCloser(bytes.NewBuffer(jsonBody))
return do(c, req, outname)
}
func doFromBboxes(c *http.Client, outname string, encImage string, bboxes []BoundingBox) error {
req, err := http.NewRequest("POST", url+fromBboxes, nil)
if err != nil {
return err
}
req.Header.Add("Accept", `application/json`)
body := MaskFromBBoxRequest{
Image: encImage,
Bboxes: bboxes,
}
jsonBody, err := json.Marshal(body)
if err != nil {
return err
}
req.Body = io.NopCloser(bytes.NewBuffer(jsonBody))
return do(c, req, outname)
}
func doFromPoints(c *http.Client, outname string, encImage string, points []Point) error {
req, err := http.NewRequest("POST", url+fromPoints, nil)
if err != nil {
return err
}
req.Header.Add("Accept", `application/json`)
body := MaskFromPointsRequest{
Image: encImage,
Points: points,
}
jsonBody, err := json.Marshal(body)
if err != nil {
return err
}
req.Body = io.NopCloser(bytes.NewBuffer(jsonBody))
return do(c, req, outname)
}