我想实现两件事,现在我不能完成其中一个。我做一个WebSocket服务器使用main。go,然后我使用vscode的live服务器打开index.html。在html页面上,当我点击"按钮,我调用服务器运行GoCV,用我的笔记本摄像头自拍。到目前为止,一切都已完成。最后,我需要将自拍数据传递给html页面并呈现,我尝试将img转换为[]字节,如"img. tobytes ()"然后在golang代码中传递给websocket,我将blob转换为objectURL,然后传递给html中的标记,然后页面只显示一个没有图像的图像图标。我不知道如何解决这个问题。可能数据格式是非法的,如何正确处理?
main.go
package main
import (
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/websocket"
"gocv.io/x/gocv"
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
func homePage(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Home Page")
}
func reader(conn *websocket.Conn) {
Img := gocv.NewMat()
for {
// read in a message
messageType, p, err := conn.ReadMessage()
fmt.Println(string(p))
if err != nil {
log.Println(err)
return
}
if err := conn.WriteMessage(messageType, p); err != nil {
log.Println(err)
return
}
if string(p) == "someone is going to take a selfie" {
webcam, err := gocv.OpenVideoCapture(0)
if err != nil {
fmt.Printf("Error opening video capture device: %vn", 0)
return
}
fmt.Println("1")
fmt.Println("2")
img := gocv.NewMat()
fmt.Println("3")
if ok := webcam.Read(&img); !ok {
fmt.Printf("Device closed: %vn", 0)
return
}
fmt.Println("4")
Img = img
fmt.Println("5")
webcam.Close()
fmt.Println("什麼都關了")
//傳字
conn.SetWriteDeadline(time.Now().Add(1000000000))
w, err := conn.NextWriter(websocket.BinaryMessage)
if err != nil {
return
}
w.Write(img.ToBytes())
if err := w.Close(); err != nil {
return
}
}
if string(p) == "someone is going to save the selfie" {
fmt.Println("要存照片囉!!")
gocv.IMWrite("selfie.jpg", Img)
}
}
}
func wsEndpoint(w http.ResponseWriter, r *http.Request) {
upgrader.CheckOrigin = func(r *http.Request) bool { return true }
// upgrade this connection to a WebSocket
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
}
log.Println("客戶端連接")
reader(ws)
}
func setupRoutes() {
http.HandleFunc("/", homePage)
http.HandleFunc("/ws", wsEndpoint)
}
func main() {
fmt.Println("伺服器開啟")
setupRoutes()
log.Fatal(http.ListenAndServe(":8080", nil))
}
index . html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>GoCV作業延伸</title>
</head>
<body>
<h2>GoCV作業延伸</h2>
<div>
<button id="capture" onclick="captureHandler();">拍照</button>
<button id="save" onclick="saveHandler();">儲存</button>
</div>
<div><img id="img" /></div>
<div class="column">
<label for="upload" class="button file-label">Select Image</label>
<input id="upload" class="hidden" type="file" accept="image/*" />
</div>
<div class="column">
<img id="upload-image" />
</div>
<script>
let socket = new WebSocket("ws://127.0.0.1:8080/ws");
console.log("Attempting Connection...");
socket.onopen = (capture) => {
console.log("Successfully Connected");
socket.send("Hi From the Client!");
};
socket.onclose = (event) => {
console.log("Socket Closed Connection: ", event);
socket.send("Client Closed!");
};
//?????????????????????????????????????????????????????????????????
const uploadButton = document.getElementById("upload");
const imgDOM = document.getElementById("upload-image");
function createImageFromFile(img, file) {
return new Promise((resolve, reject) => {
console.log(URL.createObjectURL(file));
img.src = URL.createObjectURL(file);
img.onload = () => {
URL.revokeObjectURL(img.src);
resolve(img);
};
img.onerror = () => reject("Failure to load image.");
});
}
function getFileBase64Encode(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
}
function handleFiles() {
console.log(this);
const fileList = this.files;
console.log(fileList);
const [file] = fileList;
console.log(file);
const p1 = createImageFromFile(imgDOM, file);
const p2 = getFileBase64Encode(file);
console.log(p1);
Promise.all([p1, p2]).then((result) => {
const [img, b64] = result;
});
}
uploadButton.addEventListener("change", handleFiles, false);
//?????????????????????????????????????????????????????????????????
let capture = document.getElementById("capture");
let imgdom = document.getElementById("img");
socket.onmessage = (e) => {
console.log(e);
console.log(e.data);
let blob = e.data;
img.src = URL.createObjectURL(blob);
function createImageFromBlob(img, blob) {
return new Promise((resolve, reject) => {
console.log(blob);
console.log(URL.createObjectURL(blob));
img.src = URL.createObjectURL(blob);
img.onload = () => {
URL.revokeObjectURL(img.src);
resolve(img);
};
img.onerror = () => reject("Failure to load image.");
});
}
function handleBlobs() {
console.log(blob);
createImageFromBlob(imgdom, blob);
}
capture.addEventListener("click", handleBlobs, false);
};
socket.onerror = (error) => {
console.log("Socket Error: ", error);
};
function captureHandler() {
socket.send("someone is going to take a selfie");
}
function saveHandler() {
socket.send("someone is going to save the selfie");
}
</script>
</body>
</html>
我解决了这个问题,只是编码图像到内存缓冲区,然后在传递它之前将其转换为字节数组。这些操作将图像大小从2764800(=1920*1440)字节压缩到大约50,000字节。
代替
w.Write(img.ToBytes())
buf, _ := gocv.IMEncode(".jpg", img)
w.Write(buf.GetBytes())