使用 ImageMagick 高效拼接线扫描图像
Using ImageMagick to efficiently stitch together a line scan image
我正在寻找用于运动计时的线扫描相机的替代品,或者更确切地说,用于需要确定位置的部分。我发现普通工业相机可以轻松达到每秒 1000 帧以上的商用相机解决方案的速度。就我的需要而言,通常计时的准确性并不重要,重要的是运动员的相对位置。为此,我想我可以使用最便宜的 Basler、IDS 或任何其他区域扫描工业相机之一。当然,有线扫描相机可以做的远不止几千 fps(或 hz),但是有可能以不到 500 欧元的价格获得可以完成所需的 1000-3000fps 的面扫描相机。
我的圣杯当然是 FinishLynx(或任何其他线扫描系统)的近实时图像合成功能,基本上是这部分:https://youtu.be/7CWZvFcwSEk?t=23s
我考虑替代方案的整个过程是:
- Use Basler Pylon Viewer (or other software) to record 2px wide images at the camera’s fastest read speed. For the camera I am
currently using it means it has to be turned on it’s side and the
height needs to be reduced, since it is the only way it will read
1920x2px frames @ >250fps
- Make a program or batch script that then stitches these 1920x2px frames together to, for example one second of recording 1000*1920x2px
frames, meaning a resulting image with a resolution of 1920x2000px
(Horizontal x Vertical).
- Finally using the same program or another way, just rotate the image so it reflects how the camera is positioned, thus achieving an image
with a resolution of 2000x1920px (again Horizontal x Vertical)
- Open the image in an analyzing program (currently ImageJ) to quickly analyze results
我不是程序员,但这是我能够使用批处理脚本组合在一起的,当然是在 Whosebug 的帮助下。
- Currently recording a whole 10 seconds for example to disk as a raw/mjpeg(avi/mkv) stream can be done in real time.
- Recording individual frames as TIFF or BMP, or using FFMPEG to save them as PNG or JPG takes ~20-60 seconds The appending and rotation
then takes a further ~45-60 seconds
This all needs to be achieved in less than 60 seconds for 10 seconds of footage(1000-3000fps @ 10s = 10000-30000 frames) , thus why I need something faster.
我能够弄清楚如何使用 ImageMagick 非常高效:
magick convert -limit file 16384 -limit memory 8GiB -interlace Plane -quality 85 -append +rotate 270 “%folder%\Basler*.Tiff” “%out%”
#%out% has a .jpg -filename that is dynamically made from folder name and number of frames.
此命令有效并在 i5-2520m 上让我在大约 30 秒内编码了 10000 帧(虽然大多数处理似乎只使用一个线程,因为它以 25% cpu 使用率工作).这是生成的图像:https://i.imgur.com/OD4RqL7.jpg (19686x1928px)
然而,由于使用 Basler 的 Pylon Viewer 记录到 TIFF 帧所花的时间比记录 MJPEG 视频流要长得多,所以我想使用 MJPEG (avi/mkv) 文件作为附加源。我注意到 FFMPEG 有“image2pipe”-command,它应该能够直接将图像提供给 ImageMagick。不过我无法使它正常工作:
$ ffmpeg.exe -threads 4 -y -i "Basler acA1920-155uc (21644989)_20180930_043754312.avi" -f image2pipe - | convert - -interlace Plane -quality 85 -append +rotate 270 "%out%" >> log.txt
ffmpeg version 3.4 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 7.2.0 (GCC)
configuration: –enable-gpl –enable-version3 –enable-sdl2 –enable-bzlib –enable-fontconfig –enable-gnutls –enable-iconv –enable-libass –enable-libbluray –enable-libfreetype –enable-libmp3lame –enable-libopenjpeg –enable-libopus –enable-libshine –enable-libsnappy –enable-libsoxr –enable-libtheora –enable-libtwolame –enable-libvpx –enable-libwavpack –enable-libwebp –enable-libx264 –enable-libx265 –enable-libxml2 –enable-libzimg –enable-lzma –enable-zlib –enable-gmp –enable-libvidstab –enable-libvorbis –enable-cuda –enable-cuvid –enable-d3d11va –enable-nvenc –enable-dxva2 –enable-avisynth –enable-libmfx
libavutil 55. 78.100 / 55. 78.100
libavcodec 57.107.100 / 57.107.100
libavformat 57. 83.100 / 57. 83.100
libavdevice 57. 10.100 / 57. 10.100
libavfilter 6.107.100 / 6.107.100
libswscale 4. 8.100 / 4. 8.100
libswresample 2. 9.100 / 2. 9.100
libpostproc 54. 7.100 / 54. 7.100
Invalid Parameter - -interlace
[mjpeg @ 000000000046b0a0] EOI missing, emulating
Input #0, avi, from 'Basler acA1920-155uc (21644989)_20180930_043754312.avi’:
Duration: 00:00:50.02, start: 0.000000, bitrate: 1356 kb/s
Stream #0:0: Video: mjpeg (MJPG / 0x47504A4D), yuvj422p(pc, bt470bg/unknown/unknown), 1920x2, 1318 kb/s, 200 fps, 200 tbr, 200 tbn, 200 tbc
Stream mapping:
Stream #0:0 -> #0:0 (mjpeg (native) -> mjpeg (native))
Press [q] to stop, [?] for help
Output #0, image2pipe, to ‘pipe:’:
Metadata:
encoder : Lavf57.83.100
Stream #0:0: Video: mjpeg, yuvj422p(pc), 1920x2, q=2-31, 200 kb/s, 200 fps, 200 tbn, 200 tbc
Metadata:
encoder : Lavc57.107.100 mjpeg
Side data:
cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
av_interleaved_write_frame(): Invalid argument
Error writing trailer of pipe:: Invalid argument
frame= 1 fps=0.0 q=1.6 Lsize= 0kB time=00:00:00.01 bitrate= 358.4kbits/s speed=0.625x
video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
Conversion failed!
如果我的身高再高一点,我就不会再收到“[mjpeg @ 000000000046b0a0] EOI 丢失,正在模拟”错误。然而,整个事情只适用于<2px high/wide 镜头。
编辑:哦,是的,我还可以使用 ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
或 ffmpeg -i file.mpg $filename%03d.bmp
从 MJPEG/RAW 流中提取所有帧。但是,这是我不想采取的额外步骤。 (仅仅删除一个30000个jpg的文件夹,就需要2分钟……)
有人能想出管道方法的可行解决方案或完全不同的替代方法吗?
我生成了一个 10,000 帧的示例视频,并做了一些测试。显然,我的机器和你的规格不一样,所以结果不能直接比较,但我发现让 ffmpeg
转置视频并将其传输到 ImageMagick[=32= 会更快] 作为原始 RGB24 帧。
我发现我可以像这样在 10.3 秒内将 10 秒的电影转换为 20,000x1920 像素的 JPEG:
ffmpeg -threads 4 -y -i video.mov -frames 10000 -vf "transpose=1" -f image2pipe -vcodec rawvideo -pix_fmt rgb24 - | convert -depth 8 -size 2x1920 rgb:- +append result.jpg
生成的图像如下所示:
我用 CImg
生成了这样的视频。基本上它只是在框架上连续绘制 Red/Green/Blue splodge,直到它到达右边缘,然后再次从左边缘开始:
#include <iostream>
#include "CImg.h"
using namespace std;
using namespace cimg_library;
int main()
{
// Frame we will fill
CImg<unsigned char> frame(1920,2,1,3);
int width =frame.width();
int height=frame.height();
// Item to draw in frame - created with ImageMagick
// convert xc:red xc:lime xc:blue +append -resize 256x2\! splodge.ppm
CImg<unsigned char> splodge("splodge.ppm");
int offs =0;
// We are going to output 10000 frames of RGB raw video
for(int f=0;f<10000;f++){
// Generate white image
frame.fill(255);
// Draw coloured splodge at correct place
frame.draw_image(offs,0,splodge);
offs = (offs + 1) % (width - splodge.width());
// 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 1920x2 -i - -c:v h264 -pix_fmt yuv420p video.mov
char* s=reinterpret_cast<char*>(frame.data()+(width*height)); // Get start of G plane
std::cout.write(s,width*height); // Output it
s=reinterpret_cast<char*>(frame.data()+2*(width*height)); // Get start of B plane
std::cout.write(s,width*height); // Output it
s=reinterpret_cast<char*>(frame.data()); // Get start of R plane
std::cout.write(s,width*height); // Output it
}
}
splodge 是 192x2 像素,看起来像这样:
我又做了一次尝试,看看我是否可以通过几种不同的方式来加快我的另一个答案——因此一个不同的答案。我使用了我在另一个答案中生成的相同合成视频片段来进行测试。
我没有将 2x1920 扫描线传递到 ImageMagick 以将其附加在一起并写入为 JPEG,而是执行了以下操作:
在 C++ 程序中预先创建了完整的输出帧,然后在每次迭代中循环读取 2x1920 扫描线并将其填充到输出帧中的正确位置,并且
读取整个序列后,使用 turbo-jpeg 将其压缩为 JPEG 并将其写入磁盘。
因此,不再需要 ImageMagick。整个程序现在 运行s 在大约 1.3 秒内,而不是通过 ImageMagick.
的 10.3 秒
代码如下:
////////////////////////////////////////////////////////////////////////////////
// stitch.cpp
// Mark Setchell
//
// Read 2x1920 RGB frames from `ffmpeg` and stitch into 20000x1920 RGB image.
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <unistd.h>
#include <turbojpeg.h>
using namespace std;
int main()
{
int frames = 10000;
int height = 1920;
int width = frames *2;
// Buffer in which to assemble complete output image (RGB), e.g. 20000x1920
unsigned char *img = new unsigned char [width*height*3];
// Buffer for one scanline image 1920x2 (RGB)
unsigned char *scanline = new unsigned char[2*height*3];
// Output column
int ocol=0;
// Read frames from `ffmpeg` fed into us like this:
// ffmpeg -threads 4 -y -i video.mov -frames 10000 -vf "transpose=1" -f image2pipe -vcodec rawvideo -pix_fmt rgb24 - | ./stitch
for(int f=0;f<10000;f++){
// Read one scanline from stdin, i.e. 2x1920 RGB image...
ssize_t bytesread = read(STDIN_FILENO, scanline, 2*height*3);
// ... and place into finished frame
// ip is pointer to input image
unsigned char *ip = scanline;
for(int row=0;row<height;row++){
unsigned char *op = &(img[(row*width*3)+3*ocol]);
// Copy 2 RGB pixels from scanline to output image
*op++ = *ip++; // red
*op++ = *ip++; // green
*op++ = *ip++; // blue
*op++ = *ip++; // red
*op++ = *ip++; // green
*op++ = *ip++; // blue
}
ocol += 2;
}
// Now encode to JPEG with turbo-jpeg
const int JPEG_QUALITY = 75;
long unsigned int jpegSize = 0;
unsigned char* compressedImage = NULL;
tjhandle _jpegCompressor = tjInitCompress();
// Compress in memory
tjCompress2(_jpegCompressor, img, width, 0, height, TJPF_RGB,
&compressedImage, &jpegSize, TJSAMP_444, JPEG_QUALITY,
TJFLAG_FASTDCT);
// Clean up
tjDestroy(_jpegCompressor);
// And write to disk
ofstream f("result.jpg", ios::out | ios::binary);
f.write (reinterpret_cast<char*>(compressedImage), jpegSize);
}
备注:
注1:为了预分配输出图像,程序需要提前知道有多少帧到来——我没有参数化那个,我只是hard -编码 10,000,但应该很容易更改。
确定视频序列中帧数的一种方法是:
ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 video.mov
注意 2: 请注意,我使用几个开关编译代码以提高性能:
g++-8 -O3 -march=native stitch.cpp -o stitch
注3:如果你是运行宁在Windows,你可能需要在stdin
之前以二进制模式重新打开正在做:
read(STDIN_FILENO...)
注4:如果你不想使用turbo-jpeg,你可以在主循环结束后删除所有内容,只需发送一个NetPBM PPM
图像通过管道传输到 ImageMagick 并让它进行 JPEG 写入。这看起来非常粗略:
writeToStdout("P6 20000 1920 255\n");
writeToStdout(img, width*height*3);
然后你会 运行 与:
ffmpeg ... | ./stitch | magick ppm:- result.jpg
我正在寻找用于运动计时的线扫描相机的替代品,或者更确切地说,用于需要确定位置的部分。我发现普通工业相机可以轻松达到每秒 1000 帧以上的商用相机解决方案的速度。就我的需要而言,通常计时的准确性并不重要,重要的是运动员的相对位置。为此,我想我可以使用最便宜的 Basler、IDS 或任何其他区域扫描工业相机之一。当然,有线扫描相机可以做的远不止几千 fps(或 hz),但是有可能以不到 500 欧元的价格获得可以完成所需的 1000-3000fps 的面扫描相机。
我的圣杯当然是 FinishLynx(或任何其他线扫描系统)的近实时图像合成功能,基本上是这部分:https://youtu.be/7CWZvFcwSEk?t=23s
我考虑替代方案的整个过程是:
- Use Basler Pylon Viewer (or other software) to record 2px wide images at the camera’s fastest read speed. For the camera I am currently using it means it has to be turned on it’s side and the height needs to be reduced, since it is the only way it will read 1920x2px frames @ >250fps
- Make a program or batch script that then stitches these 1920x2px frames together to, for example one second of recording 1000*1920x2px frames, meaning a resulting image with a resolution of 1920x2000px (Horizontal x Vertical).
- Finally using the same program or another way, just rotate the image so it reflects how the camera is positioned, thus achieving an image with a resolution of 2000x1920px (again Horizontal x Vertical)
- Open the image in an analyzing program (currently ImageJ) to quickly analyze results
我不是程序员,但这是我能够使用批处理脚本组合在一起的,当然是在 Whosebug 的帮助下。
- Currently recording a whole 10 seconds for example to disk as a raw/mjpeg(avi/mkv) stream can be done in real time.
- Recording individual frames as TIFF or BMP, or using FFMPEG to save them as PNG or JPG takes ~20-60 seconds The appending and rotation then takes a further ~45-60 seconds This all needs to be achieved in less than 60 seconds for 10 seconds of footage(1000-3000fps @ 10s = 10000-30000 frames) , thus why I need something faster.
我能够弄清楚如何使用 ImageMagick 非常高效:
magick convert -limit file 16384 -limit memory 8GiB -interlace Plane -quality 85 -append +rotate 270 “%folder%\Basler*.Tiff” “%out%”
#%out% has a .jpg -filename that is dynamically made from folder name and number of frames.
此命令有效并在 i5-2520m 上让我在大约 30 秒内编码了 10000 帧(虽然大多数处理似乎只使用一个线程,因为它以 25% cpu 使用率工作).这是生成的图像:https://i.imgur.com/OD4RqL7.jpg (19686x1928px)
然而,由于使用 Basler 的 Pylon Viewer 记录到 TIFF 帧所花的时间比记录 MJPEG 视频流要长得多,所以我想使用 MJPEG (avi/mkv) 文件作为附加源。我注意到 FFMPEG 有“image2pipe”-command,它应该能够直接将图像提供给 ImageMagick。不过我无法使它正常工作:
$ ffmpeg.exe -threads 4 -y -i "Basler acA1920-155uc (21644989)_20180930_043754312.avi" -f image2pipe - | convert - -interlace Plane -quality 85 -append +rotate 270 "%out%" >> log.txt
ffmpeg version 3.4 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 7.2.0 (GCC)
configuration: –enable-gpl –enable-version3 –enable-sdl2 –enable-bzlib –enable-fontconfig –enable-gnutls –enable-iconv –enable-libass –enable-libbluray –enable-libfreetype –enable-libmp3lame –enable-libopenjpeg –enable-libopus –enable-libshine –enable-libsnappy –enable-libsoxr –enable-libtheora –enable-libtwolame –enable-libvpx –enable-libwavpack –enable-libwebp –enable-libx264 –enable-libx265 –enable-libxml2 –enable-libzimg –enable-lzma –enable-zlib –enable-gmp –enable-libvidstab –enable-libvorbis –enable-cuda –enable-cuvid –enable-d3d11va –enable-nvenc –enable-dxva2 –enable-avisynth –enable-libmfx
libavutil 55. 78.100 / 55. 78.100
libavcodec 57.107.100 / 57.107.100
libavformat 57. 83.100 / 57. 83.100
libavdevice 57. 10.100 / 57. 10.100
libavfilter 6.107.100 / 6.107.100
libswscale 4. 8.100 / 4. 8.100
libswresample 2. 9.100 / 2. 9.100
libpostproc 54. 7.100 / 54. 7.100
Invalid Parameter - -interlace
[mjpeg @ 000000000046b0a0] EOI missing, emulating
Input #0, avi, from 'Basler acA1920-155uc (21644989)_20180930_043754312.avi’:
Duration: 00:00:50.02, start: 0.000000, bitrate: 1356 kb/s
Stream #0:0: Video: mjpeg (MJPG / 0x47504A4D), yuvj422p(pc, bt470bg/unknown/unknown), 1920x2, 1318 kb/s, 200 fps, 200 tbr, 200 tbn, 200 tbc
Stream mapping:
Stream #0:0 -> #0:0 (mjpeg (native) -> mjpeg (native))
Press [q] to stop, [?] for help
Output #0, image2pipe, to ‘pipe:’:
Metadata:
encoder : Lavf57.83.100
Stream #0:0: Video: mjpeg, yuvj422p(pc), 1920x2, q=2-31, 200 kb/s, 200 fps, 200 tbn, 200 tbc
Metadata:
encoder : Lavc57.107.100 mjpeg
Side data:
cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
av_interleaved_write_frame(): Invalid argument
Error writing trailer of pipe:: Invalid argument
frame= 1 fps=0.0 q=1.6 Lsize= 0kB time=00:00:00.01 bitrate= 358.4kbits/s speed=0.625x
video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
Conversion failed!
如果我的身高再高一点,我就不会再收到“[mjpeg @ 000000000046b0a0] EOI 丢失,正在模拟”错误。然而,整个事情只适用于<2px high/wide 镜头。
编辑:哦,是的,我还可以使用 ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
或 ffmpeg -i file.mpg $filename%03d.bmp
从 MJPEG/RAW 流中提取所有帧。但是,这是我不想采取的额外步骤。 (仅仅删除一个30000个jpg的文件夹,就需要2分钟……)
有人能想出管道方法的可行解决方案或完全不同的替代方法吗?
我生成了一个 10,000 帧的示例视频,并做了一些测试。显然,我的机器和你的规格不一样,所以结果不能直接比较,但我发现让 ffmpeg
转置视频并将其传输到 ImageMagick[=32= 会更快] 作为原始 RGB24 帧。
我发现我可以像这样在 10.3 秒内将 10 秒的电影转换为 20,000x1920 像素的 JPEG:
ffmpeg -threads 4 -y -i video.mov -frames 10000 -vf "transpose=1" -f image2pipe -vcodec rawvideo -pix_fmt rgb24 - | convert -depth 8 -size 2x1920 rgb:- +append result.jpg
生成的图像如下所示:
我用 CImg
生成了这样的视频。基本上它只是在框架上连续绘制 Red/Green/Blue splodge,直到它到达右边缘,然后再次从左边缘开始:
#include <iostream>
#include "CImg.h"
using namespace std;
using namespace cimg_library;
int main()
{
// Frame we will fill
CImg<unsigned char> frame(1920,2,1,3);
int width =frame.width();
int height=frame.height();
// Item to draw in frame - created with ImageMagick
// convert xc:red xc:lime xc:blue +append -resize 256x2\! splodge.ppm
CImg<unsigned char> splodge("splodge.ppm");
int offs =0;
// We are going to output 10000 frames of RGB raw video
for(int f=0;f<10000;f++){
// Generate white image
frame.fill(255);
// Draw coloured splodge at correct place
frame.draw_image(offs,0,splodge);
offs = (offs + 1) % (width - splodge.width());
// 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 1920x2 -i - -c:v h264 -pix_fmt yuv420p video.mov
char* s=reinterpret_cast<char*>(frame.data()+(width*height)); // Get start of G plane
std::cout.write(s,width*height); // Output it
s=reinterpret_cast<char*>(frame.data()+2*(width*height)); // Get start of B plane
std::cout.write(s,width*height); // Output it
s=reinterpret_cast<char*>(frame.data()); // Get start of R plane
std::cout.write(s,width*height); // Output it
}
}
splodge 是 192x2 像素,看起来像这样:
我又做了一次尝试,看看我是否可以通过几种不同的方式来加快我的另一个答案——因此一个不同的答案。我使用了我在另一个答案中生成的相同合成视频片段来进行测试。
我没有将 2x1920 扫描线传递到 ImageMagick 以将其附加在一起并写入为 JPEG,而是执行了以下操作:
在 C++ 程序中预先创建了完整的输出帧,然后在每次迭代中循环读取 2x1920 扫描线并将其填充到输出帧中的正确位置,并且
读取整个序列后,使用 turbo-jpeg 将其压缩为 JPEG 并将其写入磁盘。
因此,不再需要 ImageMagick。整个程序现在 运行s 在大约 1.3 秒内,而不是通过 ImageMagick.
的 10.3 秒代码如下:
////////////////////////////////////////////////////////////////////////////////
// stitch.cpp
// Mark Setchell
//
// Read 2x1920 RGB frames from `ffmpeg` and stitch into 20000x1920 RGB image.
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <unistd.h>
#include <turbojpeg.h>
using namespace std;
int main()
{
int frames = 10000;
int height = 1920;
int width = frames *2;
// Buffer in which to assemble complete output image (RGB), e.g. 20000x1920
unsigned char *img = new unsigned char [width*height*3];
// Buffer for one scanline image 1920x2 (RGB)
unsigned char *scanline = new unsigned char[2*height*3];
// Output column
int ocol=0;
// Read frames from `ffmpeg` fed into us like this:
// ffmpeg -threads 4 -y -i video.mov -frames 10000 -vf "transpose=1" -f image2pipe -vcodec rawvideo -pix_fmt rgb24 - | ./stitch
for(int f=0;f<10000;f++){
// Read one scanline from stdin, i.e. 2x1920 RGB image...
ssize_t bytesread = read(STDIN_FILENO, scanline, 2*height*3);
// ... and place into finished frame
// ip is pointer to input image
unsigned char *ip = scanline;
for(int row=0;row<height;row++){
unsigned char *op = &(img[(row*width*3)+3*ocol]);
// Copy 2 RGB pixels from scanline to output image
*op++ = *ip++; // red
*op++ = *ip++; // green
*op++ = *ip++; // blue
*op++ = *ip++; // red
*op++ = *ip++; // green
*op++ = *ip++; // blue
}
ocol += 2;
}
// Now encode to JPEG with turbo-jpeg
const int JPEG_QUALITY = 75;
long unsigned int jpegSize = 0;
unsigned char* compressedImage = NULL;
tjhandle _jpegCompressor = tjInitCompress();
// Compress in memory
tjCompress2(_jpegCompressor, img, width, 0, height, TJPF_RGB,
&compressedImage, &jpegSize, TJSAMP_444, JPEG_QUALITY,
TJFLAG_FASTDCT);
// Clean up
tjDestroy(_jpegCompressor);
// And write to disk
ofstream f("result.jpg", ios::out | ios::binary);
f.write (reinterpret_cast<char*>(compressedImage), jpegSize);
}
备注:
注1:为了预分配输出图像,程序需要提前知道有多少帧到来——我没有参数化那个,我只是hard -编码 10,000,但应该很容易更改。
确定视频序列中帧数的一种方法是:
ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 video.mov
注意 2: 请注意,我使用几个开关编译代码以提高性能:
g++-8 -O3 -march=native stitch.cpp -o stitch
注3:如果你是运行宁在Windows,你可能需要在stdin
之前以二进制模式重新打开正在做:
read(STDIN_FILENO...)
注4:如果你不想使用turbo-jpeg,你可以在主循环结束后删除所有内容,只需发送一个NetPBM PPM
图像通过管道传输到 ImageMagick 并让它进行 JPEG 写入。这看起来非常粗略:
writeToStdout("P6 20000 1920 255\n");
writeToStdout(img, width*height*3);
然后你会 运行 与:
ffmpeg ... | ./stitch | magick ppm:- result.jpg