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()