[英]How to draw a simulated ECG?
我想创造什么(它不必非常精确,它只是为了娱乐目的):
我有的:
我有一个 REST API 到一个服务,让我查询佩戴脉搏测量设备的人的当前 BPM。 因此,我没有指示何时发生炉膛跳动的事件。 我必须用给定的 BPM 来计算这个。 但这不是问题。
问题:
当它到达右上角时,您将如何绘制线条并使它们从左到右消失并重置。 我在 C# WPF 方面有一些经验,这就是我创建 REST 查询内容的原因。 绘图部分是否有一些库? 有没有一种简单的方法可以手动完成?
我非常感谢任何建议,因为我在互联网上这样一个相当具体的问题上找不到那么多。 所以谢谢!
更新:我得到了一些使用 WritableBitmap 的东西,但它看起来很糟糕。 关于如何获得更好的分辨率的任何想法? 我已经提高了 bitmap 的分辨率,但它看起来仍然很糟糕。 是否有某种抗锯齿功能?
这将使您开始:
安装 WriteableBitmapEx package:
安装包 WriteableBitmapEx
代码:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Width="256" Height="256">
<Grid>
<Image x:Name="Image1" Stretch="Fill" />
</Grid>
</Window>
代码:
#nullable enable
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace WpfApp1
{
public partial class MainWindow
{
private readonly WriteableBitmap _bitmap;
private readonly DispatcherTimer _timer;
private int _bitmapCursor;
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
_bitmap = BitmapFactory.New(256, 256);
Image1.Source = _bitmap;
_timer = new DispatcherTimer(
TimeSpan.FromMilliseconds(20),
DispatcherPriority.Render,
Tick,
Dispatcher.CurrentDispatcher
);
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
_timer.Start();
}
private void Tick(object? sender, EventArgs e)
{
var cy = _bitmap.Height * 0.5;
var y = (int)(cy + Math.Sin(DateTime.Now.TimeOfDay.TotalSeconds) * cy);
_bitmap.DrawLine(_bitmapCursor, 0, _bitmapCursor, _bitmap.PixelHeight - 1, Colors.Transparent);
_bitmap.SetPixel(_bitmapCursor, y, Colors.Red);
_bitmapCursor++;
_bitmapCursor %= _bitmap.PixelWidth;
}
}
}
在这里,我只是在我正在绘制的值前面擦除一个 1 像素宽的矩形,在你的情况下,擦除一个更大的矩形以获得你想要的效果。
请注意,您需要保留先前值的历史记录并从中画一条线,而不是绘制实体图。
此外,您可能还想查看这些库:
https://sourceforge.net/projects/ecgtoolkit-cs/
您可以使用 LinearGradientBrush 作为 OpacityMask 将图像的某些部分涂黑,然后水平动画偏移:
<Grid Background="Black" HorizontalAlignment="Center" VerticalAlignment="Center">
<Image Source="4ku8e.png">
<Image.Triggers>
<EventTrigger RoutedEvent="Image.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Gradient1" Storyboard.TargetProperty="Offset" From="-1.0" To="0" Duration="0:0:6" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="Gradient2" Storyboard.TargetProperty="Offset" From="-0.9" To="0.1" Duration="0:0:6" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="Gradient3" Storyboard.TargetProperty="Offset" From="-0.5" To="0.5" Duration="0:0:6" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="Gradient4" Storyboard.TargetProperty="Offset" From="0" To="1" Duration="0:0:6" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="Gradient5" Storyboard.TargetProperty="Offset" From="0" To="1" Duration="0:0:6" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="Gradient6" Storyboard.TargetProperty="Offset" From="0.1" To="1.1" Duration="0:0:6" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="Gradient7" Storyboard.TargetProperty="Offset" From="0.5" To="1.5" Duration="0:0:6" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="Gradient8" Storyboard.TargetProperty="Offset" From="1" To="2.0" Duration="0:0:6" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="Gradient9" Storyboard.TargetProperty="Offset" From="1" To="2.0" Duration="0:0:6" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
<Image.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStop x:Name="Gradient1" Color="#00000000" />
<GradientStop x:Name="Gradient2" Color="#00000000" />
<GradientStop x:Name="Gradient3" Color="#FF000000" />
<GradientStop x:Name="Gradient4" Color="#FF000000" />
<GradientStop x:Name="Gradient5" Color="#00000000" />
<GradientStop x:Name="Gradient6" Color="#00000000" />
<GradientStop x:Name="Gradient7" Color="#FF000000" />
<GradientStop x:Name="Gradient8" Color="#FF000000" />
<GradientStop x:Name="Gradient9" Color="#00000000" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
</Grid>
它不是 100% 完美的,因为您的心电图图像的左右两侧都有空白区域,但如果您将其剪辑,它会看起来更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.