Golang中如何通过HTTP传输gocv Mat

Golang中如何通过HTTP传输gocv Mat 大家好。很抱歉我的第一个帖子就是来寻求帮助的,但希望有一天我能变得足够优秀来帮助他人。

我正在开发一个客户端/服务器设置来练习Go语言,其中我使用gocv从摄像头捕获图像以及一些额外的元数据,并将其发送到远程服务器进行处理。两个进程都是用Go编写的。将mat传输到服务器进程的最佳方式是什么?

我已经尝试过使用gob,如下所示:

func handleConnection(conn net.Conn) {


    dec := gob.NewDecoder(conn)
    p := gocv.NewMat()
    dec.Decode(&p)

    gocv.IMWrite("test.png", p)

    conn.Close()
}
encoder := gob.NewEncoder(conn)
encoder.Encode(img) //img是mat

这个方法没有奏效。我还尝试过逐像素读取mat并将其编码为字符串发送,但这感觉不太对。如果只使用"net"包,我应该如何简单地发送/接收这个数据?


更多关于Golang中如何通过HTTP传输gocv Mat的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

我找到了正在寻找的解决方案。要通过gocv将图像作为mat传递,请使用gocv.ToBytes()函数,然后将其编码为字节切片。

更多关于Golang中如何通过HTTP传输gocv Mat的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中通过HTTP传输gocv的Mat对象,最有效的方式是将Mat编码为图像格式(如JPEG或PNG)进行传输。gocv提供了gocv.IMEncode()函数来将Mat编码为字节切片,然后可以通过HTTP请求体发送。

以下是完整的客户端和服务器示例:

服务器端代码:

package main

import (
    "encoding/json"
    "fmt"
    "image"
    "net/http"
    
    "gocv.io/x/gocv"
)

type ImageRequest struct {
    Data []byte `json:"data"`
    Width int   `json:"width"`
    Height int  `json:"height"`
}

func processImageHandler(w http.ResponseWriter, r *http.Request) {
    var req ImageRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        http.Error(w, "Invalid request body", http.StatusBadRequest)
        return
    }

    // 从字节数据重建Mat
    img, err := gocv.NewMatFromBytes(req.Height, req.Width, gocv.MatTypeCV8UC3, req.Data)
    if err != nil {
        http.Error(w, "Failed to decode image", http.StatusInternalServerError)
        return
    }
    defer img.Close()

    // 处理图像(示例:转换为灰度图)
    gray := gocv.NewMat()
    defer gray.Close()
    gocv.CvtColor(img, &gray, gocv.ColorBGRToGray)

    // 编码处理后的图像为JPEG
    resultBytes, err := gocv.IMEncode(gocv.JPEGFileExt, gray)
    if err != nil {
        http.Error(w, "Failed to encode result", http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "image/jpeg")
    w.Write(resultBytes)
}

func main() {
    http.HandleFunc("/process", processImageHandler)
    fmt.Println("Server starting on :8080")
    http.ListenAndServe(":8080", nil)
}

客户端代码:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    
    "gocv.io/x/gocv"
)

func main() {
    // 打开摄像头
    webcam, err := gocv.OpenVideoCapture(0)
    if err != nil {
        fmt.Printf("Error opening camera: %v\n", err)
        return
    }
    defer webcam.Close()

    img := gocv.NewMat()
    defer img.Close()

    // 捕获一帧图像
    if ok := webcam.Read(&img); !ok {
        fmt.Printf("Cannot read frame from camera\n")
        return
    }

    // 将Mat编码为JPEG字节
    imgBytes, err := gocv.IMEncode(gocv.JPEGFileExt, img)
    if err != nil {
        fmt.Printf("Error encoding image: %v\n", err)
        return
    }

    // 准备请求数据
    reqData := ImageRequest{
        Data:   imgBytes,
        Width:  img.Cols(),
        Height: img.Rows(),
    }

    jsonData, err := json.Marshal(reqData)
    if err != nil {
        fmt.Printf("Error marshaling JSON: %v\n", err)
        return
    }

    // 发送HTTP POST请求
    resp, err := http.Post("http://localhost:8080/process", "application/json", bytes.NewBuffer(jsonData))
    if err != nil {
        fmt.Printf("Error sending request: %v\n", err)
        return
    }
    defer resp.Body.Close()

    // 读取服务器返回的处理结果
    resultBytes, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Error reading response: %v\n", err)
        return
    }

    // 将结果保存为文件
    if err := gocv.IMWrite("processed.jpg", gocv.IMDecode(resultBytes, gocv.IMReadColor)); err != nil {
        fmt.Printf("Error saving result: %v\n", err)
        return
    }

    fmt.Println("Image processed and saved as processed.jpg")
}

更简单的Base64编码方案:

如果希望更简单的实现,也可以使用Base64编码:

// 客户端编码
imgBytes, _ := gocv.IMEncode(gocv.JPEGFileExt, img)
base64Str := base64.StdEncoding.EncodeToString(imgBytes)

// 服务器端解码
decodedBytes, _ := base64.StdEncoding.DecodeString(base64Str)
img, _ := gocv.IMDecode(decodedBytes, gocv.IMReadColor)

这种方法比直接使用gob更可靠,因为gocv的Mat对象包含C++层面的数据指针,无法直接通过gob序列化。通过图像编码的方式既高效又兼容标准HTTP协议。

回到顶部