1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
// Haar 小波变换(纯 MoonBit)
///|
/// Haar 小波变换结果
pub struct HaarWaveletResult {
width : Int
height : Int
levels : Int // 分解层数
coefficients : Array[Float] // 小波系数
}
///|
/// 一维 Haar 小波变换(原地)。
/// 对长度为 n(2 的幂)的数组进行 Haar 变换。
pub fn haar_transform_1d(data : Array[Float]) -> Array[Float] {
let n = data.length()
if n < 2 {
return data.copy()
}
let out = data.copy()
let sqrt2 = 2.0F.sqrt()
let mut len = n
while len > 1 {
let half = len / 2
let temp : Array[Float] = Array::make(len, 0.0F)
for i in 0..<half {
temp[i] = (out[2 * i] + out[2 * i + 1]) / sqrt2
temp[half + i] = (out[2 * i] - out[2 * i + 1]) / sqrt2
}
for i in 0..<len {
out[i] = temp[i]
}
len = half
}
out
}
///|
/// 一维 Haar 小波逆变换。
pub fn ihaar_transform_1d(data : Array[Float]) -> Array[Float] {
let n = data.length()
if n < 2 {
return data.copy()
}
let out = data.copy()
let sqrt2 = 2.0F.sqrt()
// 从最小级别开始逆变换
let mut len = 2
while len <= n {
let half = len / 2
let temp : Array[Float] = Array::make(len, 0.0F)
for i in 0..<half {
temp[2 * i] = (out[i] + out[half + i]) / sqrt2
temp[2 * i + 1] = (out[i] - out[half + i]) / sqrt2
}
for i in 0..<len {
out[i] = temp[i]
}
len *= 2
}
out
}
///|
/// 二维 Haar 小波变换。
/// 适用于灰度图(channels=1)或 RGB/RGBA 图(channels=3/4,自动转灰度)。
/// levels 为分解层数。
pub fn haar_transform_2d(
img : @types.Image,
levels? : Int = 1,
) -> HaarWaveletResult raise @types.LoadError {
if img.channels != 1 && img.channels != 3 && img.channels != 4 {
raise @types.LoadError::DecodeFailed(
"haar_transform_2d 仅支持 channels=1/3/4",
)
}
if levels < 1 || levels > 10 {
raise @types.LoadError::DecodeFailed("levels 必须在 1..10 之间")
}
let w = img.width
let h = img.height
let n = w * h
if n == 0 {
return HaarWaveletResult::{
width: w,
height: h,
levels: 0,
coefficients: [],
}
}
// 转灰度为 Float
let coeffs : Array[Float] = Array::make(n, 0.0F)
let ch = img.channels
let data_int : Array[Int] = Array::make(n * ch, 0)
for i in 0..<(n * ch) {
data_int[i] = img.data[i].to_int()
}
for i in 0..<n {
let v = if ch == 1 {
data_int[i]
} else {
let r = data_int[i * ch]
let g = data_int[i * ch + 1]
let b = data_int[i * ch + 2]
(r * 299 + g * 587 + b * 114) / 1000
}
coeffs[i] = Float::from_int(v)
}
// 多级分解
let mut cur_w = w
let mut cur_h = h
for _ in 0..<levels {
if cur_w < 2 || cur_h < 2 {
break
}
// 行变换
for y in 0..<cur_h {
let row : Array[Float] = Array::make(cur_w, 0.0F)
for x in 0..<cur_w {
row[x] = coeffs[y * w + x]
}
let transformed = haar_transform_1d(row)
for x in 0..<cur_w {
coeffs[y * w + x] = transformed[x]
}
}
// 列变换
for x in 0..<cur_w {
let col : Array[Float] = Array::make(cur_h, 0.0F)
for y in 0..<cur_h {
col[y] = coeffs[y * w + x]
}
let transformed = haar_transform_1d(col)
for y in 0..<cur_h {
coeffs[y * w + x] = transformed[y]
}
}
cur_w /= 2
cur_h /= 2
}
HaarWaveletResult::{ width: w, height: h, levels, coefficients: coeffs }
}
///|
/// 二维 Haar 小波逆变换。
pub fn haar_inverse_transform_2d(result : HaarWaveletResult) -> @types.Image {
let w = result.width
let h = result.height
let n = w * h
if n == 0 {
return @types.Image::{
width: 0,
height: 0,
channels: 1,
data: Bytes::from_array([]),
}
}
let coeffs = result.coefficients.copy()
// 多级重构(从最小级别开始)
let mut cur_w = w
let mut cur_h = h
for _ in 0..<result.levels {
if cur_w < 2 || cur_h < 2 {
break
}
cur_w /= 2
cur_h /= 2
}
for _ in 0..<result.levels {
if cur_w * 2 > w || cur_h * 2 > h {
break
}
cur_w *= 2
cur_h *= 2
// 列逆变换
for x in 0..<cur_w {
let col : Array[Float] = Array::make(cur_h, 0.0F)
for y in 0..<cur_h {
col[y] = coeffs[y * w + x]
}
let inversed = ihaar_transform_1d(col)
for y in 0..<cur_h {
coeffs[y * w + x] = inversed[y]
}
}
// 行逆变换
for y in 0..<cur_h {
let row : Array[Float] = Array::make(cur_w, 0.0F)
for x in 0..<cur_w {
row[x] = coeffs[y * w + x]
}
let inversed = ihaar_transform_1d(row)
for x in 0..<cur_w {
coeffs[y * w + x] = inversed[x]
}
}
}
// 转为图像
let out : Array[Byte] = Array::make(n, b'\x00')
for i in 0..<n {
let val = coeffs[i].to_int()
out[i] = val.clamp(min=0, max=255).to_byte()
}
@types.Image::{
width: w,
height: h,
channels: 1,
data: Bytes::from_array(out),
}
}
///|
/// Haar 小波去噪(阈值去噪)。
/// 对小波系数应用软阈值或硬阈值,然后逆变换重构。
/// 适用于灰度图(channels=1)或 RGB/RGBA 图(channels=3/4,自动转灰度)。
/// threshold 为阈值,soft=true 为软阈值,false 为硬阈值。
pub fn haar_denoise(
img : @types.Image,
threshold? : Float = 10.0F,
soft? : Bool = true,
levels? : Int = 3,
) -> @types.Image raise @types.LoadError {
if img.channels != 1 && img.channels != 3 && img.channels != 4 {
raise @types.LoadError::DecodeFailed(
"haar_denoise 仅支持 channels=1/3/4",
)
}
let result = haar_transform_2d(img, levels~)
let w = result.width
let h = result.height
let coeffs = result.coefficients
// 阈值处理(保留低频系数不变)
let low_w = w >> levels
let low_h = h >> levels
for y in 0..<h {
for x in 0..<w {
// 保留低频区域
if x < low_w && y < low_h {
continue
}
let idx = y * w + x
let c = coeffs[idx]
if soft {
// 软阈值
if c > threshold {
coeffs[idx] = c - threshold
} else if c < -threshold {
coeffs[idx] = c + threshold
} else {
coeffs[idx] = 0.0F
}
// 硬阈值
} else if c.abs() < threshold {
coeffs[idx] = 0.0F
}
}
}
haar_inverse_transform_2d(result)
}