06_morphology.py

Download
python 325 lines 8.5 KB
  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()