11_hough_transform.py

Download
python 337 lines 9.8 KB
  1"""
  211. ํ—ˆํ”„ ๋ณ€ํ™˜
  3- HoughLines (ํ‘œ์ค€ ํ—ˆํ”„ ์ง์„ )
  4- HoughLinesP (ํ™•๋ฅ ์  ํ—ˆํ”„ ์ง์„ )
  5- HoughCircles (ํ—ˆํ”„ ์›)
  6"""
  7
  8import cv2
  9import numpy as np
 10
 11
 12def create_line_image():
 13    """์ง์„ ์ด ์žˆ๋Š” ํ…Œ์ŠคํŠธ ์ด๋ฏธ์ง€"""
 14    img = np.zeros((400, 500, 3), dtype=np.uint8)
 15    img[:] = [200, 200, 200]
 16
 17    # ๋‹ค์–‘ํ•œ ์ง์„ 
 18    cv2.line(img, (50, 50), (450, 50), (0, 0, 0), 2)      # ์ˆ˜ํ‰์„ 
 19    cv2.line(img, (50, 50), (50, 350), (0, 0, 0), 2)      # ์ˆ˜์ง์„ 
 20    cv2.line(img, (100, 100), (400, 300), (0, 0, 0), 2)   # ๋Œ€๊ฐ์„ 
 21    cv2.line(img, (100, 300), (400, 100), (0, 0, 0), 2)   # ๋Œ€๊ฐ์„ 
 22    cv2.line(img, (250, 150), (250, 350), (0, 0, 0), 2)   # ์ˆ˜์ง์„ 
 23
 24    return img
 25
 26
 27def create_circle_image():
 28    """์›์ด ์žˆ๋Š” ํ…Œ์ŠคํŠธ ์ด๋ฏธ์ง€"""
 29    img = np.zeros((400, 500, 3), dtype=np.uint8)
 30    img[:] = [200, 200, 200]
 31
 32    # ๋‹ค์–‘ํ•œ ์›
 33    cv2.circle(img, (100, 100), 40, (0, 0, 0), 2)
 34    cv2.circle(img, (300, 100), 50, (0, 0, 0), 2)
 35    cv2.circle(img, (150, 250), 60, (0, 0, 0), 2)
 36    cv2.circle(img, (350, 280), 45, (0, 0, 0), 2)
 37
 38    # ์ฑ„์›Œ์ง„ ์›
 39    cv2.circle(img, (450, 350), 30, (0, 0, 0), -1)
 40
 41    return img
 42
 43
 44def hough_lines_demo():
 45    """ํ‘œ์ค€ ํ—ˆํ”„ ์ง์„  ๋ณ€ํ™˜ ๋ฐ๋ชจ"""
 46    print("=" * 50)
 47    print("ํ‘œ์ค€ ํ—ˆํ”„ ์ง์„  ๋ณ€ํ™˜ (HoughLines)")
 48    print("=" * 50)
 49
 50    img = create_line_image()
 51    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 52
 53    # ์—ฃ์ง€ ๊ฒ€์ถœ
 54    edges = cv2.Canny(gray, 50, 150)
 55
 56    # ํ—ˆํ”„ ์ง์„  ๋ณ€ํ™˜
 57    # rho: ๊ฑฐ๋ฆฌ ํ•ด์ƒ๋„ (ํ”ฝ์…€)
 58    # theta: ๊ฐ๋„ ํ•ด์ƒ๋„ (๋ผ๋””์•ˆ)
 59    # threshold: ์ตœ์†Œ ํˆฌํ‘œ ์ˆ˜
 60    lines = cv2.HoughLines(edges, 1, np.pi/180, 100)
 61
 62    result = img.copy()
 63
 64    if lines is not None:
 65        print(f"๊ฒ€์ถœ๋œ ์ง์„  ์ˆ˜: {len(lines)}")
 66
 67        for line in lines:
 68            rho, theta = line[0]
 69
 70            # ๊ทน์ขŒํ‘œ โ†’ ์ง๊ต์ขŒํ‘œ ๋ณ€ํ™˜
 71            a = np.cos(theta)
 72            b = np.sin(theta)
 73            x0 = a * rho
 74            y0 = b * rho
 75
 76            # ์ง์„  ๊ทธ๋ฆฌ๊ธฐ (์ถฉ๋ถ„ํžˆ ๊ธด ์„ ๋ถ„)
 77            x1 = int(x0 + 1000 * (-b))
 78            y1 = int(y0 + 1000 * (a))
 79            x2 = int(x0 - 1000 * (-b))
 80            y2 = int(y0 - 1000 * (a))
 81
 82            cv2.line(result, (x1, y1), (x2, y2), (0, 0, 255), 2)
 83
 84    print("\nHoughLines ํŒŒ๋ผ๋ฏธํ„ฐ:")
 85    print("  rho: ๊ฑฐ๋ฆฌ ํ•ด์ƒ๋„ (๋ณดํ†ต 1 ํ”ฝ์…€)")
 86    print("  theta: ๊ฐ๋„ ํ•ด์ƒ๋„ (๋ณดํ†ต ฯ€/180)")
 87    print("  threshold: ์ง์„ ์œผ๋กœ ํŒ๋‹จํ•  ์ตœ์†Œ ํˆฌํ‘œ ์ˆ˜")
 88
 89    cv2.imwrite('hough_lines_input.jpg', img)
 90    cv2.imwrite('hough_lines_edges.jpg', edges)
 91    cv2.imwrite('hough_lines_result.jpg', result)
 92
 93
 94def hough_lines_p_demo():
 95    """ํ™•๋ฅ ์  ํ—ˆํ”„ ์ง์„  ๋ณ€ํ™˜ ๋ฐ๋ชจ"""
 96    print("\n" + "=" * 50)
 97    print("ํ™•๋ฅ ์  ํ—ˆํ”„ ์ง์„  ๋ณ€ํ™˜ (HoughLinesP)")
 98    print("=" * 50)
 99
100    img = create_line_image()
101    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
102    edges = cv2.Canny(gray, 50, 150)
103
104    # ํ™•๋ฅ ์  ํ—ˆํ”„ ๋ณ€ํ™˜
105    # minLineLength: ์ตœ์†Œ ์ง์„  ๊ธธ์ด
106    # maxLineGap: ์ง์„ ์œผ๋กœ ๊ฐ„์ฃผํ•  ์ตœ๋Œ€ ๊ฐ„๊ฒฉ
107    lines = cv2.HoughLinesP(edges, 1, np.pi/180, 50,
108                            minLineLength=50, maxLineGap=10)
109
110    result = img.copy()
111
112    if lines is not None:
113        print(f"๊ฒ€์ถœ๋œ ์„ ๋ถ„ ์ˆ˜: {len(lines)}")
114
115        for line in lines:
116            x1, y1, x2, y2 = line[0]
117            cv2.line(result, (x1, y1), (x2, y2), (0, 255, 0), 2)
118            cv2.circle(result, (x1, y1), 5, (255, 0, 0), -1)
119            cv2.circle(result, (x2, y2), 5, (0, 0, 255), -1)
120
121    print("\nHoughLinesP ์žฅ์ :")
122    print("  - ์„ ๋ถ„์˜ ์‹œ์ž‘์ , ๋์  ๋ฐ˜ํ™˜")
123    print("  - ํ‘œ์ค€ ๋ฐฉ๋ฒ•๋ณด๋‹ค ๋น ๋ฆ„")
124    print("  - ํŒŒ๋ผ๋ฏธํ„ฐ ์กฐ์ • ์šฉ์ด")
125
126    cv2.imwrite('hough_linesp_result.jpg', result)
127
128
129def hough_lines_params_demo():
130    """ํ—ˆํ”„ ์ง์„  ํŒŒ๋ผ๋ฏธํ„ฐ ์˜ํ–ฅ"""
131    print("\n" + "=" * 50)
132    print("ํ—ˆํ”„ ์ง์„  ํŒŒ๋ผ๋ฏธํ„ฐ ์˜ํ–ฅ")
133    print("=" * 50)
134
135    img = create_line_image()
136    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
137    edges = cv2.Canny(gray, 50, 150)
138
139    # ๋‹ค์–‘ํ•œ threshold ๊ฐ’
140    thresholds = [30, 50, 100, 150]
141
142    for thresh in thresholds:
143        lines = cv2.HoughLinesP(edges, 1, np.pi/180, thresh,
144                                minLineLength=30, maxLineGap=10)
145        result = img.copy()
146
147        if lines is not None:
148            for line in lines:
149                x1, y1, x2, y2 = line[0]
150                cv2.line(result, (x1, y1), (x2, y2), (0, 255, 0), 2)
151
152            print(f"threshold={thresh}: {len(lines)} ์„ ๋ถ„ ๊ฒ€์ถœ")
153
154        cv2.imwrite(f'hough_thresh_{thresh}.jpg', result)
155
156
157def hough_circles_demo():
158    """ํ—ˆํ”„ ์› ๋ณ€ํ™˜ ๋ฐ๋ชจ"""
159    print("\n" + "=" * 50)
160    print("ํ—ˆํ”„ ์› ๋ณ€ํ™˜ (HoughCircles)")
161    print("=" * 50)
162
163    img = create_circle_image()
164    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
165
166    # ๋ธ”๋Ÿฌ ์ ์šฉ (๋…ธ์ด์ฆˆ ๊ฐ์†Œ)
167    blurred = cv2.GaussianBlur(gray, (9, 9), 2)
168
169    # ํ—ˆํ”„ ์› ๋ณ€ํ™˜
170    # cv2.HOUGH_GRADIENT: ํ—ˆํ”„ ๊ทธ๋ž˜๋””์–ธํŠธ ๋ฐฉ๋ฒ•
171    # dp: ๋ˆ„์  ๋ฐฐ์—ด ํ•ด์ƒ๋„ ๋น„์œจ (1 = ์ž…๋ ฅ๊ณผ ๋™์ผ)
172    # minDist: ์› ์ค‘์‹ฌ ๊ฐ„ ์ตœ์†Œ ๊ฑฐ๋ฆฌ
173    # param1: Canny ์—ฃ์ง€ ๊ฒ€์ถœ ์ƒ์œ„ ์ž„๊ณ„๊ฐ’
174    # param2: ์› ๊ฒ€์ถœ ์ž„๊ณ„๊ฐ’ (๋‚ฎ์„์ˆ˜๋ก ๋” ๋งŽ์€ ์› ๊ฒ€์ถœ)
175    # minRadius, maxRadius: ์› ๋ฐ˜์ง€๋ฆ„ ๋ฒ”์œ„
176
177    circles = cv2.HoughCircles(
178        blurred,
179        cv2.HOUGH_GRADIENT,
180        dp=1,
181        minDist=50,
182        param1=100,
183        param2=30,
184        minRadius=20,
185        maxRadius=100
186    )
187
188    result = img.copy()
189
190    if circles is not None:
191        circles = np.uint16(np.around(circles))
192        print(f"๊ฒ€์ถœ๋œ ์› ์ˆ˜: {len(circles[0])}")
193
194        for circle in circles[0, :]:
195            cx, cy, r = circle
196
197            # ์› ๊ทธ๋ฆฌ๊ธฐ
198            cv2.circle(result, (cx, cy), r, (0, 255, 0), 2)
199            # ์ค‘์‹ฌ์  ํ‘œ์‹œ
200            cv2.circle(result, (cx, cy), 3, (0, 0, 255), -1)
201
202            print(f"  ์›: ์ค‘์‹ฌ=({cx}, {cy}), ๋ฐ˜์ง€๋ฆ„={r}")
203
204    print("\nHoughCircles ํŒŒ๋ผ๋ฏธํ„ฐ:")
205    print("  dp: ๋ˆ„์  ๋ฐฐ์—ด ํ•ด์ƒ๋„ (1 ๊ถŒ์žฅ)")
206    print("  minDist: ์› ์ค‘์‹ฌ ๊ฐ„ ์ตœ์†Œ ๊ฑฐ๋ฆฌ")
207    print("  param1: Canny ์ƒ์œ„ ์ž„๊ณ„๊ฐ’")
208    print("  param2: ์› ๊ฒ€์ถœ ์ž„๊ณ„๊ฐ’ (๋‚ฎ์œผ๋ฉด ๋งŽ์ด ๊ฒ€์ถœ)")
209    print("  minRadius/maxRadius: ๋ฐ˜์ง€๋ฆ„ ๋ฒ”์œ„")
210
211    cv2.imwrite('hough_circles_input.jpg', img)
212    cv2.imwrite('hough_circles_result.jpg', result)
213
214
215def hough_circles_params_demo():
216    """ํ—ˆํ”„ ์› ํŒŒ๋ผ๋ฏธํ„ฐ ์˜ํ–ฅ"""
217    print("\n" + "=" * 50)
218    print("ํ—ˆํ”„ ์› ํŒŒ๋ผ๋ฏธํ„ฐ ์˜ํ–ฅ")
219    print("=" * 50)
220
221    img = create_circle_image()
222    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
223    blurred = cv2.GaussianBlur(gray, (9, 9), 2)
224
225    # param2 ๊ฐ’ ๋ณ€ํ™”
226    param2_values = [20, 30, 40, 50]
227
228    for p2 in param2_values:
229        circles = cv2.HoughCircles(
230            blurred, cv2.HOUGH_GRADIENT, 1, 50,
231            param1=100, param2=p2, minRadius=20, maxRadius=100
232        )
233
234        result = img.copy()
235        count = 0
236
237        if circles is not None:
238            circles = np.uint16(np.around(circles))
239            count = len(circles[0])
240
241            for circle in circles[0, :]:
242                cx, cy, r = circle
243                cv2.circle(result, (cx, cy), r, (0, 255, 0), 2)
244                cv2.circle(result, (cx, cy), 3, (0, 0, 255), -1)
245
246        print(f"param2={p2}: {count} ์› ๊ฒ€์ถœ")
247        cv2.imwrite(f'hough_circles_p2_{p2}.jpg', result)
248
249
250def practical_lane_detection():
251    """์‹ค์šฉ ์˜ˆ์ œ: ์ฐจ์„  ๊ฒ€์ถœ ์‹œ๋ฎฌ๋ ˆ์ด์…˜"""
252    print("\n" + "=" * 50)
253    print("์‹ค์šฉ ์˜ˆ์ œ: ์ฐจ์„  ๊ฒ€์ถœ")
254    print("=" * 50)
255
256    # ๋„๋กœ ์ด๋ฏธ์ง€ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
257    img = np.zeros((400, 600, 3), dtype=np.uint8)
258    img[:] = [100, 100, 100]  # ํšŒ์ƒ‰ ๋„๋กœ
259
260    # ์ฐจ์„  ๊ทธ๋ฆฌ๊ธฐ
261    cv2.line(img, (100, 400), (250, 200), (255, 255, 255), 5)  # ์™ผ์ชฝ ์ฐจ์„ 
262    cv2.line(img, (500, 400), (350, 200), (255, 255, 255), 5)  # ์˜ค๋ฅธ์ชฝ ์ฐจ์„ 
263    cv2.line(img, (300, 400), (300, 250), (255, 255, 0), 3)    # ์ค‘์•™์„  (์ ์„  ์—ญํ• )
264
265    # ๊ทธ๋ ˆ์ด์Šค์ผ€์ผ ๋ฐ ์—ฃ์ง€
266    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
267    edges = cv2.Canny(gray, 50, 150)
268
269    # ROI (Region of Interest) ๋งˆ์Šคํฌ
270    mask = np.zeros_like(edges)
271    roi_vertices = np.array([[(50, 400), (550, 400), (350, 180), (250, 180)]], np.int32)
272    cv2.fillPoly(mask, roi_vertices, 255)
273    masked_edges = cv2.bitwise_and(edges, mask)
274
275    # ํ—ˆํ”„ ์ง์„  ๊ฒ€์ถœ
276    lines = cv2.HoughLinesP(masked_edges, 1, np.pi/180, 30,
277                            minLineLength=50, maxLineGap=100)
278
279    result = img.copy()
280
281    if lines is not None:
282        left_lines = []
283        right_lines = []
284
285        for line in lines:
286            x1, y1, x2, y2 = line[0]
287
288            # ๊ธฐ์šธ๊ธฐ ๊ณ„์‚ฐ
289            if x2 - x1 != 0:
290                slope = (y2 - y1) / (x2 - x1)
291
292                # ๊ธฐ์šธ๊ธฐ๋กœ ์ขŒ/์šฐ ์ฐจ์„  ๋ถ„๋ฅ˜
293                if slope < -0.3:  # ์™ผ์ชฝ ์ฐจ์„ 
294                    left_lines.append(line[0])
295                elif slope > 0.3:  # ์˜ค๋ฅธ์ชฝ ์ฐจ์„ 
296                    right_lines.append(line[0])
297
298        # ์ฐจ์„  ๊ทธ๋ฆฌ๊ธฐ
299        for line in left_lines:
300            cv2.line(result, (line[0], line[1]), (line[2], line[3]), (0, 255, 0), 3)
301        for line in right_lines:
302            cv2.line(result, (line[0], line[1]), (line[2], line[3]), (0, 0, 255), 3)
303
304        print(f"์™ผ์ชฝ ์ฐจ์„ : {len(left_lines)}, ์˜ค๋ฅธ์ชฝ ์ฐจ์„ : {len(right_lines)}")
305
306    cv2.imwrite('lane_input.jpg', img)
307    cv2.imwrite('lane_edges.jpg', masked_edges)
308    cv2.imwrite('lane_result.jpg', result)
309    print("์ฐจ์„  ๊ฒ€์ถœ ์ด๋ฏธ์ง€ ์ €์žฅ ์™„๋ฃŒ")
310
311
312def main():
313    """๋ฉ”์ธ ํ•จ์ˆ˜"""
314    # ํ‘œ์ค€ ํ—ˆํ”„ ์ง์„ 
315    hough_lines_demo()
316
317    # ํ™•๋ฅ ์  ํ—ˆํ”„ ์ง์„ 
318    hough_lines_p_demo()
319
320    # ์ง์„  ํŒŒ๋ผ๋ฏธํ„ฐ
321    hough_lines_params_demo()
322
323    # ํ—ˆํ”„ ์›
324    hough_circles_demo()
325
326    # ์› ํŒŒ๋ผ๋ฏธํ„ฐ
327    hough_circles_params_demo()
328
329    # ์‹ค์šฉ ์˜ˆ์ œ
330    practical_lane_detection()
331
332    print("\nํ—ˆํ”„ ๋ณ€ํ™˜ ๋ฐ๋ชจ ์™„๋ฃŒ!")
333
334
335if __name__ == '__main__':
336    main()