Skip to content

Commit aacb701

Browse files
committed
frequency_filter
1 parent 115e5bd commit aacb701

File tree

2 files changed

+168
-49
lines changed

2 files changed

+168
-49
lines changed

CV.ipynb

Lines changed: 40 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"from filter import *\n",
1919
"from geometric_transform import *\n",
2020
"from region_growing import *\n",
21-
"from edge_detection import *\n"
21+
"from edge_detection import *\n",
22+
"from dft import *\n"
2223
]
2324
},
2425
{
@@ -99,6 +100,14 @@
99100
" processed_image = sobel_sharpen(image)\n",
100101
" elif sub_option == 'Laplacian算子':\n",
101102
" processed_image = laplacian_sharpen(image)\n",
103+
"\n",
104+
" elif method == '图像分割':\n",
105+
" processed_image = region_growing(image, seed_point=(400, 100) , threshold=8)\n",
106+
"\n",
107+
" elif method == '频域滤波':\n",
108+
" processed_image = frequency_filter(image, sub_option)\n",
109+
" \n",
110+
" \n",
102111
" \n",
103112
" return processed_image"
104113
]
@@ -111,7 +120,7 @@
111120
{
112121
"data": {
113122
"application/vnd.jupyter.widget-view+json": {
114-
"model_id": "00032151954b42fb828aa2790db5c373",
123+
"model_id": "4d6c6bf9fd1a4f3598e6b825cb3d8e79",
115124
"version_major": 2,
116125
"version_minor": 0
117126
},
@@ -125,12 +134,12 @@
125134
{
126135
"data": {
127136
"application/vnd.jupyter.widget-view+json": {
128-
"model_id": "47be5d2ca16447f5a3154705cf9953bc",
137+
"model_id": "6474644e0a12414b82a83da934ed6083",
129138
"version_major": 2,
130139
"version_minor": 0
131140
},
132141
"text/plain": [
133-
"Dropdown(description='处理方法:', options=('灰度化', '二值化', '滤波', '锐化', '几何变换', '图像分割', '边缘检测'), value='灰度化')"
142+
"Dropdown(description='处理方法:', options=('灰度化', '二值化', '滤波', '锐化', '几何变换', '图像分割', '边缘检测', '频域滤波'), value='灰度化')"
134143
]
135144
},
136145
"metadata": {},
@@ -139,7 +148,7 @@
139148
{
140149
"data": {
141150
"application/vnd.jupyter.widget-view+json": {
142-
"model_id": "a3e24b211b5447e990ec1f0c29488356",
151+
"model_id": "5bf6822fc8b04386a972a853c84efbbf",
143152
"version_major": 2,
144153
"version_minor": 0
145154
},
@@ -153,7 +162,7 @@
153162
{
154163
"data": {
155164
"application/vnd.jupyter.widget-view+json": {
156-
"model_id": "bb77475af8a543bdbd0c0f2a2ba901fc",
165+
"model_id": "efcecbb0d851489d84443616f17e215d",
157166
"version_major": 2,
158167
"version_minor": 0
159168
},
@@ -167,12 +176,12 @@
167176
{
168177
"data": {
169178
"application/vnd.jupyter.widget-view+json": {
170-
"model_id": "79d8b080ad62405dace7d9e894bacb4f",
179+
"model_id": "d265ad29c3264622b8171a6f11b8f524",
171180
"version_major": 2,
172181
"version_minor": 0
173182
},
174183
"text/plain": [
175-
"HBox(children=(IntSlider(value=5, description='Kernel Size:', layout=Layout(visibility='visible'), max=15, min…"
184+
"HBox(children=(IntSlider(value=5, description='Kernel Size:', layout=Layout(visibility='hidden'), max=15, min="
176185
]
177186
},
178187
"metadata": {},
@@ -181,7 +190,7 @@
181190
{
182191
"data": {
183192
"application/vnd.jupyter.widget-view+json": {
184-
"model_id": "dd64688a4b574476953c293a34e86734",
193+
"model_id": "2d2cdd9bf06f4d39832329fff88a755b",
185194
"version_major": 2,
186195
"version_minor": 0
187196
},
@@ -195,7 +204,7 @@
195204
{
196205
"data": {
197206
"application/vnd.jupyter.widget-view+json": {
198-
"model_id": "6a61d2487aa447db8868502d1f6eb9f8",
207+
"model_id": "c2832dbb2fa345feb2869736a9b65ace",
199208
"version_major": 2,
200209
"version_minor": 0
201210
},
@@ -209,7 +218,7 @@
209218
{
210219
"data": {
211220
"application/vnd.jupyter.widget-view+json": {
212-
"model_id": "e09dc55a769a4019b05cd8f251db0e0d",
221+
"model_id": "4b3de52f7b4c4a99a5de86544574cbf9",
213222
"version_major": 2,
214223
"version_minor": 0
215224
},
@@ -223,7 +232,7 @@
223232
{
224233
"data": {
225234
"application/vnd.jupyter.widget-view+json": {
226-
"model_id": "44d023f03b964e488d8e2079de5f512d",
235+
"model_id": "0ac2dc72a40b4490ad9e1c4a5244d20b",
227236
"version_major": 2,
228237
"version_minor": 0
229238
},
@@ -244,7 +253,7 @@
244253
"\n",
245254
"# 方法选择下拉菜单\n",
246255
"method_dropdown = widgets.Dropdown(\n",
247-
" options=['灰度化', '二值化', '滤波', '锐化', '几何变换', '图像分割', '边缘检测'], \n",
256+
" options=['灰度化', '二值化', '滤波', '锐化', '几何变换', '图像分割', '边缘检测', '频域滤波'], \n",
248257
" value='灰度化',\n",
249258
" description='处理方法:'\n",
250259
")\n",
@@ -312,9 +321,6 @@
312321
" flip_direction = geometry_params.children[4].value\n",
313322
" processed_image = flip(image, flip_direction)\n",
314323
" \n",
315-
" elif method_dropdown.value == '图像分割':\n",
316-
" processed_image = region_growing(image, seed_point=(400, 100) , threshold=8)\n",
317-
" \n",
318324
" elif method_dropdown.value == '边缘检测':\n",
319325
" edge_method = edge_detection_params.children[0].value\n",
320326
" if edge_method == 'Sobel算子':\n",
@@ -325,7 +331,7 @@
325331
" low_threshold = edge_detection_params.children[1].value\n",
326332
" high_threshold = edge_detection_params.children[2].value\n",
327333
" processed_image = canny_edge_detection(image, low_threshold, high_threshold)\n",
328-
"\n",
334+
" \n",
329335
" else:\n",
330336
" processed_image = process_image(image, method_dropdown.value, sub_option_dropdown.value)\n",
331337
" \n",
@@ -343,28 +349,23 @@
343349
"\n",
344350
"# 方法改变事件处理\n",
345351
"def on_method_change(change):\n",
352+
" threshold_slider.layout.visibility = 'hidden'\n",
353+
" filter_params.layout.visibility = 'hidden'\n",
354+
" geometry_params.layout.visibility = 'hidden'\n",
355+
" edge_detection_params.layout.visibility = 'hidden'\n",
356+
"\n",
346357
" if change['new'] == '灰度化':\n",
347358
" sub_option_dropdown.options = ['灰度化', '灰度直方图修正', '线性变换', '对数变换', '指数变换']\n",
348-
" threshold_slider.layout.visibility = 'hidden'\n",
349-
" filter_params.layout.visibility = 'hidden'\n",
350-
" geometry_params.layout.visibility = 'hidden'\n",
351-
" edge_detection_params.layout.visibility = 'hidden'\n",
352359
"\n",
353360
" elif change['new'] == '二值化':\n",
354361
" sub_option_dropdown.options = ['固定阈值分割', '自适应均值阈值分割', '自适应高斯阈值分割', 'Otsu自动计算阈值分割']\n",
355-
" filter_params.layout.visibility = 'hidden'\n",
356-
" geometry_params.layout.visibility = 'hidden'\n",
357-
" edge_detection_params.layout.visibility = 'hidden'\n",
358362
" if sub_option_dropdown.value == '固定阈值分割':\n",
359363
" threshold_slider.layout.visibility = 'visible'\n",
360364
" else:\n",
361365
" threshold_slider.layout.visibility = 'hidden'\n",
362366
"\n",
363367
" elif change['new'] == '滤波':\n",
364368
" sub_option_dropdown.options = ['均值滤波', '高斯滤波', '中值滤波', '双边滤波']\n",
365-
" threshold_slider.layout.visibility = 'hidden'\n",
366-
" geometry_params.layout.visibility = 'hidden'\n",
367-
" edge_detection_params.layout.visibility = 'hidden'\n",
368369
" filter_params.layout.visibility = 'visible'\n",
369370
"\n",
370371
" if sub_option_dropdown.value in ['均值滤波', '高斯滤波']:\n",
@@ -388,18 +389,11 @@
388389
" \n",
389390
" elif change['new'] == '锐化':\n",
390391
" sub_option_dropdown.options = ['Sobel算子', 'Laplacian算子']\n",
391-
" threshold_slider.layout.visibility = 'hidden'\n",
392-
" filter_params.layout.visibility = 'hidden'\n",
393-
" geometry_params.layout.visibility = 'hidden'\n",
394-
" edge_detection_params.layout.visibility = 'hidden'\n",
395392
"\n",
396393
" elif change['new'] == '几何变换':\n",
397394
" sub_option_dropdown.options = ['平移', '旋转', '错切', '缩放', '翻转']\n",
398-
" threshold_slider.layout.visibility = 'hidden'\n",
399-
" filter_params.layout.visibility = 'hidden'\n",
400395
" geometry_params.layout.visibility = 'visible'\n",
401-
" edge_detection_params.layout.visibility = 'hidden'\n",
402-
" \n",
396+
"\n",
403397
" # 初始化几何变换参数控件的可见性\n",
404398
" for param in geometry_params.children:\n",
405399
" param.layout.visibility = 'hidden'\n",
@@ -416,31 +410,31 @@
416410
" \n",
417411
" elif change['new'] == '图像分割':\n",
418412
" sub_option_dropdown.options = ['区域生长']\n",
419-
" threshold_slider.layout.visibility = 'hidden'\n",
420-
" filter_params.layout.visibility = 'hidden'\n",
421-
" geometry_params.layout.visibility = 'hidden'\n",
422-
" edge_detection_params.layout.visibility = 'hidden'\n",
423413
"\n",
424414
" elif change['new'] == '边缘检测':\n",
425415
" sub_option_dropdown.options = ['Sobel算子', 'Laplacian算子', 'Canny算子']\n",
426-
" threshold_slider.layout.visibility = 'hidden'\n",
427-
" filter_params.layout.visibility = 'hidden'\n",
428-
" geometry_params.layout.visibility = 'hidden'\n",
429416
" edge_detection_params.layout.visibility = 'visible'\n",
430417
"\n",
418+
" elif change['new'] == '频域滤波':\n",
419+
" sub_option_dropdown.options = ['低通滤波', '高通滤波', '带阻(陷波)滤波']\n",
420+
" \n",
431421
"method_dropdown.observe(on_method_change, names='value')\n",
432422
"\n",
433423
"# 子选项改变事件处理\n",
434424
"def on_sub_option_change(change):\n",
425+
" filter_params.layout.visibility = 'hidden'\n",
426+
" geometry_params.layout.visibility = 'hidden'\n",
427+
" threshold_slider.layout.visibility = 'hidden'\n",
428+
" edge_detection_params.layout.visibility = 'hidden'\n",
429+
"\n",
435430
" if method_dropdown.value == '二值化':\n",
436-
" filter_params.layout.visibility = 'hidden'\n",
437-
" geometry_params.layout.visibility = 'hidden'\n",
438431
" if change['new'] == '固定阈值分割':\n",
439432
" threshold_slider.layout.visibility = 'visible'\n",
440433
" else:\n",
441434
" threshold_slider.layout.visibility = 'hidden'\n",
442435
"\n",
443436
" elif method_dropdown.value == '滤波':\n",
437+
" filter_params.layout.visibility = 'visible'\n",
444438
" if change['new'] in ['均值滤波', '高斯滤波']:\n",
445439
" filter_params.children[0].layout.visibility = 'visible' # Kernel Size\n",
446440
" filter_params.children[1].layout.visibility = 'visible' if change['new'] == '高斯滤波' else 'hidden' # Sigma X\n",
@@ -461,6 +455,7 @@
461455
" filter_params.children[4].layout.visibility = 'hidden' # Sigma Space\n",
462456
"\n",
463457
" elif method_dropdown.value == '几何变换':\n",
458+
" geometry_params.layout.visibility = 'visible'\n",
464459
" for param in geometry_params.children:\n",
465460
" param.layout.visibility = 'hidden'\n",
466461
" if change['new'] == '平移':\n",
@@ -474,14 +469,10 @@
474469
" geometry_params.children[4].layout.visibility = 'visible' # Flip Direction\n",
475470
"\n",
476471
" elif method_dropdown.value == '边缘检测':\n",
472+
" edge_detection_params.layout.visibility = 'visible'\n",
477473
" edge_detection_params.children[1].layout.visibility = 'visible' if change['new'] == 'Canny算子' else 'hidden'\n",
478474
" edge_detection_params.children[2].layout.visibility = 'visible' if change['new'] == 'Canny算子' else 'hidden'\n",
479475
"\n",
480-
" else:\n",
481-
" filter_params.layout.visibility = 'hidden'\n",
482-
" geometry_params.layout.visibility = 'hidden'\n",
483-
" threshold_slider.layout.visibility = 'hidden'\n",
484-
"\n",
485476
"sub_option_dropdown.observe(on_sub_option_change, names='value')\n",
486477
"\n",
487478
"# 显示控件\n",

dft.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import numpy as np
2+
import cv2 as cv
3+
import matplotlib.pyplot as plt
4+
5+
# 低通滤波
6+
def apply_low_pass_filter(image, cutoff_frequency):
7+
# 获取图像的高度和宽度
8+
rows, cols = image.shape
9+
crow, ccol = rows // 2, cols // 2
10+
11+
# 创建一个与图像大小相同的掩码
12+
mask = np.zeros((rows, cols, 2), np.uint8)
13+
14+
# 在中心区域创建一个圆形掩码
15+
r = int(cutoff_frequency)
16+
x, y = np.ogrid[:rows, :cols]
17+
mask_area = (x - crow) ** 2 + (y - ccol) ** 2 <= r * r
18+
mask[mask_area] = 1
19+
20+
# 进行傅里叶变换
21+
f_transform = cv.dft(image, flags=cv.DFT_COMPLEX_OUTPUT)
22+
f_transform_shifted = np.fft.fftshift(f_transform)
23+
24+
# 应用低通滤波器
25+
filtered_f_transform = f_transform_shifted * mask
26+
27+
# 进行逆傅里叶变换
28+
filtered_f_transform_ishift = np.fft.ifftshift(filtered_f_transform)
29+
filtered_image = cv.idft(filtered_f_transform_ishift)
30+
filtered_image = cv.magnitude(filtered_image[:, :, 0], filtered_image[:, :, 1])
31+
32+
return filtered_image
33+
34+
# 高通滤波
35+
def apply_high_pass_filter(image, cutoff_frequency):
36+
# 获取图像的高度和宽度
37+
rows, cols = image.shape
38+
crow, ccol = rows // 2, cols // 2
39+
40+
# 创建一个与图像大小相同的掩码
41+
mask = np.ones((rows, cols, 2), np.uint8)
42+
43+
# 在中心区域创建一个圆形掩码
44+
r = int(cutoff_frequency)
45+
x, y = np.ogrid[:rows, :cols]
46+
mask_area = (x - crow) ** 2 + (y - ccol) ** 2 <= r * r
47+
mask[mask_area] = 0
48+
49+
# 进行傅里叶变换
50+
f_transform = cv.dft(image, flags=cv.DFT_COMPLEX_OUTPUT)
51+
f_transform_shifted = np.fft.fftshift(f_transform)
52+
53+
# 应用高通滤波器
54+
filtered_f_transform = f_transform_shifted * mask
55+
56+
# 进行逆傅里叶变换
57+
filtered_f_transform_ishift = np.fft.ifftshift(filtered_f_transform)
58+
filtered_image = cv.idft(filtered_f_transform_ishift)
59+
filtered_image = cv.magnitude(filtered_image[:, :, 0], filtered_image[:, :, 1])
60+
61+
return filtered_image
62+
63+
# 带阻(陷波)滤波
64+
def apply_band_stop_filter(image, low_cutoff, high_cutoff):
65+
# 获取图像的高度和宽度
66+
rows, cols = image.shape
67+
crow, ccol = rows // 2, cols // 2
68+
69+
# 创建一个与图像大小相同的掩码
70+
mask = np.ones((rows, cols, 2), np.uint8)
71+
72+
# 在中心区域创建两个圆形掩码
73+
low_r = int(low_cutoff)
74+
high_r = int(high_cutoff)
75+
x, y = np.ogrid[:rows, :cols]
76+
low_mask_area = (x - crow) ** 2 + (y - ccol) ** 2 <= low_r * low_r
77+
high_mask_area = (x - crow) ** 2 + (y - ccol) ** 2 >= high_r * high_r
78+
mask[low_mask_area | high_mask_area] = 0
79+
80+
# 进行傅里叶变换
81+
f_transform = cv.dft(image, flags=cv.DFT_COMPLEX_OUTPUT)
82+
f_transform_shifted = np.fft.fftshift(f_transform)
83+
84+
# 应用带阻滤波器
85+
filtered_f_transform = f_transform_shifted * mask
86+
87+
# 进行逆傅里叶变换
88+
filtered_f_transform_ishift = np.fft.ifftshift(filtered_f_transform)
89+
filtered_image = cv.idft(filtered_f_transform_ishift)
90+
filtered_image = cv.magnitude(filtered_image[:, :, 0], filtered_image[:, :, 1])
91+
92+
return filtered_image
93+
94+
# 频率滤波
95+
def frequency_filter(image, sub_option):
96+
image_gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # 转换为灰度图像
97+
image_gray_float = np.float32(image_gray) # 转换为浮点数
98+
99+
# 傅里叶变换
100+
image_dft = cv.dft(image_gray_float, flags=cv.DFT_COMPLEX_OUTPUT)
101+
image_dft_shift = np.fft.fftshift(image_dft) # 中心化
102+
103+
# 计算幅值谱
104+
magnitude_spectrum = 20 * np.log(cv.magnitude(image_dft_shift[:, :, 0], image_dft_shift[:, :, 1]))
105+
106+
# 显示幅值谱
107+
plt.figure(figsize=(16, 8))
108+
plt.subplot(2, 4, 1)
109+
plt.imshow(magnitude_spectrum, cmap='gray')
110+
plt.title('Magnitude Spectrum')
111+
plt.xticks([]), plt.yticks([])
112+
113+
if sub_option == '低通滤波':
114+
cutoff_frequency_lp = 30
115+
filtered_img = apply_low_pass_filter(image_gray_float, cutoff_frequency_lp)
116+
117+
elif sub_option == '高通滤波':
118+
cutoff_frequency_hp = 30
119+
filtered_img = apply_high_pass_filter(image_gray_float, cutoff_frequency_hp)
120+
121+
elif sub_option == '带阻(陷波)滤波':
122+
low_cutoff_bs = 10
123+
high_cutoff_bs = 50
124+
filtered_img = apply_band_stop_filter(image_gray_float, low_cutoff_bs, high_cutoff_bs)
125+
126+
127+
return filtered_img
128+

0 commit comments

Comments
 (0)