12_histogram.py

Download
python 317 lines 9.2 KB
  1"""
  212. ํžˆ์Šคํ† ๊ทธ๋žจ ๋ถ„์„
  3- calcHist (ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐ)
  4- equalizeHist (ํžˆ์Šคํ† ๊ทธ๋žจ ํ‰ํ™œํ™”)
  5- CLAHE (์ ์‘ํ˜• ํžˆ์Šคํ† ๊ทธ๋žจ ํ‰ํ™œํ™”)
  6- ํžˆ์Šคํ† ๊ทธ๋žจ ์—ญํˆฌ์˜
  7"""
  8
  9import cv2
 10import numpy as np
 11
 12
 13def create_low_contrast_image():
 14    """์ €๋Œ€๋น„ ์ด๋ฏธ์ง€ ์ƒ์„ฑ"""
 15    img = np.zeros((300, 400), dtype=np.uint8)
 16
 17    # ์ข์€ ๋ฒ”์œ„์˜ ๋ฐ๊ธฐ๊ฐ’๋งŒ ์‚ฌ์šฉ (100-150)
 18    img[:] = 120
 19
 20    # ๋„ํ˜• ๊ทธ๋ฆฌ๊ธฐ
 21    cv2.rectangle(img, (50, 50), (150, 150), 140, -1)
 22    cv2.circle(img, (300, 150), 60, 130, -1)
 23    cv2.putText(img, 'LOW', (150, 250), cv2.FONT_HERSHEY_SIMPLEX, 1.5, 150, 2)
 24
 25    return img
 26
 27
 28def create_color_image():
 29    """์ปฌ๋Ÿฌ ํ…Œ์ŠคํŠธ ์ด๋ฏธ์ง€"""
 30    img = np.zeros((300, 400, 3), dtype=np.uint8)
 31
 32    # ๋‹ค์–‘ํ•œ ์ƒ‰์ƒ ์˜์—ญ
 33    img[0:150, 0:200] = [200, 50, 50]      # ํŒŒ๋ž‘
 34    img[0:150, 200:400] = [50, 200, 50]    # ์ดˆ๋ก
 35    img[150:300, 0:200] = [50, 50, 200]    # ๋นจ๊ฐ•
 36    img[150:300, 200:400] = [200, 200, 50] # ์ฒญ๋ก
 37
 38    return img
 39
 40
 41def calc_histogram_demo():
 42    """ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐ ๋ฐ๋ชจ"""
 43    print("=" * 50)
 44    print("ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐ (calcHist)")
 45    print("=" * 50)
 46
 47    img = create_low_contrast_image()
 48
 49    # ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐ
 50    # images: ์ž…๋ ฅ ์ด๋ฏธ์ง€ ๋ฆฌ์ŠคํŠธ
 51    # channels: ์ฑ„๋„ ์ธ๋ฑ์Šค (๊ทธ๋ ˆ์ด: [0], BGR: [0], [1], [2])
 52    # mask: ๋งˆ์Šคํฌ (None = ์ „์ฒด)
 53    # histSize: ๋นˆ ๊ฐœ์ˆ˜ (๋ณดํ†ต 256)
 54    # ranges: ๊ฐ’ ๋ฒ”์œ„
 55
 56    hist = cv2.calcHist([img], [0], None, [256], [0, 256])
 57
 58    print(f"ํžˆ์Šคํ† ๊ทธ๋žจ shape: {hist.shape}")
 59    print(f"์ด ํ”ฝ์…€ ์ˆ˜: {hist.sum()}")
 60    print(f"์ตœ๋Œ€ ๋นˆ๋„ ๊ฐ’: {hist.max():.0f}")
 61    print(f"์ตœ๋Œ€ ๋นˆ๋„ ์œ„์น˜: {hist.argmax()}")
 62
 63    # ํžˆ์Šคํ† ๊ทธ๋žจ ์‹œ๊ฐํ™” (ํ…์ŠคํŠธ)
 64    print("\nํžˆ์Šคํ† ๊ทธ๋žจ ๋ถ„ํฌ (๊ฐ„๋žต):")
 65    for i in range(0, 256, 32):
 66        count = hist[i:i+32].sum()
 67        bar = '#' * int(count / 1000)
 68        print(f"  {i:3d}-{i+31:3d}: {bar} ({count:.0f})")
 69
 70    cv2.imwrite('histogram_input.jpg', img)
 71
 72    return hist
 73
 74
 75def histogram_color_demo():
 76    """์ปฌ๋Ÿฌ ํžˆ์Šคํ† ๊ทธ๋žจ ๋ฐ๋ชจ"""
 77    print("\n" + "=" * 50)
 78    print("์ปฌ๋Ÿฌ ํžˆ์Šคํ† ๊ทธ๋žจ")
 79    print("=" * 50)
 80
 81    img = create_color_image()
 82
 83    # BGR ๊ฐ ์ฑ„๋„ ํžˆ์Šคํ† ๊ทธ๋žจ
 84    colors = ('b', 'g', 'r')
 85
 86    for i, color in enumerate(colors):
 87        hist = cv2.calcHist([img], [i], None, [256], [0, 256])
 88        peak = hist.argmax()
 89        print(f"{color.upper()} ์ฑ„๋„: ์ตœ๋Œ€ ๋นˆ๋„ ์œ„์น˜={peak}, ๊ฐ’={hist[peak][0]:.0f}")
 90
 91    cv2.imwrite('histogram_color.jpg', img)
 92
 93
 94def equalize_histogram_demo():
 95    """ํžˆ์Šคํ† ๊ทธ๋žจ ํ‰ํ™œํ™” ๋ฐ๋ชจ"""
 96    print("\n" + "=" * 50)
 97    print("ํžˆ์Šคํ† ๊ทธ๋žจ ํ‰ํ™œํ™” (equalizeHist)")
 98    print("=" * 50)
 99
100    img = create_low_contrast_image()
101
102    # ํžˆ์Šคํ† ๊ทธ๋žจ ํ‰ํ™œํ™”
103    equalized = cv2.equalizeHist(img)
104
105    # ์ „ํ›„ ํ†ต๊ณ„ ๋น„๊ต
106    print("ํ‰ํ™œํ™” ์ „:")
107    print(f"  Min={img.min()}, Max={img.max()}")
108    print(f"  Mean={img.mean():.1f}, Std={img.std():.1f}")
109
110    print("\nํ‰ํ™œํ™” ํ›„:")
111    print(f"  Min={equalized.min()}, Max={equalized.max()}")
112    print(f"  Mean={equalized.mean():.1f}, Std={equalized.std():.1f}")
113
114    print("\nํ‰ํ™œํ™” ํšจ๊ณผ:")
115    print("  - ๋ช…์•” ๋Œ€๋น„ ํ–ฅ์ƒ")
116    print("  - ํžˆ์Šคํ† ๊ทธ๋žจ์ด ๊ท ์ผํ•˜๊ฒŒ ๋ถ„ํฌ")
117    print("  - ์ „์ฒด ์ด๋ฏธ์ง€์— ๋™์ผํ•˜๊ฒŒ ์ ์šฉ")
118
119    cv2.imwrite('equalize_before.jpg', img)
120    cv2.imwrite('equalize_after.jpg', equalized)
121
122
123def clahe_demo():
124    """CLAHE ๋ฐ๋ชจ"""
125    print("\n" + "=" * 50)
126    print("CLAHE (Contrast Limited Adaptive Histogram Equalization)")
127    print("=" * 50)
128
129    img = create_low_contrast_image()
130
131    # ์ผ๋ฐ˜ ํ‰ํ™œํ™”
132    equalized = cv2.equalizeHist(img)
133
134    # CLAHE
135    # clipLimit: ๋Œ€๋น„ ์ œํ•œ (๋†’์„์ˆ˜๋ก ๋Œ€๋น„ ๊ฐ•ํ•จ)
136    # tileGridSize: ํƒ€์ผ ํฌ๊ธฐ
137
138    clahe1 = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
139    clahe2 = cv2.createCLAHE(clipLimit=4.0, tileGridSize=(8, 8))
140    clahe3 = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(16, 16))
141
142    result1 = clahe1.apply(img)
143    result2 = clahe2.apply(img)
144    result3 = clahe3.apply(img)
145
146    print("CLAHE vs ์ผ๋ฐ˜ ํ‰ํ™œํ™”:")
147    print("  - CLAHE: ์ง€์—ญ์ ์œผ๋กœ ์ ์šฉ (ํƒ€์ผ ๋‹จ์œ„)")
148    print("  - ๋…ธ์ด์ฆˆ ์ฆํญ ๋ฐฉ์ง€ (clipLimit)")
149    print("  - ๋ถˆ๊ท ์ผ ์กฐ๋ช…์— ํšจ๊ณผ์ ")
150
151    print("\nCLAHE ํŒŒ๋ผ๋ฏธํ„ฐ:")
152    print("  clipLimit: ๋Œ€๋น„ ์ œํ•œ (2.0~4.0 ๊ถŒ์žฅ)")
153    print("  tileGridSize: ํƒ€์ผ ํฌ๊ธฐ (8x8 ๊ถŒ์žฅ)")
154
155    cv2.imwrite('clahe_equalized.jpg', equalized)
156    cv2.imwrite('clahe_2_8.jpg', result1)
157    cv2.imwrite('clahe_4_8.jpg', result2)
158    cv2.imwrite('clahe_2_16.jpg', result3)
159
160
161def clahe_color_demo():
162    """์ปฌ๋Ÿฌ ์ด๋ฏธ์ง€ CLAHE ๋ฐ๋ชจ"""
163    print("\n" + "=" * 50)
164    print("์ปฌ๋Ÿฌ ์ด๋ฏธ์ง€ CLAHE")
165    print("=" * 50)
166
167    img = create_color_image()
168
169    # LAB ์ƒ‰์ƒ ๊ณต๊ฐ„์œผ๋กœ ๋ณ€ํ™˜
170    lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
171    l, a, b = cv2.split(lab)
172
173    # L ์ฑ„๋„์—๋งŒ CLAHE ์ ์šฉ
174    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
175    l_clahe = clahe.apply(l)
176
177    # ๋‹ค์‹œ ๋ณ‘ํ•ฉ
178    lab_clahe = cv2.merge([l_clahe, a, b])
179    result = cv2.cvtColor(lab_clahe, cv2.COLOR_LAB2BGR)
180
181    print("์ปฌ๋Ÿฌ ์ด๋ฏธ์ง€ CLAHE ๋ฐฉ๋ฒ•:")
182    print("  1. BGR โ†’ LAB ๋ณ€ํ™˜")
183    print("  2. L ์ฑ„๋„์— CLAHE ์ ์šฉ")
184    print("  3. LAB โ†’ BGR ๋ณ€ํ™˜")
185    print("  (์ƒ‰์ƒ(a,b)์€ ์œ ์ง€, ๋ฐ๊ธฐ(L)๋งŒ ์กฐ์ •)")
186
187    cv2.imwrite('clahe_color_before.jpg', img)
188    cv2.imwrite('clahe_color_after.jpg', result)
189
190
191def histogram_comparison_demo():
192    """ํžˆ์Šคํ† ๊ทธ๋žจ ๋น„๊ต ๋ฐ๋ชจ"""
193    print("\n" + "=" * 50)
194    print("ํžˆ์Šคํ† ๊ทธ๋žจ ๋น„๊ต (compareHist)")
195    print("=" * 50)
196
197    # ๋น„๊ตํ•  ์ด๋ฏธ์ง€๋“ค ์ƒ์„ฑ
198    img1 = np.zeros((100, 100), dtype=np.uint8)
199    img1[:] = 100
200    cv2.rectangle(img1, (20, 20), (80, 80), 150, -1)
201
202    img2 = img1.copy()  # ๋™์ผ
203
204    img3 = np.zeros((100, 100), dtype=np.uint8)
205    img3[:] = 50
206    cv2.rectangle(img3, (20, 20), (80, 80), 200, -1)
207
208    # ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐ
209    hist1 = cv2.calcHist([img1], [0], None, [256], [0, 256])
210    hist2 = cv2.calcHist([img2], [0], None, [256], [0, 256])
211    hist3 = cv2.calcHist([img3], [0], None, [256], [0, 256])
212
213    # ์ •๊ทœํ™”
214    cv2.normalize(hist1, hist1, 0, 1, cv2.NORM_MINMAX)
215    cv2.normalize(hist2, hist2, 0, 1, cv2.NORM_MINMAX)
216    cv2.normalize(hist3, hist3, 0, 1, cv2.NORM_MINMAX)
217
218    # ๋น„๊ต ๋ฐฉ๋ฒ•
219    methods = [
220        (cv2.HISTCMP_CORREL, 'Correlation'),
221        (cv2.HISTCMP_CHISQR, 'Chi-Square'),
222        (cv2.HISTCMP_INTERSECT, 'Intersection'),
223        (cv2.HISTCMP_BHATTACHARYYA, 'Bhattacharyya'),
224    ]
225
226    print("img1 vs img2 (๋™์ผ), img1 vs img3 (๋‹ค๋ฆ„):\n")
227
228    for method, name in methods:
229        score12 = cv2.compareHist(hist1, hist2, method)
230        score13 = cv2.compareHist(hist1, hist3, method)
231        print(f"  {name:15}: ๋™์ผ={score12:.4f}, ๋‹ค๋ฆ„={score13:.4f}")
232
233    print("\n๋น„๊ต ๋ฐฉ๋ฒ• ํ•ด์„:")
234    print("  Correlation: 1์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์œ ์‚ฌ")
235    print("  Chi-Square: 0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์œ ์‚ฌ")
236    print("  Intersection: ํด์ˆ˜๋ก ์œ ์‚ฌ")
237    print("  Bhattacharyya: 0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์œ ์‚ฌ")
238
239
240def back_projection_demo():
241    """ํžˆ์Šคํ† ๊ทธ๋žจ ์—ญํˆฌ์˜ ๋ฐ๋ชจ"""
242    print("\n" + "=" * 50)
243    print("ํžˆ์Šคํ† ๊ทธ๋žจ ์—ญํˆฌ์˜ (Back Projection)")
244    print("=" * 50)
245
246    # ๋Œ€์ƒ ์ด๋ฏธ์ง€ (๋‹ค์–‘ํ•œ ์ƒ‰์ƒ)
247    target = np.zeros((300, 400, 3), dtype=np.uint8)
248    target[:] = [100, 100, 100]  # ํšŒ์ƒ‰ ๋ฐฐ๊ฒฝ
249
250    # ๋นจ๊ฐ„ ๋ฌผ์ฒด๋“ค
251    cv2.circle(target, (100, 100), 40, (50, 50, 200), -1)
252    cv2.circle(target, (300, 200), 50, (30, 30, 180), -1)
253    cv2.rectangle(target, (150, 200), (220, 280), (40, 40, 210), -1)
254
255    # ํŒŒ๋ž€ ๋ฌผ์ฒด
256    cv2.circle(target, (350, 100), 30, (200, 50, 50), -1)
257
258    # ROI (๋นจ๊ฐ„์ƒ‰ ์ƒ˜ํ”Œ)
259    roi = target[60:140, 60:140]  # ๋นจ๊ฐ„ ์› ์˜์—ญ
260
261    # HSV ๋ณ€ํ™˜
262    hsv_target = cv2.cvtColor(target, cv2.COLOR_BGR2HSV)
263    hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
264
265    # ROI ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐ (Hue, Saturation๋งŒ)
266    roi_hist = cv2.calcHist([hsv_roi], [0, 1], None, [180, 256], [0, 180, 0, 256])
267    cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)
268
269    # ์—ญํˆฌ์˜
270    back_proj = cv2.calcBackProject([hsv_target], [0, 1], roi_hist, [0, 180, 0, 256], 1)
271
272    # ๊ฒฐ๊ณผ ๊ฐœ์„  (ํ˜•ํƒœํ•™์  ์—ฐ์‚ฐ)
273    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
274    cv2.filter2D(back_proj, -1, kernel, back_proj)
275    _, thresh = cv2.threshold(back_proj, 50, 255, cv2.THRESH_BINARY)
276
277    print("์—ญํˆฌ์˜ ๊ณผ์ •:")
278    print("  1. ROI์˜ ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐ")
279    print("  2. ๋Œ€์ƒ ์ด๋ฏธ์ง€์˜ ๊ฐ ํ”ฝ์…€์ด ROI์™€ ์–ผ๋งˆ๋‚˜ ์œ ์‚ฌํ•œ์ง€ ๊ณ„์‚ฐ")
280    print("  3. ์œ ์‚ฌํ•œ ์ƒ‰์ƒ ์˜์—ญ์ด ๋ฐ๊ฒŒ ํ‘œ์‹œ๋จ")
281    print("  4. ๊ฐ์ฒด ์ถ”์ ์— ํ™œ์šฉ (MeanShift, CamShift)")
282
283    cv2.imwrite('backproj_target.jpg', target)
284    cv2.imwrite('backproj_roi.jpg', roi)
285    cv2.imwrite('backproj_result.jpg', back_proj)
286    cv2.imwrite('backproj_thresh.jpg', thresh)
287
288
289def main():
290    """๋ฉ”์ธ ํ•จ์ˆ˜"""
291    # ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐ
292    calc_histogram_demo()
293
294    # ์ปฌ๋Ÿฌ ํžˆ์Šคํ† ๊ทธ๋žจ
295    histogram_color_demo()
296
297    # ํžˆ์Šคํ† ๊ทธ๋žจ ํ‰ํ™œํ™”
298    equalize_histogram_demo()
299
300    # CLAHE
301    clahe_demo()
302
303    # ์ปฌ๋Ÿฌ CLAHE
304    clahe_color_demo()
305
306    # ํžˆ์Šคํ† ๊ทธ๋žจ ๋น„๊ต
307    histogram_comparison_demo()
308
309    # ์—ญํˆฌ์˜
310    back_projection_demo()
311
312    print("\nํžˆ์Šคํ† ๊ทธ๋žจ ๋ถ„์„ ๋ฐ๋ชจ ์™„๋ฃŒ!")
313
314
315if __name__ == '__main__':
316    main()