不使用GoCV实现Golang摄像头调用

不使用GoCV实现Golang摄像头调用 是否有办法编写不使用GoCV的Go代码来调用摄像头、拍摄照片和视频?我发现了go-webcam,但它仅支持Linux。我需要在Windows 10设备上运行。谢谢。

1 回复

更多关于不使用GoCV实现Golang摄像头调用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,可以通过调用系统API实现。在Windows上可以使用DirectShow接口,这里提供一个使用github.com/blackjack/webcam包的示例,它支持Windows和Linux:

package main

import (
    "fmt"
    "image/jpeg"
    "os"
    "time"
    "github.com/blackjack/webcam"
)

func main() {
    // 获取摄像头列表
    cams, err := webcam.ListWebcams()
    if err != nil {
        panic(err)
    }
    
    // 选择第一个摄像头
    cam, err := webcam.Open(cams[0])
    if err != nil {
        panic(err)
    }
    defer cam.Close()
    
    // 设置格式和分辨率
    format := webcam.PixelFormat(webcam.PixelFmtMJPEG)
    width, height := uint32(640), uint32(480)
    
    err = cam.StartStreaming(format, width, height)
    if err != nil {
        panic(err)
    }
    
    // 拍摄照片
    timeout := uint32(5) // 5秒超时
    frame, err := cam.ReadFrame(timeout)
    if err != nil {
        panic(err)
    }
    
    // 保存为JPEG
    img, err := cam.Decode(frame, format, width, height)
    if err != nil {
        panic(err)
    }
    
    file, _ := os.Create("photo.jpg")
    defer file.Close()
    jpeg.Encode(file, img, nil)
    
    fmt.Println("照片已保存为 photo.jpg")
    
    // 录制视频(示例:录制5秒)
    videoFile, _ := os.Create("video.mjpeg")
    defer videoFile.Close()
    
    start := time.Now()
    for time.Since(start) < 5*time.Second {
        frame, err := cam.ReadFrame(timeout)
        if err != nil {
            break
        }
        videoFile.Write(frame)
    }
    
    fmt.Println("视频已保存为 video.mjpeg")
}

对于更完整的Windows支持,可以使用github.com/kbinani/screenshot配合github.com/vova616/screenshot

package main

import (
    "image/png"
    "os"
    "github.com/kbinani/screenshot"
)

func main() {
    // 获取所有显示器的截图(可作为摄像头替代方案)
    n := screenshot.NumActiveDisplays()
    for i := 0; i < n; i++ {
        bounds := screenshot.GetDisplayBounds(i)
        img, err := screenshot.CaptureRect(bounds)
        if err != nil {
            panic(err)
        }
        
        fileName := fmt.Sprintf("display_%d.png", i)
        file, _ := os.Create(fileName)
        defer file.Close()
        png.Encode(file, img)
    }
}

如果需要直接调用Windows API,可以使用syscall包调用ole32.dllstrmiids.dll

package main

import (
    "syscall"
    "unsafe"
)

var (
    ole32 = syscall.NewLazyDLL("ole32.dll")
    coInitialize = ole32.NewProc("CoInitialize")
    coUninitialize = ole32.NewProc("CoUninitialize")
)

func main() {
    // 初始化COM库
    coInitialize.Call(0)
    defer coUninitialize.Call()
    
    // 这里可以继续调用DirectShow API
    // 需要导入相应的Windows头文件定义
}

注意:直接调用Windows API需要处理大量CGO交互和COM对象管理。建议使用现有的封装库,如github.com/AllenDang/w32github.com/lxn/win来简化调用。

回到顶部