1"""
206. ๋ชจํด๋ก์ง ์ฐ์ฐ
3- ์นจ์ (erode), ํฝ์ฐฝ (dilate)
4- ์ด๊ธฐ (opening), ๋ซ๊ธฐ (closing)
5- ๊ทธ๋๋์ธํธ, ํํ, ๋ธ๋ํ
6- ๊ตฌ์กฐ ์์ (structuring element)
7"""
8
9import cv2
10import numpy as np
11
12
13def create_binary_image():
14 """์ด์ง ์ด๋ฏธ์ง ์์ฑ"""
15 img = np.zeros((300, 400), dtype=np.uint8)
16
17 # ์ฌ๊ฐํ
18 cv2.rectangle(img, (50, 50), (150, 150), 255, -1)
19
20 # ์
21 cv2.circle(img, (300, 150), 50, 255, -1)
22
23 # ํ
์คํธ
24 cv2.putText(img, 'MORPH', (100, 250), cv2.FONT_HERSHEY_SIMPLEX, 1.5, 255, 3)
25
26 return img
27
28
29def create_noisy_binary():
30 """๋
ธ์ด์ฆ๊ฐ ์๋ ์ด์ง ์ด๋ฏธ์ง"""
31 img = create_binary_image()
32
33 # ์์ ๋
ธ์ด์ฆ ์ ์ถ๊ฐ (์๊ธ-ํ์ถ)
34 noise_salt = np.random.random(img.shape) < 0.01
35 noise_pepper = np.random.random(img.shape) < 0.01
36 img[noise_salt] = 255
37 img[noise_pepper] = 0
38
39 return img
40
41
42def structuring_element_demo():
43 """๊ตฌ์กฐ ์์ ๋ฐ๋ชจ"""
44 print("=" * 50)
45 print("๊ตฌ์กฐ ์์ (Structuring Element)")
46 print("=" * 50)
47
48 # ์ฌ๊ฐํ ๊ตฌ์กฐ ์์
49 rect_3x3 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
50 rect_5x5 = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
51
52 # ์ญ์ํ ๊ตฌ์กฐ ์์
53 cross_3x3 = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
54 cross_5x5 = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
55
56 # ํ์ํ ๊ตฌ์กฐ ์์
57 ellipse_5x5 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
58
59 print("์ฌ๊ฐํ 3x3:")
60 print(rect_3x3)
61 print("\n์ญ์ํ 3x3:")
62 print(cross_3x3)
63 print("\nํ์ํ 5x5:")
64 print(ellipse_5x5)
65
66 return rect_5x5
67
68
69def erosion_demo():
70 """์นจ์ (Erosion) ๋ฐ๋ชจ"""
71 print("\n" + "=" * 50)
72 print("์นจ์ (Erosion)")
73 print("=" * 50)
74
75 img = create_binary_image()
76 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
77
78 # ์นจ์ ์ ์ฉ
79 eroded_1 = cv2.erode(img, kernel, iterations=1)
80 eroded_2 = cv2.erode(img, kernel, iterations=2)
81 eroded_3 = cv2.erode(img, kernel, iterations=3)
82
83 print("์นจ์ ํน์ฑ:")
84 print(" - ์ ๊ฒฝ(ํฐ์) ์์ญ ์ถ์")
85 print(" - ์์ ๋
ธ์ด์ฆ ์ ๊ฑฐ")
86 print(" - iterations ์ฆ๊ฐ โ ๋ ๋ง์ด ์ถ์")
87
88 cv2.imwrite('morph_original.jpg', img)
89 cv2.imwrite('erode_1.jpg', eroded_1)
90 cv2.imwrite('erode_2.jpg', eroded_2)
91 cv2.imwrite('erode_3.jpg', eroded_3)
92
93
94def dilation_demo():
95 """ํฝ์ฐฝ (Dilation) ๋ฐ๋ชจ"""
96 print("\n" + "=" * 50)
97 print("ํฝ์ฐฝ (Dilation)")
98 print("=" * 50)
99
100 img = create_binary_image()
101 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
102
103 # ํฝ์ฐฝ ์ ์ฉ
104 dilated_1 = cv2.dilate(img, kernel, iterations=1)
105 dilated_2 = cv2.dilate(img, kernel, iterations=2)
106 dilated_3 = cv2.dilate(img, kernel, iterations=3)
107
108 print("ํฝ์ฐฝ ํน์ฑ:")
109 print(" - ์ ๊ฒฝ(ํฐ์) ์์ญ ํ๋")
110 print(" - ๊ตฌ๋ฉ ๋ฉ์ฐ๊ธฐ")
111 print(" - ๊ฐ์ฒด ์ฐ๊ฒฐ")
112
113 cv2.imwrite('dilate_1.jpg', dilated_1)
114 cv2.imwrite('dilate_2.jpg', dilated_2)
115 cv2.imwrite('dilate_3.jpg', dilated_3)
116
117
118def opening_demo():
119 """์ด๊ธฐ (Opening) ๋ฐ๋ชจ"""
120 print("\n" + "=" * 50)
121 print("์ด๊ธฐ (Opening) = ์นจ์ + ํฝ์ฐฝ")
122 print("=" * 50)
123
124 img = create_noisy_binary()
125 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
126
127 # ์ด๊ธฐ = ์นจ์ ํ ํฝ์ฐฝ
128 opened = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
129
130 # ์๋์ผ๋ก๋ ๊ฐ๋ฅ
131 opened_manual = cv2.dilate(cv2.erode(img, kernel), kernel)
132
133 print("์ด๊ธฐ ํน์ฑ:")
134 print(" - ์นจ์ ํ ํฝ์ฐฝ")
135 print(" - ์์ ๋
ธ์ด์ฆ(ํฐ์ ์ ) ์ ๊ฑฐ")
136 print(" - ๊ฐ์ฒด ํฌ๊ธฐ๋ ๊ฑฐ์ ์ ์ง")
137
138 cv2.imwrite('noisy_binary.jpg', img)
139 cv2.imwrite('opened.jpg', opened)
140
141
142def closing_demo():
143 """๋ซ๊ธฐ (Closing) ๋ฐ๋ชจ"""
144 print("\n" + "=" * 50)
145 print("๋ซ๊ธฐ (Closing) = ํฝ์ฐฝ + ์นจ์")
146 print("=" * 50)
147
148 img = create_noisy_binary()
149 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
150
151 # ๋ซ๊ธฐ = ํฝ์ฐฝ ํ ์นจ์
152 closed = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
153
154 print("๋ซ๊ธฐ ํน์ฑ:")
155 print(" - ํฝ์ฐฝ ํ ์นจ์")
156 print(" - ์์ ๊ตฌ๋ฉ(๊ฒ์ ์ ) ์ฑ์ฐ๊ธฐ")
157 print(" - ๊ฐ์ฒด ํฌ๊ธฐ๋ ๊ฑฐ์ ์ ์ง")
158
159 cv2.imwrite('closed.jpg', closed)
160
161
162def gradient_demo():
163 """๋ชจํด๋ก์ง ๊ทธ๋๋์ธํธ ๋ฐ๋ชจ"""
164 print("\n" + "=" * 50)
165 print("๋ชจํด๋ก์ง ๊ทธ๋๋์ธํธ")
166 print("=" * 50)
167
168 img = create_binary_image()
169 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
170
171 # ๊ทธ๋๋์ธํธ = ํฝ์ฐฝ - ์นจ์
172 gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
173
174 # ์๋ ๊ณ์ฐ
175 dilated = cv2.dilate(img, kernel)
176 eroded = cv2.erode(img, kernel)
177 gradient_manual = cv2.subtract(dilated, eroded)
178
179 print("๊ทธ๋๋์ธํธ ํน์ฑ:")
180 print(" - ํฝ์ฐฝ - ์นจ์")
181 print(" - ๊ฐ์ฒด์ ์ธ๊ณฝ์ ์ถ์ถ")
182
183 cv2.imwrite('gradient.jpg', gradient)
184
185
186def tophat_blackhat_demo():
187 """ํํ, ๋ธ๋ํ ๋ฐ๋ชจ"""
188 print("\n" + "=" * 50)
189 print("ํํ & ๋ธ๋ํ")
190 print("=" * 50)
191
192 # ๋ถ๊ท ์ผํ ์กฐ๋ช
์ ์ด๋ฏธ์ง ์๋ฎฌ๋ ์ด์
193 img = np.zeros((300, 400), dtype=np.uint8)
194
195 # ๊ทธ๋ผ๋ฐ์ด์
๋ฐฐ๊ฒฝ (๋ถ๊ท ์ผ ์กฐ๋ช
)
196 for i in range(300):
197 for j in range(400):
198 img[i, j] = int(50 + 100 * (i / 300) + 50 * (j / 400))
199
200 # ๋ฐ์ ๊ฐ์ฒด
201 cv2.rectangle(img, (100, 100), (150, 150), 255, -1)
202 cv2.circle(img, (300, 150), 30, 255, -1)
203
204 # ์ด๋์ด ๊ฐ์ฒด
205 cv2.rectangle(img, (50, 200), (100, 250), 30, -1)
206
207 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 21))
208
209 # ํํ = ์๋ณธ - ์ด๊ธฐ (๋ฐ์ ์์ญ ๊ฐ์กฐ)
210 tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
211
212 # ๋ธ๋ํ = ๋ซ๊ธฐ - ์๋ณธ (์ด๋์ด ์์ญ ๊ฐ์กฐ)
213 blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
214
215 print("ํํ:")
216 print(" - ์๋ณธ - ์ด๊ธฐ")
217 print(" - ๋ฐฐ๊ฒฝ๋ณด๋ค ๋ฐ์ ์์ญ ๊ฐ์กฐ")
218 print(" - ๋ถ๊ท ์ผ ์กฐ๋ช
๋ณด์ ์ ํ์ฉ")
219
220 print("\n๋ธ๋ํ:")
221 print(" - ๋ซ๊ธฐ - ์๋ณธ")
222 print(" - ๋ฐฐ๊ฒฝ๋ณด๋ค ์ด๋์ด ์์ญ ๊ฐ์กฐ")
223
224 cv2.imwrite('uneven_lighting.jpg', img)
225 cv2.imwrite('tophat.jpg', tophat)
226 cv2.imwrite('blackhat.jpg', blackhat)
227
228
229def hit_miss_demo():
230 """ํํธ๋ฏธ์ค ๋ณํ ๋ฐ๋ชจ"""
231 print("\n" + "=" * 50)
232 print("ํํธ๋ฏธ์ค ๋ณํ (Hit-Miss)")
233 print("=" * 50)
234
235 # ํน์ ํจํด ์ฐพ๊ธฐ
236 img = np.zeros((200, 200), dtype=np.uint8)
237 # L์ ๋ชจ์ ํจํด ์์ฑ
238 cv2.rectangle(img, (50, 50), (70, 100), 255, -1)
239 cv2.rectangle(img, (50, 80), (100, 100), 255, -1)
240
241 # ๋ค๋ฅธ ์์น์๋
242 cv2.rectangle(img, (120, 120), (140, 170), 255, -1)
243 cv2.rectangle(img, (120, 150), (170, 170), 255, -1)
244
245 # ํํธ๋ฏธ์ค ์ปค๋ (L์ ๋ชจ์๋ฆฌ ์ฐพ๊ธฐ)
246 kernel = np.array([
247 [0, 1, 0],
248 [1, 1, 0],
249 [0, 0, 0]
250 ], dtype=np.int8)
251
252 # ํํธ๋ฏธ์ค ๋ณํ
253 hitmiss = cv2.morphologyEx(img, cv2.MORPH_HITMISS, kernel)
254
255 print("ํํธ๋ฏธ์ค ๋ณํ:")
256 print(" - ํน์ ํจํด ์ฐพ๊ธฐ")
257 print(" - 1: ์ ๊ฒฝ, 0: ๋ฐฐ๊ฒฝ, -1: ๋ฌด๊ด")
258
259 cv2.imwrite('hitmiss_input.jpg', img)
260 cv2.imwrite('hitmiss_result.jpg', hitmiss)
261
262
263def practical_example():
264 """์ค์ฉ ์์ : ํ
์คํธ ์ ๋ฆฌ"""
265 print("\n" + "=" * 50)
266 print("์ค์ฉ ์์ : ํ
์คํธ ์ ๋ฆฌ")
267 print("=" * 50)
268
269 # ๋
ธ์ด์ฆ ์๋ ํ
์คํธ ์ด๋ฏธ์ง ์์ฑ
270 img = np.zeros((100, 400), dtype=np.uint8)
271 cv2.putText(img, 'OpenCV', (50, 70), cv2.FONT_HERSHEY_SIMPLEX, 2, 255, 2)
272
273 # ๋
ธ์ด์ฆ ์ถ๊ฐ
274 noise = np.random.random(img.shape) < 0.05
275 img[noise] = 255
276
277 # ์ด๊ธฐ๋ก ๋
ธ์ด์ฆ ์ ๊ฑฐ
278 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
279 cleaned = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
280
281 # ๋ซ๊ธฐ๋ก ๊ธ์ ๋ณด์
282 kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
283 enhanced = cv2.morphologyEx(cleaned, cv2.MORPH_CLOSE, kernel2)
284
285 cv2.imwrite('text_noisy.jpg', img)
286 cv2.imwrite('text_cleaned.jpg', cleaned)
287 cv2.imwrite('text_enhanced.jpg', enhanced)
288 print("ํ
์คํธ ์ ๋ฆฌ ์ด๋ฏธ์ง ์ ์ฅ ์๋ฃ")
289
290
291def main():
292 """๋ฉ์ธ ํจ์"""
293 # ๊ตฌ์กฐ ์์
294 structuring_element_demo()
295
296 # ์นจ์
297 erosion_demo()
298
299 # ํฝ์ฐฝ
300 dilation_demo()
301
302 # ์ด๊ธฐ
303 opening_demo()
304
305 # ๋ซ๊ธฐ
306 closing_demo()
307
308 # ๊ทธ๋๋์ธํธ
309 gradient_demo()
310
311 # ํํ/๋ธ๋ํ
312 tophat_blackhat_demo()
313
314 # ํํธ๋ฏธ์ค
315 hit_miss_demo()
316
317 # ์ค์ฉ ์์
318 practical_example()
319
320 print("\n๋ชจํด๋ก์ง ์ฐ์ฐ ๋ฐ๋ชจ ์๋ฃ!")
321
322
323if __name__ == '__main__':
324 main()