<i id='T3xwi'><tr id='T3xwi'><dt id='T3xwi'><q id='T3xwi'><span id='T3xwi'><b id='T3xwi'><form id='T3xwi'><ins id='T3xwi'></ins><ul id='T3xwi'></ul><sub id='T3xwi'></sub></form><legend id='T3xwi'></legend><bdo id='T3xwi'><pre id='T3xwi'><center id='T3xwi'></center></pre></bdo></b><th id='T3xwi'></th></span></q></dt></tr></i><div id='T3xwi'><tfoot id='T3xwi'></tfoot><dl id='T3xwi'><fieldset id='T3xwi'></fieldset></dl></div>
      <legend id='T3xwi'><style id='T3xwi'><dir id='T3xwi'><q id='T3xwi'></q></dir></style></legend>
        <bdo id='T3xwi'></bdo><ul id='T3xwi'></ul>

      <small id='T3xwi'></small><noframes id='T3xwi'>

      1. <tfoot id='T3xwi'></tfoot>

        从 C++ 中的像素值数组创建视频

        时间:2023-06-05

      2. <tfoot id='jDpBn'></tfoot>

              • <bdo id='jDpBn'></bdo><ul id='jDpBn'></ul>

                <small id='jDpBn'></small><noframes id='jDpBn'>

              • <legend id='jDpBn'><style id='jDpBn'><dir id='jDpBn'><q id='jDpBn'></q></dir></style></legend>
                <i id='jDpBn'><tr id='jDpBn'><dt id='jDpBn'><q id='jDpBn'><span id='jDpBn'><b id='jDpBn'><form id='jDpBn'><ins id='jDpBn'></ins><ul id='jDpBn'></ul><sub id='jDpBn'></sub></form><legend id='jDpBn'></legend><bdo id='jDpBn'><pre id='jDpBn'><center id='jDpBn'></center></pre></bdo></b><th id='jDpBn'></th></span></q></dt></tr></i><div id='jDpBn'><tfoot id='jDpBn'></tfoot><dl id='jDpBn'><fieldset id='jDpBn'></fieldset></dl></div>
                    <tbody id='jDpBn'></tbody>
                  本文介绍了从 C++ 中的像素值数组创建视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  有谁知道一种将存储在数组中的像素值序列保存到视频的方法?目前我正在使用 Cimg 来可视化一个简单的 n 体模拟,同时我可以将每次迭代保存到一个图像文件中,这非常慢.任何有关处理视频的类似库的建议将不胜感激.本质上,我只想将我创建的 Cimg 窗口中显示的内容记录到视频文件中.程序是用C++编写的,在linux上,用g++编译.

                  Does anyone know of a method to save a sequence of pixel values, stored in an array to a video? Currently I'm using Cimg to visualise a simple n-body simulation, whilst I can save each iteration to an image file, this is very slow. Any suggestions on a similar library for handling video would be appreciated. Essentially, I just want to record what's displayed in the Cimg window I create to a video file. The program is written in C++, on linux, compiling with g++.

                  事实上,我可以运行模拟并使用屏幕捕获软件记录它的运行情况,这似乎意味着这是可能的,但我想要一个更简洁的解决方案.

                  The fact that I can run the simulation and record it running with screen capturing software would seem to imply it's possible, but I'd like a tidier solution.

                  推荐答案

                  我今天正在玩这个,我想我会分享我的结果.您可以从 CImg 输出原始 RGB 视频,然后使用 ffmpeg 将其编码为视频,如下所示:

                  I was playing around doing this today, and thought I would share my results. You can output raw RGB video from CImg and then use ffmpeg to encode it up into video like this:

                  #include <iostream>
                  #include "CImg.h"
                  
                  using namespace std;
                  using namespace cimg_library;
                  
                  int main()
                  {
                     const unsigned int width=1024;
                     const unsigned int height=768;
                  
                     // Basic frame we will draw in
                     CImg<unsigned char> image(width,height,1,3);
                  
                     unsigned char magenta[] = {255,0,255};
                  
                     // We are going to output 300 frames of 1024x768 RGB raw video
                     // ... making a 10s long video at 30fps
                     int radius=100;
                     int cx=100;
                     int cy=100;
                     for(int frame=0;frame<300;frame++){
                        // Start with black - it shows fewer stains ;-)
                        image.fill(0);
                        image.draw_circle(cx,cy,radius,magenta);
                  
                        // Move and re-colour circle
                        cx+=2; cy++; if(magenta[1]!=255){magenta[1]++;}
                  
                        // Output to ffmpeg to make video, in planar GBR format
                        // i.e. run program like this
                        // ./main | ffmpeg -y -f rawvideo -pixel_format gbrp -video_size 1024x768 -i - -c:v h264 -pix_fmt yuv420p video.mov
                        char* s=reinterpret_cast<char*>(image.data()+(width*height));   // Get start of G plane
                        std::cout.write(s,width*height);                                // Output it
                        s=reinterpret_cast<char*>(image.data()+2*(width*height));       // Get start of B plane
                        std::cout.write(s,width*height);                                // Output it
                        s=reinterpret_cast<char*>(image.data());                        // Get start of R plane
                        std::cout.write(s,width*height);                                // Output it
                     }
                  }
                  

                  我想我不会去好莱坞,因为视频不是很令人兴奋!

                  I guess I won't make it to Hollywood as the video is not very exciting!

                  像这样运行上面的代码来制作视频:

                  Run the above code like this to make a video:

                  ./main | ffmpeg -y -f rawvideo -pixel_format gbrp -video_size 1024x768 -i - -c:v h264 -pix_fmt yuv420p video.mov
                  


                  注意 1

                  要意识到的是,CImg 以平面配置存储数据,这意味着首先是所有红色像素,然后是所有绿色像素,然后是所有蓝色像素 - 所有没有任何填充或空格.

                  The thing to realise is that CImg stores data in a planar configuration, which means all the red pixels first, then all the green ones directly afterwards and then all the blue ones straight after that - all without any padding or spaces.

                  想象一下 CImg 中的 4x4 图像(16 像素):

                  Imagine a 4x4 image (with 16 pixels) in CImg:

                  RRRRRRRRRRRRRRRR GGGGGGGGGGGGGGGG BBBBBBBBBBBBBBBB
                  

                  与常规 RGB 数据不同,它会存储与以下内容相同的图像:

                  unlike regular RGB data, which would store the same image as:

                  RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB 
                  

                  因此,您可以将所有数据打乱并重新格式化并作为 -pixel_fmt rgb24 传递给 ffmpeg,或者像我一样在 中输出CImg 的平面格式并选择匹配的 -pixel_fmt gbrp(其中 p 表示 平面").您只需要以正确的 B、G、R 顺序输出平面.另请参阅注释 4.

                  So, you can either shuffle all the data around and reformat it and pass to ffmpeg as -pixel_fmt rgb24, or do as I did and output in CImg's planar format and choose a matching -pixel_fmt gbrp (where the p means "planar"). You just have to output the planes in the correct B,G,R order. See also Note 4.

                  注意事项 2

                  我选择做 3 个 write() ,每个颜色平面一个,为了演示的清晰起见,使用 聚集写入"会更有效.writev(),所以:

                  I chose to do 3 write()s, one for each colour plane, for the sake of clarity of demonstration, it would be more efficient to use a "gathered write" with writev(), so this:

                  char* s=reinterpret_cast<char*>(image.data()+(width*height));   // Get start of G plane
                  std::cout.write(s,width*height);                                // Output it
                  s=reinterpret_cast<char*>(image.data()+2*(width*height));       // Get start of B plane
                  std::cout.write(s,width*height);                                // Output it
                  s=reinterpret_cast<char*>(image.data());                        // Get start of R plane
                  std::cout.write(s,width*height);  
                  

                  会变成这样:

                  struct iovec iov[3];
                  ssize_t nwritten;
                  
                  iov[0].iov_base = reinterpret_cast<char*>(image.data()+(width*height))
                  iov[0].iov_len  = width*height;
                  iov[1].iov_base = reinterpret_cast<char*>(image.data()+2*(width*height));
                  iov[1].iov_len  = width*height;
                  iov[2].iov_base = reinterpret_cast<char*>(image.data());  
                  iov[2].iov_len  = width*height;
                  
                  nwritten = writev(STDOUT_FILENO,iov,3);
                  


                  注意 3

                  我使用 -c:v h264 -pix_fmt yuv420p 使视频与 Mac 上的 Apple QuickTime 兼容,但无论如何您都可以轻松更改输出 -更难的部分是让 CImgfmpeg 之间的接口正确.

                  I used the -c:v h264 -pix_fmt yuv420p to make the video compatible with Apple's QuickTime on my Mac, but you can change the output easily anyway - the harder part was getting the interface between CImg and fmpeg right.

                  注意事项 4

                  如果你想打乱数据并将其写入ffmpeg非平面(-pixel_fmt rgb),我最初是这样做的,代码是这样的:

                  If you want to shuffle the data around and write it to ffmpeg non-planar (-pixel_fmt rgb), I did that originally and the code was like this:

                  // Outside main loop
                  unsigned char* BIP = new unsigned char[width*height*3];
                  unsigned char *d,*r,*g,*b;
                  
                  ...
                  ...
                  
                  // Now output it...
                  // ... remember CImg is band-interleaved by plane  RRRRRR GGGGGG BBBBBB
                  // ... not band-interleaved by pixel RGB RGB RGB RGB
                  r=image.data();       // Start of R plane in CImg image
                  g=r+(width*height);   // Start of G plane in CImg image
                  b=g+(width*height);   // Start of B plane in CImg image
                  d=BIP;                // Destination buffer in RGB order
                  for(int i=0;i<width*height;i++){
                     *d++=*r++;
                     *d++=*g++;
                     *d++=*b++;
                  }
                  // Output to ffmpeg to make video, i.e. run program like this
                  // ./main | ffmpeg -y -f rawvideo -pixel_format rgb24 -video_size 1024x768 -i - -c:v h264 -pix_fmt yuv420p video.mov
                  std::cout.write(reinterpret_cast<char*>(BIP),width*height*3);
                  

                  理论上,您可以使用 CImgpermute_axes() 方法来做到这一点,但我没有成功.

                  In theory, you can do this with CImg's permute_axes() method, but I had no success.

                  这篇关于从 C++ 中的像素值数组创建视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:使用 Qt 播放实时视频流 下一篇:使用gstreamer暂停后如何继续播放?

                  相关文章

                • <i id='jzucG'><tr id='jzucG'><dt id='jzucG'><q id='jzucG'><span id='jzucG'><b id='jzucG'><form id='jzucG'><ins id='jzucG'></ins><ul id='jzucG'></ul><sub id='jzucG'></sub></form><legend id='jzucG'></legend><bdo id='jzucG'><pre id='jzucG'><center id='jzucG'></center></pre></bdo></b><th id='jzucG'></th></span></q></dt></tr></i><div id='jzucG'><tfoot id='jzucG'></tfoot><dl id='jzucG'><fieldset id='jzucG'></fieldset></dl></div>
                  1. <legend id='jzucG'><style id='jzucG'><dir id='jzucG'><q id='jzucG'></q></dir></style></legend>
                  2. <small id='jzucG'></small><noframes id='jzucG'>

                    • <bdo id='jzucG'></bdo><ul id='jzucG'></ul>
                      <tfoot id='jzucG'></tfoot>