C++ OpenCV - 如何将调整大小的视频帧显示为 ASCII?

问题描述 投票:0回答:1

我制作了一个程序,可以将视频转换为调整大小的 ASCII 动画,但是

Mat frame
只捕获整个视频左上角的一部分。相应地,
Mat
的深度和通道为0和1。即使
at<uchar>
返回为空,如果没有
Mat
,该程序也无法运行?

Expected output size Actual output size

#include <iostream>
#include <vector>
#include <chrono>
#include <thread>
#include <Windows.h>
#include <mmsystem.h>
#include <opencv2/opencv.hpp>

#pragma comment(lib, "winmm.lib")

void checkForOpenCV()
{
    if(cv::getCPUTickCount == 0)
    {
        std::cout << "OpenCV is not detected." << '\n';
    }
    else
    {
        std::cout << "OpenCV is detected." << '\n';
    }
}

cv::VideoCapture openVid(std::string &filePath)
{
    cv::VideoCapture cap{filePath};
    if(!cap.isOpened())
    {
        std::cout << "The file cannot be accessed." << '\n';
        exit(-1);
    }
    else
    {
        std::cout << "File is accessed." << '\n';
    }

    return cap;
}

char brightness2Ascii(int brightness, std::string asciiCharset)
{
    int index(brightness * asciiCharset.size() / 256);
    return asciiCharset[index];
}

int main()
{
    checkForOpenCV();

    std::string filePath{R"(C:\Users\Harold.DESKTOP-UJ6F4M4\Videos\video.mp4)"};
    cv::VideoCapture cap{openVid(filePath)};

    double fps{cap.get(cv::CAP_PROP_FPS)};
    std::cout << fps << '\n';

    int width(cap.get(cv::CAP_PROP_FRAME_WIDTH));
    int height(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
    int aspectRatio{12};
    std::cout << width << " x " << height << '\n';

    std::vector<cv::Mat> totalFrames{};
    cv::Mat frame{};

    int depth{frame.depth()};
    int channels{frame.channels()};

    while(cap.read(frame))
    {
        cv::resize(frame, frame, cv::Size(width / aspectRatio, height / aspectRatio), 0, 0, cv::INTER_LINEAR);
        totalFrames.push_back(frame.clone());
    }
    cap.release();

    
    for(const auto &frame:totalFrames)
    {
        std::string asciiArt{};
        for(int i{0}; i < frame.rows; i++)
        {
            for(int j{0}; j < frame.cols; j++)
            {
                const std::string asciiCharset{" .'-=*%#@"}; // {" .'-=*%#@"} {"@ "}
                int brightness{frame.at<uchar>(i, j)};
                char pixelChar{brightness2Ascii(brightness, asciiCharset)};
                asciiArt += pixelChar;
            }
            asciiArt += '\n';
        }
std::cout << depth << '\n' << channels << '\n';
        std::cout << asciiArt;
        cv::waitKey(fps / 2);

    }

    return 0;
}

我尝试创建一个单独的

Mat resizedFrame
,以及为
asciiChar
声明单独的宽度和高度,但无济于事。最初,我认为问题是由于在预加载所有框架后调整框架大小而出现的,但是在预加载循环中重新定位
resize()
后,我不再那么确定了。

c++ opencv ascii-art
1个回答
0
投票

事实证明,如果我将

frame
与它一起使用,我需要将
GRAY Mat
转换为
at<uchar>
。我没有这样做,因为视频已经是黑白的,但 OpenCV 无论如何都将其转换为 BGR。对于非灰色垫子,请使用
at<Vec3b>()
代替。

 for(const auto &frame : totalFrames)
 {
 cv::cvtColor(frame, grayFrame, cv::COLOR_BGR2GRAY);
 cv::resize(grayFrame, grayFrame, cv::Size(2 * width / aspectRatio, height / aspectRatio), 0, 0, cv::INTER_LINEAR);

 std::string asciiArt{};
 for(int i{0}; i < grayFrame.rows; i++)
 {
     for(int j{0}; j < grayFrame.cols; j++)
     {
         const std::string asciiCharset{".'-=*%#@"}; // {" .'-=*%#@"} {"@ "}
         int brightness{grayFrame.at<uchar>(i, j)};
         char pixelChar{brightness2Ascii(brightness, asciiCharset)};
         asciiArt += pixelChar;
     }
     asciiArt += '\n';
 }
 std::cout << asciiArt;
 Sleep(1000 / fps);

}

© www.soinside.com 2019 - 2024. All rights reserved.