Haar Wavelets Implementation in C#
2009-05-26 20:52
295 查看
You searched for 'wavelet c#'
Here are some results for the search term on this websiteHaar Wavelets Implementation in C#
Latest Activities
<< Latest Activities | The joys of sharing the world with trolls >>
三月23
Haar Wavelets Implementation in C#
Tags: c#, wavelets | Categories: Computer Sciencehttp://www.raine-tech.com/blogs/jr/post/Haar-Wavelets-Implementation-in-C.aspx" target=_blank>E-mail | Permalink | 评论 (3) | Post RSS
[HaarWavelets.rar]
As I mentioned in a recent post, I’ve recently started studying the subject of wavelets, a mathematical transform with many interesting applications than range from image compression to audio de-noising. I won’t go into detail of what wavelets are and how they work, though I intend to do so in a later blog post once I feel more comfortable with the subject, but in the meantime I decided to implement the Haar Wavelets, which are the simplest kind, in C#. The implementation itself is nothing fancy and rather straightforward, but I find the operations themselves and how they work to be very appealing.
The interface for the class is very conservative, offering methods to acquire the trend and fluctuation sub-signals from an input as well as methods to reconstruct a signal from its trend and fluctuations. I also included methods to perform transforms and inverse transforms which take the number of levels of the desired (Each level represents one application of the transform). Since I’m using doubles as the numeric type, there are a few numeric stability issues which I decided not to get into at the time. They could be reduced by simply using the decimal type instead or considering them when working with the class.
Here’s the full source code, which you can also download from the link above. The class could be made much shorter and a bit more efficient by offering only methods to perform the transform and the inverse transform, instead of breaking the functionality into pieces and allowing clients to obtain only the trend or fluctuation sub-signals. Particuarly, performing a full one-level transform would require traversing the input only once whereas in the current implementation it’s done twice since the trend and fluctuations are calculated separately. In spite of this, I prefer the current implementation because it offers a clear and explicit way to work with the transforms rather than having to use one array that holds all the required sub-signals similar to what the Transform method returns.
1: using System;
2: using System.Linq;
3:
4: namespace RaineTech.Math.Wavelets
5: {
6: /// <summary>
7: /// Represents the Haar Wavelets.
8: /// </summary>
9: public class HaarWavelets
10: {
11: /// <summary>
12: /// Calculates the trend sub-signal for the specified input.
13: /// </summary>
14: /// <param name="input">The input from which to calculate the trend. Its length must be divisible by 2.</param>
15: /// <returns>An array of half the length of the input containing the trend sub-signal.</returns>
16: public double[] GetTrendSignal(double[] input)
17: {
18: return GetTrendSignal(input, 0, input.Length);
19: }
20:
21: /// <summary>
22: /// Calculates the trend sub-signal for the specified input.
23: /// </summary>
24: /// <param name="input">The input from which to calculate the trend.</param>
25: /// <param name="offset">The offset into the input array.</param>
26: /// <param name="count">The number of elements to take from the input array. This must be a multiple of 2.</param>
27: /// <returns>An array of half the length of the input containing the trend sub-signal.</returns>
28: public double[] GetTrendSignal(double[] input, int offset, int count)
29: {
30: if (count % 2 != 0)
31: {
32: throw new ArgumentException("Input must have an even number of elements.");
33: }
34: int trendLength = count / 2;
35: double[] trend = new double[trendLength];
36: for (int i = 0; i < trendLength; ++i)
37: {
38: trend[i] = (input[offset + 2 * i] + input[offset + 2 * i + 1]) / System.Math.Sqrt(2.0);
39: }
40: return trend;
41: }
42:
43: /// <summary>
44: /// Calculates the fluctuation sub-signal for the specified input.
45: /// </summary>
46: /// <param name="input">The input from which to calculate the fluctuations. Its length must be divisible by 2.</param>
47: /// <returns>An array of half the length of the input containing the fluctuation sub-signal.</returns>
48: public double[] GetFluctuationSignal(double[] input)
49: {
50: return GetFluctuationSignal(input, 0, input.Length);
51: }
52:
53: /// <summary>
54: /// Calculates the fluctuation sub-signal for the specified input.
55: /// </summary>
56: /// <param name="input">The input from which to calculate the fluctuations.</param>
57: /// <param name="offset">The offset into the input array.</param>
58: /// <param name="count">The number of elements to take from the input array. This number must be a multiple of 2.</param>
59: /// <returns>An array of half the length of the input containing the fluctuation sub-signal.</returns>
60: public double[] GetFluctuationSignal(double[] input, int offset, int count)
61: {
62: if (count % 2 != 0)
63: {
64: throw new ArgumentException("Input must have an even number of elements.");
65: }
66: int fluctuationsLength = count / 2;
67: double[] fluctuations = new double[fluctuationsLength];
68: for (int i = 0; i < fluctuationsLength; ++i)
69: {
70: fluctuations[i] = (input[offset + 2 * i] - input[offset + 2 * i + 1]) / System.Math.Sqrt(2.0);
71: }
72: return fluctuations;
73: }
74:
75: /// <summary>
76: /// Reconstructs a signal from its equal-length trend and fluctuation sub-signals. This is equivalent to a
77: /// one-level inverse transform.
78: /// </summary>
79: /// <param name="trendSignal">The trend sub-signal.</param>
80: /// <param name="fluctuationSignal">The fluctuation sub-signal.</param>
81: /// <returns>The reconstructed signal.</returns>
82: public double[] Reconstruct(double[] trendSignal, double[] fluctuationSignal)
83: {
84: double[] result = new double[trendSignal.Length + fluctuationSignal.Length];
85: for (int i = 0; i < trendSignal.Length; ++i)
86: {
87: result[2 * i] = (trendSignal[i] + fluctuationSignal[i]) / System.Math.Sqrt(2.0);
88: result[2 * i + 1] = (trendSignal[i] - fluctuationSignal[i]) / System.Math.Sqrt(2.0);
89: }
90: return result;
91: }
92:
93: /// <summary>
94: /// Performs an n-leveled transform on the specified input.
95: /// </summary>
96: /// <param name="input">The input to transform. The length of this array must be divisilbe by 2 ^ level.</param>
97: /// <param name="level">The levels of the desired transform.</param>
98: /// <returns>
99: /// An array containing the results of the transform starting by the highest leveled thrend sub-signal followed
100: /// by the fluctuation sub-signals in descending order.
101: /// </returns>
102: public double[] Transform(double[] input, int level)
103: {
104: if (input.Length % System.Math.Pow(2, level) != 0)
105: {
106: throw new ArgumentException("The number of levels specified can't be applied on the input.");
107: }
108: double[] result = new double[input.Length];
109: double[] trend, fluctuation;
110: {
111: for (int i = 0; i < level; ++i)
112: {
113: trend = GetTrendSignal(input);
114: fluctuation = GetFluctuationSignal(input);
115: input = trend;
116: for (int j = 0; j < input.Length; ++j)
117: {
118: result[j] = trend[j];
119: result[j + trend.Length] = fluctuation[j];
120: }
121: }
122: }
123: return result;
124: }
125:
126: /// <summary>
127: /// Performs an n-leveled inverse transform on the input array containing the trend and fluctuation sub-signals.
128: /// </summary>
129: /// <param name="input">
130: /// An array that starts with the highest leveled trend sub-signal followed by the fluctuation
131: /// sub-signals in descending order. The length of this array must be divisible by 2 ^ level.
132: /// </param>
133: /// <param name="level">The desired level of the inverse transform.</param>
134: /// <returns>An array containing the result of the inverse transform.</returns>
135: public double[] InverseTransform(double[] input, int level)
136: {
137: if (input.Length % System.Math.Pow(2, level) != 0)
138: {
139: throw new ArgumentException("The number of levels specified can't be applied on the input.");
140: }
141: double[] trend = input, fluctuation = new double[0];
142: for (int i = level; i > 0; --i)
143: {
144: int subsignalLength = input.Length / (int)System.Math.Pow(2, i);
145: trend = trend.Take(subsignalLength).ToArray();
146: fluctuation = input.Skip(subsignalLength).Take(subsignalLength).ToArray();
147: trend = Reconstruct(trend, fluctuation);
148: }
149: return trend;
150: }
151: }
相关文章推荐
- A CRC8 Implementation In C#
- A CRC32 Implementation In C#
- Implementation of Dependency Injection Pattern in C#
- [转]A-Star (A*) Implementation in C# (Path Finding, PathFinder)
- The implementation of anonymous methods in C# and its consequences
- The implementation of anonymous methods in C# and its consequences
- Simple Cryptographer - Simple DES/AES Implementation in C#
- Multiple Implementation in C#
- A Comparison Between Haar Wavelet Transform and Fast Fourier Transform in Analyzing Financial Time S
- Threading in C#
- WPF Recipes in C# 2008: A Problem-Solution Approach
- Sams Teach Yourself the C# Language in 21 Days by Bradley L Jones
- Matrix Factorization: A Simple Tutorial and Implementation in
- Converting PDF to Text in C#(转换PDF为Text)
- Threading in C# ,phase 1
- c# in unity Update()函数的意义
- Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors
- 一步一步学习多线程系列文章---开篇《Threading in C#》翻译
- Using Indexers in C#
- Explaining Delegates in C# - Part 3 (Events 2)