Skip links

Adding Object Detection to a Go application using CodeProject.AI Server

CodeProject.AI Server provides a RESTful API that makes it easy to add AI capabilities to any app that can make a HTTP call. In this article we’ll demonstrate how to create a basic Go application that includes object detection capabilities via calls to CodeProject.AI.

We’ll be using Visual Studio Code on whatever platform suits you best. We’ll also assume you’ve downloaded and installed CodeProject.AI Server.

Getting Started

In Visual Studio Code create a new file object-detect.go. Our app, and our demonstration of using CodeProject.AI Server will be fully contained in this one file.

The steps we’ll take will be simple:
  1. Select an image file to process and ensure we can load the image.
  2. Load the image and store it in a multipart form data object
  3. Send the form data containing the image to CodeProject.AI Server for processing
  4. Read and parse the response
  5. Display the results

It’s that simple.

The Code

package main
import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "log"
    "mime/multipart"
    "net/http"
    "os"
)

const (
    apiUrl    = "http://localhost:32168/v1/vision/detection"
    imagePath = "..\\..\\TestData\\Objects\\study-group.jpg"
)

type DetectionResponse struct {
    Predictions []struct {
        Label string  `json:"label"`
        Confidence float64 `json:"confidence"`
        XMin  int     `json:"x_min"`
        YMin  int     `json:"y_min"`
        XMax  int     `json:"x_max"`
        YMax  int     `json:"y_max"`
    } `json:"predictions"`
}

func main() {
    // Open the image file
    file, err := os.Open(imagePath)
    if err != nil {
        log.Fatalf("failed to open image: %v", err)
    }
    defer file.Close()
    
    // Create a buffer to hold the multipart form data
    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)
    // Add the image file to the form data
    part, err := writer.CreateFormFile("image", imagePath)
    if err != nil {
        log.Fatalf("failed to create form file: %v", err)
    }
    _, err = io.ReadAll(file)
    if err != nil {
        log.Fatalf("failed to read image file: %v", err)
    }
    file.Seek(0, 0)
    _, err = io.Copy(part, file)
    if err != nil {
        log.Fatalf("failed to copy file content: %v", err)
    }
    
    // Close the writer to set the terminating boundary
    err = writer.Close()
    if err != nil {
        log.Fatalf("failed to close writer: %v", err)
    }
    
    // Make the HTTP request to the CodeProject.AI Server
    req, err := http.NewRequest("POST", apiUrl, body)
    if err != nil {
        log.Fatalf("failed to create request: %v", err)
    }
    req.Header.Set("Content-Type", writer.FormDataContentType())
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        log.Fatalf("failed to perform request: %v", err)
    }
    defer resp.Body.Close()
    
    // Read the response
    responseBody, err := io.ReadAll(resp.Body)
    if err != nil {
        log.Fatalf("failed to read response body: %v", err)
    }
    
    // Parse the JSON response
    var detectionResponse DetectionResponse
    err = json.Unmarshal(responseBody, &detectionResponse)
    if err != nil {
        log.Fatalf("failed to unmarshal response: %v", err)
    }
    
    // Print the detected objects
    for _, prediction := range detectionResponse.Predictions {
        fmt.Printf("Object: %s, Confidence: %.2f, Bounding Box: [%d, %d, %d, %d]\n",
            prediction.Label, prediction.Confidence, prediction.XMin, prediction.YMin, prediction.XMax, prediction.YMax)
    }
}

And we’re done!

Obviously this is as simple an example as one could ask for, but the point is to illustrate how little code is needed to actually utilize CodeProject.AI Server. The majority of the code we’re provided is actually error checking.

Next Steps

CodeProject.AI Server has dozens of modules, each with their own API. It’s straightforward to adapt this code to use other modules by changing the URL that is called, and creating a new response structure that would replace DetectionResponse with a structure that suits the API you’ll be using.

Good luck and have fun!

Leave a comment

🍪 This website uses cookies to improve your web experience.