【发布时间】:2017-09-05 09:38:58
【问题描述】:
我正在尝试创建一个程序来获取图像序列并以所需的帧速率(最高 120 FPS)播放它。
到目前为止,我有一个 Image 控件的 Source 绑定到的类。此类存储文件位置列表,并且可以调用下一帧的文件位置。它看起来像这样:
public class VideoViewer : INotifyPropertyChanged
{
private string image;
private List<string> imageLocs = new List<string>();
private int imageIndex = 0;
public event PropertyChangedEventHandler PropertyChanged;
public string imageSource
{
get
{
return image;
}
set
{
image = value;
OnPropertyChanged("imageSource");
}
}
public List<string> imagesArray
{
get
{
return imageLocs;
}
set
{
imageLocs = value;
OnPropertyChanged("imagesArray");
}
}
public void NextFrame()
{
//If not on last frame
if(imageIndex < (imageLocs.Count - 1))
{
//Add one to the index to select the next frame in the array
imageIndex += 1;
imageSource = imagesArray[imageIndex];
//Update the image
OnPropertyChanged("imageSource");
}
//If on the last frame of the array, reset to 0
else if(imageIndex == (imageLocs.Count - 1))
{
imageIndex = 0;
imageSource = imagesArray[imageIndex];
OnPropertyChanged("imageSource");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
在我的 MainWindow 中,我有 3 个按钮,一个加载类的浏览按钮,一个启动 DispatcherTimer 的播放按钮,它每 1/120 秒调用我的类的 NextFrame() 方法,以及一个停止计时器的停止按钮.
public partial class MainWindow : Window
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
VideoViewer vV = new VideoViewer();
DispatcherTimer timer = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
this.DataContext = vV;
}
private void PlayButton_Click(object sender, RoutedEventArgs e)
{
timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1/120) };
timer.Tick += TimerTick;
timer.Start();
}
private void PauseButton_Click(object sender, RoutedEventArgs e)
{
timer.Stop();
}
private void TimerTick(object sender, EventArgs e)
{
vV.NextFrame();
}
private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
// Set the file dialog to filter for graphics files.
this.openFileDialog1.Filter =
"Images (*.BMP;*.JPG;*.GIF;*.PNG)|*.BMP;*.JPG;*.GIF;*.PNG|" +
"All files (*.*)|*.*";
// Allow the user to select multiple images.
this.openFileDialog1.Multiselect = true;
this.openFileDialog1.Title = "My Image Browser";
DialogResult dr = this.openFileDialog1.ShowDialog();
if (dr == System.Windows.Forms.DialogResult.OK)
{
if (dr == System.Windows.Forms.DialogResult.OK)
{
List<string> images = new List<string>();
// Read the files
foreach (String file in openFileDialog1.FileNames)
{
images.Add(file);
}
vV.imagesArray = images;
}
}
}
}
这在较低的帧速率下工作正常,但播放视频的速度似乎不会超过 30 FPS(例如,我希望 30 FPS 的视频在设置为 120 FPS 时以 4 倍的速度播放)
除了 DispatcherTimer 之外,还有什么可以用来达到预期效果的吗?
【问题讨论】:
-
我想从文件中加载你的图像并解码它需要比你想要的帧长度更长的时间。
-
如何正常工作?
1 / 120将返回0,因为涉及到int计算。这应该改为1D / 120D。 Proof here -
从 1/120 更改为 1D/120D 没有任何作用,它仍然以相同的速度播放。是的,我在想,如果不是计时器限制,加载文件可能需要很长时间。
-
您可以通过自己预先加载所有图像来验证该假设(因此您的 imagesArray 类型将是
List<ImageSource>)。 -
您是否尝试过扩展
UIElement或FrameworkElement并使用OnRender方法来绘制图像?这应该比现在快很多。