如何在位图图像上绘制对数轴
How do I Draw Logarithmic Axis on Bitmap Image
我正在创建一个频谱图,其中 y 轴是输入文件的频率响应。
基于最小和最大频率(基于 fs 是可变的),我将如何:
- 以有意义的方式根据对数分布绘制频率的 y 轴,如下面的示例图像所示。 log10(f), 下图中频率在x轴上,仅用于说明一个点
图一
以前的图像换成更适合对数刻度的图像
沿 y 轴提供许多带注释的参考点,这些参考点与值直接相关,即 100Hz、1kHz、5kHz(在 1/3 倍频程频带中,如所述 here)
定义用于绘制频率的像素与频率映射比率方法,其中沿 y 轴有 n 个频率区间
最后,虽然我已经能够使用以下代码创建基本图形,但对于如何最好地在位图图像中实现对数比例,我有点不知所措:
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));
}
我迄今为止创建的图像的缩放渲染如下所示。
频谱图中的每个(单色)点将使用以下代码段绘制:
spectrogram.SetPixel(x, y, Color.FromArgb(255, colour, colour, colour));
我有所有必要的数据可以绘制在以下轴上:
- x 时间(线性)
- y 频率(对数)
- z 强度(对数)
另一个挑战是图像是从左上角而不是右下角渲染的,所以如果你能告诉我一个明智的方法来处理这个问题,我将非常感激。
这是一个使用 .NET 4.5.2 的 c# 控制台应用程序
更新
通过希望澄清问题,我希望实现的是图表对数刻度模式,并在位图图表轴而不是图表控件上实现它:
axis.IsLogarithmic = true;
所以取 log10(频率)(在我的示例中)在 0 Hz 和 21963 Hz 之间有 256 个 points/frequency bin,然后将其映射到 y 轴上,使用常见的 1/3 倍频程中心频率符号y轴如下图:
请注意,上图取自 this post,其中 OP 向我请求类似的信息,但在图表控件上,由于未使用图表对象,我无法使用其答案。
有关 256 points/frequency 个垃圾箱的含义的说明,请参见下文:
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
要在两个值之间创建对数刻度,让 V0
和 V1
,取以 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)))
获得这几十年的starting/ending位数
例如,从19到3410,十进制从10/100到1000/10000,第2位到第3位。
我正在创建一个频谱图,其中 y 轴是输入文件的频率响应。 基于最小和最大频率(基于 fs 是可变的),我将如何:
- 以有意义的方式根据对数分布绘制频率的 y 轴,如下面的示例图像所示。 log10(f), 下图中频率在x轴上,仅用于说明一个点
图一
以前的图像换成更适合对数刻度的图像
沿 y 轴提供许多带注释的参考点,这些参考点与值直接相关,即 100Hz、1kHz、5kHz(在 1/3 倍频程频带中,如所述 here)
定义用于绘制频率的像素与频率映射比率方法,其中沿 y 轴有 n 个频率区间
最后,虽然我已经能够使用以下代码创建基本图形,但对于如何最好地在位图图像中实现对数比例,我有点不知所措:
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));
}
我迄今为止创建的图像的缩放渲染如下所示。
频谱图中的每个(单色)点将使用以下代码段绘制:
spectrogram.SetPixel(x, y, Color.FromArgb(255, colour, colour, colour));
我有所有必要的数据可以绘制在以下轴上:
- x 时间(线性)
- y 频率(对数)
- z 强度(对数)
另一个挑战是图像是从左上角而不是右下角渲染的,所以如果你能告诉我一个明智的方法来处理这个问题,我将非常感激。
这是一个使用 .NET 4.5.2 的 c# 控制台应用程序
更新
通过希望澄清问题,我希望实现的是图表对数刻度模式,并在位图图表轴而不是图表控件上实现它:
axis.IsLogarithmic = true;
所以取 log10(频率)(在我的示例中)在 0 Hz 和 21963 Hz 之间有 256 个 points/frequency bin,然后将其映射到 y 轴上,使用常见的 1/3 倍频程中心频率符号y轴如下图:
请注意,上图取自 this post,其中 OP 向我请求类似的信息,但在图表控件上,由于未使用图表对象,我无法使用其答案。
有关 256 points/frequency 个垃圾箱的含义的说明,请参见下文:
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
要在两个值之间创建对数刻度,让 V0
和 V1
,取以 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)))
获得这几十年的starting/ending位数
例如,从19到3410,十进制从10/100到1000/10000,第2位到第3位。