package main

import (
    "bytes"
    "fmt"
    "gocv.io/x/gocv"
    "golang.org/x/crypto/ssh/terminal"
    "image"
    "os"
    "os/exec"
    "time"
)

const pixels = ` .,-'` + `:!1+*abcdefghijklmnopqrstuvwxyz<>()\/{}[]?234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ%&@#$`

func main() {
    // 打开文件
    c, err := gocv.VideoCaptureFile("../1.mp4")
    // 获取帧数
    fps := c.Get(gocv.VideoCaptureFPS)
    if err != nil {
        panic(err)
    }

    mat := gocv.NewMat()
    w, h := 0, 0
    // 放大缩小倍率
    b := 0
    // 每一帧之间时长
    s := int64((1 / fps) * 1e6)

    var t time.Time
    // 每一帧时长与每一帧计算时长之差
    var sub int64

    var buf bytes.Buffer
    // 转化大小
    point := image.Point{Y: 0, X: 0}
    for c.Read(&mat) {
        t = time.Now()
        // 获取终端大小
        wl, hl, _ := terminal.GetSize(int(os.Stdout.Fd()))
        // 如果终端大小发生变化则重新计算放大缩小倍率
        if wl != w || hl != h {
            w = wl
            h = hl
            x, y := mat.Rows(), mat.Cols()
            if hl > wl {
                if x < wl {
                    b = wl / x
                    x *= b
                    y *= b
                } else {
                    b = x / wl
                    x /= b
                    y /= b
                }
            } else {
                if y < hl {
                    b = hl / y
                    x *= b
                    y *= b
                } else {
                    b = y / hl
                    x /= b
                    y /= b
                }
            }
            point.X = x
            point.Y = y
        }
        // 转灰度
        gocv.CvtColor(mat, &mat, gocv.ColorBGRToGray)
        // resize图像大小
        gocv.Resize(mat, &mat, point, 0, 0, gocv.InterpolationLinear)
        // 图像归一化
        mat.DivideFloat(255 / float32(len(pixels)-1))
        cols, rows := mat.Cols(), mat.Rows()
        buf.Reset()
        for i := 0; i < rows; i++ {
            for j := 0; j < cols; j++ {
            
                // 图像转化字符
                buf.WriteByte(pixels[mat.GetSCharAt(i, j)])
            }
            buf.WriteByte('\n')
        }
        sub= time.Now().Sub(t).Microseconds()
        // 如果比较计算时间与每一帧图像时间
        if sub < s {
            // 休眠,使字符显示时间靠近源视频每一帧时间
            time.Sleep(time.Duration(s-sub) * time.Microsecond)
        }
        // 清屏
        cmd := exec.Command("bash", "-c", "clear")
        cmd.Stdout = os.Stdout
        cmd.Run()
        fmt.Print(buf.String())
    }
}
Last modification:August 12, 2021
如果觉得我的文章对你有用,请随意赞赏