如何在位图图像上绘制对数轴

时间:2016-09-11 14:52:22

标签: c# graphics fft spectrogram

我正在创建一个频谱图,其中y轴是输入文件的频率响应。 根据最小和最大频率(基于fs变化),我将如何:

  1. 以有意义的方式根据对数分布绘制y轴的频率,如下面的示例图所示。 log10(f),在下面的图表中,频率在x轴上,仅用于说明一个点
  2. 图1 frequency response graph

    之前的图片换成了一个更合适的对数刻度表示

    1. 沿y轴提供多个带注释的参考点,这些参考点直接与值相关,即100Hz,1kHz,5kHz(在1/3倍频带中,如here所述)

    2. 定义像素到频率映射比率的方法,用于绘制沿y轴有 n 频率区数的频率

    3. 最后,虽然我已经能够使用以下代码创建基本图形,但我对如何在位图图像中最佳地实现日志比例感到有点遗憾:

          Bitmap spectrogram = new Bitmap(xAxisImageSize, yAxisImageSize);
          // Mmake the Image BG Colour Black
          using (Graphics graph = Graphics.FromImage(spectrogram))
          {
              Rectangle ImageSize = new Rectangle(0, 0, xAxisImageSize, yAxisImageSize);
              graph.FillRectangle(Brushes.Black, ImageSize);
              Pen whitePen = new Pen(Color.White, 3);
              // x axis
              graph.DrawLine(whitePen, 124, 900, 634, 900);
              // x axis label
              graph.DrawString("Time", new Font("Arial", 12), Brushes.White, new PointF(600, 924));
              // y axis
              graph.DrawLine(whitePen, 124, 900, 124, 388);
              // y axis label
              graph.DrawString("f (Hz)", new Font("Arial", 12), Brushes.White, new PointF(24, 388));
              // y axis top frequency
              graph.DrawString("20k", new Font("Arial", 12), Brushes.White, new PointF(75, 388));
              // y axis top marker
              graph.DrawLine(whitePen, 110, 388, 124, 388);
              // x axis Zero Point
              graph.DrawString("0", new Font("Arial", 12), Brushes.White, new PointF(124, 924));
              // y axis Zero Point
              graph.DrawString("0", new Font("Arial", 12), Brushes.White, new PointF(75, 886));
          }
      

      到目前为止我创建的图像的缩放渲染可以在下面看到。

      cropped and scaled spectrogram example

      光谱图中的每个(单色)点将使用以下片段绘制:

      spectrogram.SetPixel(x, y, Color.FromArgb(255, colour, colour, colour));
      

      我有以下轴上绘制的所有必要数据:

      1. x time(linear)
      2. y频率(对数)
      3. z强度(对数)
      4. 另一个挑战是图像是从左上角而不是右下角渲染的,所以如果你能告诉我一个合理的方法来管理它,我会非常感激。

        这是一个使用.NET 4.5.2的c#控制台应用程序

        更新

        通过希望澄清问题,我希望实现的是图表对数比例模式,并在位图图形轴而不是图表控件上实现:

        axis.IsLogarithmic = true;
        

        所以取log10(频率),其中有(在我的例子中)在0 Hz和21963 Hz之间的256点/频率区间然后将其映射到y轴上,在y轴上具有共同的1/3倍频程中心频率符号如下所示:

        enter image description here

        请注意,上面的图片来自this post,其中OP正在向我请求类似的信息,但是在图表控件上,由于没有使用图表对象,我无法使用该答案。

        有关256点/频率箱的含义的说明,请参阅下文:

        Frequency Bin 0: 0
        Frequency Bin 1: 86
        Frequency Bin 2: 172
        Frequency Bin 3: 258
        Frequency Bin 4: 344
        Frequency Bin 5: 430
        Frequency Bin 6: 516
        Frequency Bin 7: 602
        Frequency Bin 8: 689
        Frequency Bin 9: 775
        Frequency Bin 10: 861
        Frequency Bin 11: 947
        Frequency Bin 12: 1033
        Frequency Bin 13: 1119
        .....
        Frequency Bin 242: 20844
        Frequency Bin 243: 20930
        Frequency Bin 244: 21016
        Frequency Bin 245: 21102
        Frequency Bin 246: 21188
        Frequency Bin 247: 21274
        Frequency Bin 248: 21360
        Frequency Bin 249: 21447
        Frequency Bin 250: 21533
        Frequency Bin 251: 21619
        Frequency Bin 252: 21705
        Frequency Bin 253: 21791
        Frequency Bin 254: 21877
        Frequency Bin 255: 21963
        

1 个答案:

答案 0 :(得分:0)

要在两个值之间创建对数刻度,请V0V1,取10个对数log(V1)log(V2)并重新缩放以映射到所需的坐标在你的情节中,让X0转到X1

X = X0 + (X1 - X0)(log(V) - log(V0))/(log(V1) - log(V0))

要以简单值绘制刻度,首先要确定跨越的完整十年,从10^floor(log(V0))10^floor(log(V1)),然后通过

获取最高位数
ceil(10^(log(V0) - floor(log(V0)))
floor(10^(log(V1) - floor(log(V1)))

获取这几十年的开始/结束数字。

例如,从19到3410,几十年从10/100到1000/10000,数字2到数字3包括在内。