【问题标题】:opencv 4.0 can't save videoopencv 4.0 无法保存视频
【发布时间】:2019-05-27 19:51:44
【问题描述】:

我正在尝试录制我的桌面屏幕并使用 opencv videoWriter 将其保存到视频中,但最终总是有一个甚至无法播放的 6kb 视频。

这是我的代码,我首先为屏幕创建 mat 对象,然后将它们写入文件。

#include "pch.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp> 
#include <iostream>
#include <stdio.h>
#include <opencv2/objdetect/objdetect.hpp>
#include <Windows.h>

using namespace std;
using namespace cv;


int height;
int width;

Mat hwnd2mat()
{
  // returning Mat object for screen and working fine as I'm showing it into a window
}


void CaptureScreen()
{
    int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
    HWND hDesktopWnd = GetDesktopWindow();
    int key = 0;
    string filename = "D:/outcpp.avi";
    cv::Size targetSize = cv::Size(320, 240);
    VideoWriter video(filename, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 10, targetSize);
    while (1)
    {
        Mat frame = hwnd2mat();

        cv::Mat image = frame;
        cv::Mat dst;
        cv::resize(image, dst, targetSize);

        if (dst.empty())
            break;
        video.write(dst);
        imshow("Frame", dst);
        char c = (char)waitKey(1);
        if (c == 27)
            break;
    }
    video.release();
    destroyAllWindows();
    //readVideo(filename);
}




int main(int argc, char **argv)
{
    CaptureScreen();
    return 0;
}

【问题讨论】:

  • CaptureScreen 看起来不错。 hwnd2mat 可能存在问题。显示它的代码。
  • @barmark 我刚刚在我的代码中直接使用了这个code

标签: c++ windows opencv


【解决方案1】:

你正在调用一个函数,根据它的签名,它返回一些东西,但实际上没有。根据 C++ 标准,这会导致未定义的行为,因此您的程序有问题。

请同时启用警告,因为编译器通常会准确地告诉您。

【讨论】:

  • 你在说Mat hwnd2mat()吗?
  • 这是一个相当神秘的答案!
  • 我同意,@MarkSetchell。也许答案也可以是评论。我也没有声称答案解决了上述代码的所有问题或行为发生了变化,但至少它修复了代码中的一个错误。
  • hwnd2mat(),当然。 main() 是唯一的例外,尽管有 int 返回类型声明,但它允许不从中返回任何内容。
  • @UlrichEckhardt 我直接从here使用了这个函数
【解决方案2】:

用 *.mp4 尝试不同的fourcc 代码,这样会更好,并且在不显示图像的情况下运行。确保视频已成功打开并发布。

void hwnd2mat(cv::Mat &mat)
{
    int w = mat.cols;
    int h = mat.rows;

    auto hdc = GetDC(0);
    auto memdc = CreateCompatibleDC(hdc);
    auto hbitmap = CreateCompatibleBitmap(hdc, w, h);
    auto holdbmp = SelectObject(memdc, hbitmap);
    BitBlt(memdc, 0, 0, w, h, hdc, 0, 0, SRCCOPY);

    BITMAPINFOHEADER bi = { sizeof(bi), w, -h, 1, 24 };
    GetDIBits(hdc, hbitmap, 0, h, mat.data, (BITMAPINFO*)&bi, 0);

    SelectObject(memdc, holdbmp);
    DeleteDC(memdc);
    DeleteObject(hbitmap);
    ReleaseDC(0, hdc);
}

int main()
{
    int w = GetSystemMetrics(SM_CXSCREEN);
    int h = GetSystemMetrics(SM_CYSCREEN);
    cv::Size size = cv::Size(w, h);
    Mat frame(size, CV_8UC3);

    double fps = 10.0;

    //string filename = "d:\\outcpp.avi";
    //auto fourcc = cv::VideoWriter::fourcc('M', 'J', 'P', 'G');

    string filename = "d:\\outcpp.mp4";
    auto fourcc = cv::VideoWriter::fourcc('m', 'p', '4', 'v');

    VideoWriter video(filename, fourcc, fps, frame.size());
    if(!video.isOpened())
    {
        cout << "codec failed\n";
        return 0;
    }

    while(GetAsyncKeyState(VK_ESCAPE) == 0)
    {
        cout << ".";
        hwnd2mat(frame);
        video.write(frame);
        Sleep(int(1000.0/fps));
    }

    video.release();
    cout << "\nreleased\n";

    return 0;
}

【讨论】:

  • @barnak 我尝试了你的代码,但它一直在 if(!video.isOpened()) { cout &lt;&lt; "codec failed\n"; return 0; } 上退出,所以我将其注释掉,之后它没有创建任何 mp4 视频并且在 imshow(frame) 上显示灰色窗口。
  • 您的计算机上没有安装该编解码器,请尝试使用其他编解码器(确保它与文件扩展名匹配)。如果video.isOpend() 失败,则不要继续。
  • @barnak 我再次尝试并只是更改了我的文件路径,之后它在 mp4 中创建视频,但在视频中它的显示屏幕以弯曲的方式显示。知道为什么吗?
  • @barnak 感谢您的帮助,它现在工作正常,我刚刚在您的代码中更改了int w = GetSystemMetrics(SM_CXSCREEN)+10;,并且知道它的工作原理以及这里的错误是什么。
猜你喜欢
  • 1970-01-01
  • 2018-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-14
  • 2020-09-24
  • 1970-01-01
相关资源
最近更新 更多