• OpenCV“迷雾”车道识别的反思


    标题有些拗口,就这样吧。

    这个例子就是为了说明,算力离智能还有很远很远的距离。

    机器人迷雾之算力与智能_zhangrelay的博客-CSDN博客


    测试图片如下:

    车道图

    其中第一幅图是仿真案例:

    ROS2+Gazebo+OpenCV之mobot仿真视觉传感器_zhangrelay的博客-CSDN博客 

    在如上文章中提及。


    同时,可以参考:

     机器人方向的刚性需求→个人思考←_zhangrelay的博客-CSDN博客


    只有一个图可用,如下:

    一看效果太好了,可以上路测试啦。

    其实,换个图基本就不行了,但是人眼分辨所有测试图都是不会出错的。

    看个离谱的:

    妙不妙?

    更离谱的:

    慌不慌?

    疑问一:参数不合适。

    反问,人在不同城市开车或者走路的时候,会先调参数吗?

    疑问二:算法不够智能。

    反问,算法是计算方法,和智能有联系,但关联性参考:

    “机器人迷雾之算力与智能“

    疑问三,这种方式合适吗。

    思考:先抛开算法,仅仅考虑算力,类比一个人类指标智力。

    开车开的好的人,一定学历高吗?

    赛车手中,高学历一定成绩有优势吗……

    还是先回归常识,再搞算法,否则,事倍功半。

    目前,有会独立思考的机器人程序吗?或者真正意义上的智能体?


    附录

    测试算法如下(引用):

    1. import cv2 # Import the OpenCV library to enable computer vision
    2. import numpy as np # Import the NumPy scientific computing library
    3. import edge_detection as edge # Handles the detection of lane lines
    4. import matplotlib.pyplot as plt # Used for plotting and error checking
    5. # Author: Addison Sears-Collins
    6. # Description: Implementation of the Lane class
    7. # Make sure the video file is in the same directory as your code
    8. filename = 'orig_lane_detection_1.mp4'
    9. file_size = (1920,1080) # Assumes 1920x1080 mp4
    10. scale_ratio = 1 # Option to scale to fraction of original size.
    11. # We want to save the output to a video file
    12. output_filename = 'orig_lane_detection_1_lanes.mp4'
    13. output_frames_per_second = 20.0
    14. # Global variables
    15. prev_leftx = None
    16. prev_lefty = None
    17. prev_rightx = None
    18. prev_righty = None
    19. prev_left_fit = []
    20. prev_right_fit = []
    21. prev_leftx2 = None
    22. prev_lefty2 = None
    23. prev_rightx2 = None
    24. prev_righty2 = None
    25. prev_left_fit2 = []
    26. prev_right_fit2 = []
    27. class Lane:
    28. """
    29. Represents a lane on a road.
    30. """
    31. def __init__(self, orig_frame):
    32. """
    33. Default constructor
    34. :param orig_frame: Original camera image (i.e. frame)
    35. """
    36. self.orig_frame = orig_frame
    37. # This will hold an image with the lane lines
    38. self.lane_line_markings = None
    39. # This will hold the image after perspective transformation
    40. self.warped_frame = None
    41. self.transformation_matrix = None
    42. self.inv_transformation_matrix = None
    43. # (Width, Height) of the original video frame (or image)
    44. self.orig_image_size = self.orig_frame.shape[::-1][1:]
    45. width = self.orig_image_size[0]
    46. height = self.orig_image_size[1]
    47. self.width = width
    48. self.height = height
    49. # Four corners of the trapezoid-shaped region of interest
    50. # You need to find these corners manually.
    51. self.roi_points = np.float32([
    52. (int(0.456*width),int(0.544*height)), # Top-left corner
    53. (0, height-1), # Bottom-left corner
    54. (int(0.958*width),height-1), # Bottom-right corner
    55. (int(0.6183*width),int(0.544*height)) # Top-right corner
    56. ])
    57. # The desired corner locations of the region of interest
    58. # after we perform perspective transformation.
    59. # Assume image width of 600, padding == 150.
    60. self.padding = int(0.25 * width) # padding from side of the image in pixels
    61. self.desired_roi_points = np.float32([
    62. [self.padding, 0], # Top-left corner
    63. [self.padding, self.orig_image_size[1]], # Bottom-left corner
    64. [self.orig_image_size[
    65. 0]-self.padding, self.orig_image_size[1]], # Bottom-right corner
    66. [self.orig_image_size[0]-self.padding, 0] # Top-right corner
    67. ])
    68. # Histogram that shows the white pixel peaks for lane line detection
    69. self.histogram = None
    70. # Sliding window parameters
    71. self.no_of_windows = 10
    72. self.margin = int((1/12) * width) # Window width is +/- margin
    73. self.minpix = int((1/24) * width) # Min no. of pixels to recenter window
    74. # Best fit polynomial lines for left line and right line of the lane
    75. self.left_fit = None
    76. self.right_fit = None
    77. self.left_lane_inds = None
    78. self.right_lane_inds = None
    79. self.ploty = None
    80. self.left_fitx = None
    81. self.right_fitx = None
    82. self.leftx = None
    83. self.rightx = None
    84. self.lefty = None
    85. self.righty = None
    86. # Pixel parameters for x and y dimensions
    87. self.YM_PER_PIX = 7.0 / 400 # meters per pixel in y dimension
    88. self.XM_PER_PIX = 3.7 / 255 # meters per pixel in x dimension
    89. # Radii of curvature and offset
    90. self.left_curvem = None
    91. self.right_curvem = None
    92. self.center_offset = None
    93. def calculate_car_position(self, print_to_terminal=False):
    94. """
    95. Calculate the position of the car relative to the center
    96. :param: print_to_terminal Display data to console if True
    97. :return: Offset from the center of the lane
    98. """
    99. # Assume the camera is centered in the image.
    100. # Get position of car in centimeters
    101. car_location = self.orig_frame.shape[1] / 2
    102. # Fine the x coordinate of the lane line bottom
    103. height = self.orig_frame.shape[0]
    104. bottom_left = self.left_fit[0]*height**2 + self.left_fit[
    105. 1]*height + self.left_fit[2]
    106. bottom_right = self.right_fit[0]*height**2 + self.right_fit[
    107. 1]*height + self.right_fit[2]
    108. center_lane = (bottom_right - bottom_left)/2 + bottom_left
    109. center_offset = (np.abs(car_location) - np.abs(
    110. center_lane)) * self.XM_PER_PIX * 100
    111. if print_to_terminal == True:
    112. print(str(center_offset) + 'cm')
    113. self.center_offset = center_offset
    114. return center_offset
    115. def calculate_curvature(self, print_to_terminal=False):
    116. """
    117. Calculate the road curvature in meters.
    118. :param: print_to_terminal Display data to console if True
    119. :return: Radii of curvature
    120. """
    121. # Set the y-value where we want to calculate the road curvature.
    122. # Select the maximum y-value, which is the bottom of the frame.
    123. y_eval = np.max(self.ploty)
    124. # Fit polynomial curves to the real world environment
    125. left_fit_cr = np.polyfit(self.lefty * self.YM_PER_PIX, self.leftx * (
    126. self.XM_PER_PIX), 2)
    127. right_fit_cr = np.polyfit(self.righty * self.YM_PER_PIX, self.rightx * (
    128. self.XM_PER_PIX), 2)
    129. # Calculate the radii of curvature
    130. left_curvem = ((1 + (2*left_fit_cr[0]*y_eval*self.YM_PER_PIX + left_fit_cr[
    131. 1])**2)**1.5) / np.absolute(2*left_fit_cr[0])
    132. right_curvem = ((1 + (2*right_fit_cr[
    133. 0]*y_eval*self.YM_PER_PIX + right_fit_cr[
    134. 1])**2)**1.5) / np.absolute(2*right_fit_cr[0])
    135. # Display on terminal window
    136. if print_to_terminal == True:
    137. print(left_curvem, 'm', right_curvem, 'm')
    138. self.left_curvem = left_curvem
    139. self.right_curvem = right_curvem
    140. return left_curvem, right_curvem
    141. def calculate_histogram(self,frame=None,plot=True):
    142. """
    143. Calculate the image histogram to find peaks in white pixel count
    144. :param frame: The warped image
    145. :param plot: Create a plot if True
    146. """
    147. if frame is None:
    148. frame = self.warped_frame
    149. # Generate the histogram
    150. self.histogram = np.sum(frame[int(
    151. frame.shape[0]/2):,:], axis=0)
    152. if plot == True:
    153. # Draw both the image and the histogram
    154. figure, (ax1, ax2) = plt.subplots(2,1) # 2 row, 1 columns
    155. figure.set_size_inches(10, 5)
    156. ax1.imshow(frame, cmap='gray')
    157. ax1.set_title("Warped Binary Frame")
    158. ax2.plot(self.histogram)
    159. ax2.set_title("Histogram Peaks")
    160. plt.show()
    161. return self.histogram
    162. def display_curvature_offset(self, frame=None, plot=False):
    163. """
    164. Display curvature and offset statistics on the image
    165. :param: plot Display the plot if True
    166. :return: Image with lane lines and curvature
    167. """
    168. image_copy = None
    169. if frame is None:
    170. image_copy = self.orig_frame.copy()
    171. else:
    172. image_copy = frame
    173. cv2.putText(image_copy,'Curve Radius: '+str((
    174. self.left_curvem+self.right_curvem)/2)[:7]+' m', (int((
    175. 5/600)*self.width), int((
    176. 20/338)*self.height)), cv2.FONT_HERSHEY_SIMPLEX, (float((
    177. 0.5/600)*self.width)),(
    178. 255,255,255),2,cv2.LINE_AA)
    179. cv2.putText(image_copy,'Center Offset: '+str(
    180. self.center_offset)[:7]+' cm', (int((
    181. 5/600)*self.width), int((
    182. 40/338)*self.height)), cv2.FONT_HERSHEY_SIMPLEX, (float((
    183. 0.5/600)*self.width)),(
    184. 255,255,255),2,cv2.LINE_AA)
    185. if plot==True:
    186. cv2.imshow("Image with Curvature and Offset", image_copy)
    187. return image_copy
    188. def get_lane_line_previous_window(self, left_fit, right_fit, plot=False):
    189. """
    190. Use the lane line from the previous sliding window to get the parameters
    191. for the polynomial line for filling in the lane line
    192. :param: left_fit Polynomial function of the left lane line
    193. :param: right_fit Polynomial function of the right lane line
    194. :param: plot To display an image or not
    195. """
    196. # margin is a sliding window parameter
    197. margin = self.margin
    198. # Find the x and y coordinates of all the nonzero
    199. # (i.e. white) pixels in the frame.
    200. nonzero = self.warped_frame.nonzero()
    201. nonzeroy = np.array(nonzero[0])
    202. nonzerox = np.array(nonzero[1])
    203. # Store left and right lane pixel indices
    204. left_lane_inds = ((nonzerox > (left_fit[0]*(
    205. nonzeroy**2) + left_fit[1]*nonzeroy + left_fit[2] - margin)) & (
    206. nonzerox < (left_fit[0]*(
    207. nonzeroy**2) + left_fit[1]*nonzeroy + left_fit[2] + margin)))
    208. right_lane_inds = ((nonzerox > (right_fit[0]*(
    209. nonzeroy**2) + right_fit[1]*nonzeroy + right_fit[2] - margin)) & (
    210. nonzerox < (right_fit[0]*(
    211. nonzeroy**2) + right_fit[1]*nonzeroy + right_fit[2] + margin)))
    212. self.left_lane_inds = left_lane_inds
    213. self.right_lane_inds = right_lane_inds
    214. # Get the left and right lane line pixel locations
    215. leftx = nonzerox[left_lane_inds]
    216. lefty = nonzeroy[left_lane_inds]
    217. rightx = nonzerox[right_lane_inds]
    218. righty = nonzeroy[right_lane_inds]
    219. global prev_leftx2
    220. global prev_lefty2
    221. global prev_rightx2
    222. global prev_righty2
    223. global prev_left_fit2
    224. global prev_right_fit2
    225. # Make sure we have nonzero pixels
    226. if len(leftx)==0 or len(lefty)==0 or len(rightx)==0 or len(righty)==0:
    227. leftx = prev_leftx2
    228. lefty = prev_lefty2
    229. rightx = prev_rightx2
    230. righty = prev_righty2
    231. self.leftx = leftx
    232. self.rightx = rightx
    233. self.lefty = lefty
    234. self.righty = righty
    235. left_fit = np.polyfit(lefty, leftx, 2)
    236. right_fit = np.polyfit(righty, rightx, 2)
    237. # Add the latest polynomial coefficients
    238. prev_left_fit2.append(left_fit)
    239. prev_right_fit2.append(right_fit)
    240. # Calculate the moving average
    241. if len(prev_left_fit2) > 10:
    242. prev_left_fit2.pop(0)
    243. prev_right_fit2.pop(0)
    244. left_fit = sum(prev_left_fit2) / len(prev_left_fit2)
    245. right_fit = sum(prev_right_fit2) / len(prev_right_fit2)
    246. self.left_fit = left_fit
    247. self.right_fit = right_fit
    248. prev_leftx2 = leftx
    249. prev_lefty2 = lefty
    250. prev_rightx2 = rightx
    251. prev_righty2 = righty
    252. # Create the x and y values to plot on the image
    253. ploty = np.linspace(
    254. 0, self.warped_frame.shape[0]-1, self.warped_frame.shape[0])
    255. left_fitx = left_fit[0]*ploty**2 + left_fit[1]*ploty + left_fit[2]
    256. right_fitx = right_fit[0]*ploty**2 + right_fit[1]*ploty + right_fit[2]
    257. self.ploty = ploty
    258. self.left_fitx = left_fitx
    259. self.right_fitx = right_fitx
    260. if plot==True:
    261. # Generate images to draw on
    262. out_img = np.dstack((self.warped_frame, self.warped_frame, (
    263. self.warped_frame)))*255
    264. window_img = np.zeros_like(out_img)
    265. # Add color to the left and right line pixels
    266. out_img[nonzeroy[left_lane_inds], nonzerox[left_lane_inds]] = [255, 0, 0]
    267. out_img[nonzeroy[right_lane_inds], nonzerox[right_lane_inds]] = [
    268. 0, 0, 255]
    269. # Create a polygon to show the search window area, and recast
    270. # the x and y points into a usable format for cv2.fillPoly()
    271. margin = self.margin
    272. left_line_window1 = np.array([np.transpose(np.vstack([
    273. left_fitx-margin, ploty]))])
    274. left_line_window2 = np.array([np.flipud(np.transpose(np.vstack([
    275. left_fitx+margin, ploty])))])
    276. left_line_pts = np.hstack((left_line_window1, left_line_window2))
    277. right_line_window1 = np.array([np.transpose(np.vstack([
    278. right_fitx-margin, ploty]))])
    279. right_line_window2 = np.array([np.flipud(np.transpose(np.vstack([
    280. right_fitx+margin, ploty])))])
    281. right_line_pts = np.hstack((right_line_window1, right_line_window2))
    282. # Draw the lane onto the warped blank image
    283. cv2.fillPoly(window_img, np.int_([left_line_pts]), (0,255, 0))
    284. cv2.fillPoly(window_img, np.int_([right_line_pts]), (0,255, 0))
    285. result = cv2.addWeighted(out_img, 1, window_img, 0.3, 0)
    286. # Plot the figures
    287. figure, (ax1, ax2, ax3) = plt.subplots(3,1) # 3 rows, 1 column
    288. figure.set_size_inches(10, 10)
    289. figure.tight_layout(pad=3.0)
    290. ax1.imshow(cv2.cvtColor(self.orig_frame, cv2.COLOR_BGR2RGB))
    291. ax2.imshow(self.warped_frame, cmap='gray')
    292. ax3.imshow(result)
    293. ax3.plot(left_fitx, ploty, color='yellow')
    294. ax3.plot(right_fitx, ploty, color='yellow')
    295. ax1.set_title("Original Frame")
    296. ax2.set_title("Warped Frame")
    297. ax3.set_title("Warped Frame With Search Window")
    298. plt.show()
    299. def get_lane_line_indices_sliding_windows(self, plot=False):
    300. """
    301. Get the indices of the lane line pixels using the
    302. sliding windows technique.
    303. :param: plot Show plot or not
    304. :return: Best fit lines for the left and right lines of the current lane
    305. """
    306. # Sliding window width is +/- margin
    307. margin = self.margin
    308. frame_sliding_window = self.warped_frame.copy()
    309. # Set the height of the sliding windows
    310. window_height = np.int(self.warped_frame.shape[0]/self.no_of_windows)
    311. # Find the x and y coordinates of all the nonzero
    312. # (i.e. white) pixels in the frame.
    313. nonzero = self.warped_frame.nonzero()
    314. nonzeroy = np.array(nonzero[0])
    315. nonzerox = np.array(nonzero[1])
    316. # Store the pixel indices for the left and right lane lines
    317. left_lane_inds = []
    318. right_lane_inds = []
    319. # Current positions for pixel indices for each window,
    320. # which we will continue to update
    321. leftx_base, rightx_base = self.histogram_peak()
    322. leftx_current = leftx_base
    323. rightx_current = rightx_base
    324. # Go through one window at a time
    325. no_of_windows = self.no_of_windows
    326. for window in range(no_of_windows):
    327. # Identify window boundaries in x and y (and right and left)
    328. win_y_low = self.warped_frame.shape[0] - (window + 1) * window_height
    329. win_y_high = self.warped_frame.shape[0] - window * window_height
    330. win_xleft_low = leftx_current - margin
    331. win_xleft_high = leftx_current + margin
    332. win_xright_low = rightx_current - margin
    333. win_xright_high = rightx_current + margin
    334. cv2.rectangle(frame_sliding_window,(win_xleft_low,win_y_low),(
    335. win_xleft_high,win_y_high), (255,255,255), 2)
    336. cv2.rectangle(frame_sliding_window,(win_xright_low,win_y_low),(
    337. win_xright_high,win_y_high), (255,255,255), 2)
    338. # Identify the nonzero pixels in x and y within the window
    339. good_left_inds = ((nonzeroy >= win_y_low) & (nonzeroy < win_y_high) &
    340. (nonzerox >= win_xleft_low) & (
    341. nonzerox < win_xleft_high)).nonzero()[0]
    342. good_right_inds = ((nonzeroy >= win_y_low) & (nonzeroy < win_y_high) &
    343. (nonzerox >= win_xright_low) & (
    344. nonzerox < win_xright_high)).nonzero()[0]
    345. # Append these indices to the lists
    346. left_lane_inds.append(good_left_inds)
    347. right_lane_inds.append(good_right_inds)
    348. # If you found > minpix pixels, recenter next window on mean position
    349. minpix = self.minpix
    350. if len(good_left_inds) > minpix:
    351. leftx_current = np.int(np.mean(nonzerox[good_left_inds]))
    352. if len(good_right_inds) > minpix:
    353. rightx_current = np.int(np.mean(nonzerox[good_right_inds]))
    354. # Concatenate the arrays of indices
    355. left_lane_inds = np.concatenate(left_lane_inds)
    356. right_lane_inds = np.concatenate(right_lane_inds)
    357. # Extract the pixel coordinates for the left and right lane lines
    358. leftx = nonzerox[left_lane_inds]
    359. lefty = nonzeroy[left_lane_inds]
    360. rightx = nonzerox[right_lane_inds]
    361. righty = nonzeroy[right_lane_inds]
    362. # Fit a second order polynomial curve to the pixel coordinates for
    363. # the left and right lane lines
    364. left_fit = None
    365. right_fit = None
    366. global prev_leftx
    367. global prev_lefty
    368. global prev_rightx
    369. global prev_righty
    370. global prev_left_fit
    371. global prev_right_fit
    372. # Make sure we have nonzero pixels
    373. if len(leftx)==0 or len(lefty)==0 or len(rightx)==0 or len(righty)==0:
    374. leftx = prev_leftx
    375. lefty = prev_lefty
    376. rightx = prev_rightx
    377. righty = prev_righty
    378. left_fit = np.polyfit(lefty, leftx, 2)
    379. right_fit = np.polyfit(righty, rightx, 2)
    380. # Add the latest polynomial coefficients
    381. prev_left_fit.append(left_fit)
    382. prev_right_fit.append(right_fit)
    383. # Calculate the moving average
    384. if len(prev_left_fit) > 10:
    385. prev_left_fit.pop(0)
    386. prev_right_fit.pop(0)
    387. left_fit = sum(prev_left_fit) / len(prev_left_fit)
    388. right_fit = sum(prev_right_fit) / len(prev_right_fit)
    389. self.left_fit = left_fit
    390. self.right_fit = right_fit
    391. prev_leftx = leftx
    392. prev_lefty = lefty
    393. prev_rightx = rightx
    394. prev_righty = righty
    395. if plot==True:
    396. # Create the x and y values to plot on the image
    397. ploty = np.linspace(
    398. 0, frame_sliding_window.shape[0]-1, frame_sliding_window.shape[0])
    399. left_fitx = left_fit[0]*ploty**2 + left_fit[1]*ploty + left_fit[2]
    400. right_fitx = right_fit[0]*ploty**2 + right_fit[1]*ploty + right_fit[2]
    401. # Generate an image to visualize the result
    402. out_img = np.dstack((
    403. frame_sliding_window, frame_sliding_window, (
    404. frame_sliding_window))) * 255
    405. # Add color to the left line pixels and right line pixels
    406. out_img[nonzeroy[left_lane_inds], nonzerox[left_lane_inds]] = [255, 0, 0]
    407. out_img[nonzeroy[right_lane_inds], nonzerox[right_lane_inds]] = [
    408. 0, 0, 255]
    409. # Plot the figure with the sliding windows
    410. figure, (ax1, ax2, ax3) = plt.subplots(3,1) # 3 rows, 1 column
    411. figure.set_size_inches(10, 10)
    412. figure.tight_layout(pad=3.0)
    413. ax1.imshow(cv2.cvtColor(self.orig_frame, cv2.COLOR_BGR2RGB))
    414. ax2.imshow(frame_sliding_window, cmap='gray')
    415. ax3.imshow(out_img)
    416. ax3.plot(left_fitx, ploty, color='yellow')
    417. ax3.plot(right_fitx, ploty, color='yellow')
    418. ax1.set_title("Original Frame")
    419. ax2.set_title("Warped Frame with Sliding Windows")
    420. ax3.set_title("Detected Lane Lines with Sliding Windows")
    421. plt.show()
    422. return self.left_fit, self.right_fit
    423. def get_line_markings(self, frame=None):
    424. """
    425. Isolates lane lines.
    426. :param frame: The camera frame that contains the lanes we want to detect
    427. :return: Binary (i.e. black and white) image containing the lane lines.
    428. """
    429. if frame is None:
    430. frame = self.orig_frame
    431. # Convert the video frame from BGR (blue, green, red)
    432. # color space to HLS (hue, saturation, lightness).
    433. hls = cv2.cvtColor(frame, cv2.COLOR_BGR2HLS)
    434. ################### Isolate possible lane line edges ######################
    435. # Perform Sobel edge detection on the L (lightness) channel of
    436. # the image to detect sharp discontinuities in the pixel intensities
    437. # along the x and y axis of the video frame.
    438. # sxbinary is a matrix full of 0s (black) and 255 (white) intensity values
    439. # Relatively light pixels get made white. Dark pixels get made black.
    440. _, sxbinary = edge.threshold(hls[:, :, 1], thresh=(120, 255))
    441. sxbinary = edge.blur_gaussian(sxbinary, ksize=3) # Reduce noise
    442. # 1s will be in the cells with the highest Sobel derivative values
    443. # (i.e. strongest lane line edges)
    444. sxbinary = edge.mag_thresh(sxbinary, sobel_kernel=3, thresh=(110, 255))
    445. ######################## Isolate possible lane lines ######################
    446. # Perform binary thresholding on the S (saturation) channel
    447. # of the video frame. A high saturation value means the hue color is pure.
    448. # We expect lane lines to be nice, pure colors (i.e. solid white, yellow)
    449. # and have high saturation channel values.
    450. # s_binary is matrix full of 0s (black) and 255 (white) intensity values
    451. # White in the regions with the purest hue colors (e.g. >130...play with
    452. # this value for best results).
    453. s_channel = hls[:, :, 2] # use only the saturation channel data
    454. _, s_binary = edge.threshold(s_channel, (130, 255))
    455. # Perform binary thresholding on the R (red) channel of the
    456. # original BGR video frame.
    457. # r_thresh is a matrix full of 0s (black) and 255 (white) intensity values
    458. # White in the regions with the richest red channel values (e.g. >120).
    459. # Remember, pure white is bgr(255, 255, 255).
    460. # Pure yellow is bgr(0, 255, 255). Both have high red channel values.
    461. _, r_thresh = edge.threshold(frame[:, :, 2], thresh=(120, 255))
    462. # Lane lines should be pure in color and have high red channel values
    463. # Bitwise AND operation to reduce noise and black-out any pixels that
    464. # don't appear to be nice, pure, solid colors (like white or yellow lane
    465. # lines.)
    466. rs_binary = cv2.bitwise_and(s_binary, r_thresh)
    467. ### Combine the possible lane lines with the possible lane line edges #####
    468. # If you show rs_binary visually, you'll see that it is not that different
    469. # from this return value. The edges of lane lines are thin lines of pixels.
    470. self.lane_line_markings = cv2.bitwise_or(rs_binary, sxbinary.astype(
    471. np.uint8))
    472. return self.lane_line_markings
    473. def histogram_peak(self):
    474. """
    475. Get the left and right peak of the histogram
    476. Return the x coordinate of the left histogram peak and the right histogram
    477. peak.
    478. """
    479. midpoint = np.int(self.histogram.shape[0]/2)
    480. leftx_base = np.argmax(self.histogram[:midpoint])
    481. rightx_base = np.argmax(self.histogram[midpoint:]) + midpoint
    482. # (x coordinate of left peak, x coordinate of right peak)
    483. return leftx_base, rightx_base
    484. def overlay_lane_lines(self, plot=False):
    485. """
    486. Overlay lane lines on the original frame
    487. :param: Plot the lane lines if True
    488. :return: Lane with overlay
    489. """
    490. # Generate an image to draw the lane lines on
    491. warp_zero = np.zeros_like(self.warped_frame).astype(np.uint8)
    492. color_warp = np.dstack((warp_zero, warp_zero, warp_zero))
    493. # Recast the x and y points into usable format for cv2.fillPoly()
    494. pts_left = np.array([np.transpose(np.vstack([
    495. self.left_fitx, self.ploty]))])
    496. pts_right = np.array([np.flipud(np.transpose(np.vstack([
    497. self.right_fitx, self.ploty])))])
    498. pts = np.hstack((pts_left, pts_right))
    499. # Draw lane on the warped blank image
    500. cv2.fillPoly(color_warp, np.int_([pts]), (0,255, 0))
    501. # Warp the blank back to original image space using inverse perspective
    502. # matrix (Minv)
    503. newwarp = cv2.warpPerspective(color_warp, self.inv_transformation_matrix, (
    504. self.orig_frame.shape[
    505. 1], self.orig_frame.shape[0]))
    506. # Combine the result with the original image
    507. result = cv2.addWeighted(self.orig_frame, 1, newwarp, 0.3, 0)
    508. if plot==True:
    509. # Plot the figures
    510. figure, (ax1, ax2) = plt.subplots(2,1) # 2 rows, 1 column
    511. figure.set_size_inches(10, 10)
    512. figure.tight_layout(pad=3.0)
    513. ax1.imshow(cv2.cvtColor(self.orig_frame, cv2.COLOR_BGR2RGB))
    514. ax2.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
    515. ax1.set_title("Original Frame")
    516. ax2.set_title("Original Frame With Lane Overlay")
    517. plt.show()
    518. return result
    519. def perspective_transform(self, frame=None, plot=False):
    520. """
    521. Perform the perspective transform.
    522. :param: frame Current frame
    523. :param: plot Plot the warped image if True
    524. :return: Bird's eye view of the current lane
    525. """
    526. if frame is None:
    527. frame = self.lane_line_markings
    528. # Calculate the transformation matrix
    529. self.transformation_matrix = cv2.getPerspectiveTransform(
    530. self.roi_points, self.desired_roi_points)
    531. # Calculate the inverse transformation matrix
    532. self.inv_transformation_matrix = cv2.getPerspectiveTransform(
    533. self.desired_roi_points, self.roi_points)
    534. # Perform the transform using the transformation matrix
    535. self.warped_frame = cv2.warpPerspective(
    536. frame, self.transformation_matrix, self.orig_image_size, flags=(
    537. cv2.INTER_LINEAR))
    538. # Convert image to binary
    539. (thresh, binary_warped) = cv2.threshold(
    540. self.warped_frame, 127, 255, cv2.THRESH_BINARY)
    541. self.warped_frame = binary_warped
    542. # Display the perspective transformed (i.e. warped) frame
    543. if plot == True:
    544. warped_copy = self.warped_frame.copy()
    545. warped_plot = cv2.polylines(warped_copy, np.int32([
    546. self.desired_roi_points]), True, (147,20,255), 3)
    547. # Display the image
    548. while(1):
    549. cv2.imshow('Warped Image', warped_plot)
    550. # Press any key to stop
    551. if cv2.waitKey(0):
    552. break
    553. cv2.destroyAllWindows()
    554. return self.warped_frame
    555. def plot_roi(self, frame=None, plot=False):
    556. """
    557. Plot the region of interest on an image.
    558. :param: frame The current image frame
    559. :param: plot Plot the roi image if True
    560. """
    561. if plot == False:
    562. return
    563. if frame is None:
    564. frame = self.orig_frame.copy()
    565. # Overlay trapezoid on the frame
    566. this_image = cv2.polylines(frame, np.int32([
    567. self.roi_points]), True, (147,20,255), 3)
    568. # Display the image
    569. while(1):
    570. cv2.imshow('ROI Image', this_image)
    571. # Press any key to stop
    572. if cv2.waitKey(0):
    573. break
    574. cv2.destroyAllWindows()
    575. def main():
    576. # Load a video
    577. cap = cv2.VideoCapture(filename)
    578. # Create a VideoWriter object so we can save the video output
    579. fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    580. result = cv2.VideoWriter(output_filename,
    581. fourcc,
    582. output_frames_per_second,
    583. file_size)
    584. # Process the video
    585. while cap.isOpened():
    586. # Capture one frame at a time
    587. success, frame = cap.read()
    588. # Do we have a video frame? If true, proceed.
    589. if success:
    590. # Resize the frame
    591. width = int(frame.shape[1] * scale_ratio)
    592. height = int(frame.shape[0] * scale_ratio)
    593. frame = cv2.resize(frame, (width, height))
    594. # Store the original frame
    595. original_frame = frame.copy()
    596. # Create a Lane object
    597. lane_obj = Lane(orig_frame=original_frame)
    598. # Perform thresholding to isolate lane lines
    599. lane_line_markings = lane_obj.get_line_markings()
    600. # Plot the region of interest on the image
    601. lane_obj.plot_roi(plot=False)
    602. # Perform the perspective transform to generate a bird's eye view
    603. # If Plot == True, show image with new region of interest
    604. warped_frame = lane_obj.perspective_transform(plot=False)
    605. # Generate the image histogram to serve as a starting point
    606. # for finding lane line pixels
    607. histogram = lane_obj.calculate_histogram(plot=False)
    608. # Find lane line pixels using the sliding window method
    609. left_fit, right_fit = lane_obj.get_lane_line_indices_sliding_windows(
    610. plot=False)
    611. # Fill in the lane line
    612. lane_obj.get_lane_line_previous_window(left_fit, right_fit, plot=False)
    613. # Overlay lines on the original frame
    614. frame_with_lane_lines = lane_obj.overlay_lane_lines(plot=False)
    615. # Calculate lane line curvature (left and right lane lines)
    616. lane_obj.calculate_curvature(print_to_terminal=False)
    617. # Calculate center offset
    618. lane_obj.calculate_car_position(print_to_terminal=False)
    619. # Display curvature and center offset on image
    620. frame_with_lane_lines2 = lane_obj.display_curvature_offset(
    621. frame=frame_with_lane_lines, plot=False)
    622. # Write the frame to the output video file
    623. result.write(frame_with_lane_lines2)
    624. # Display the frame
    625. cv2.imshow("Frame", frame_with_lane_lines2)
    626. # Display frame for X milliseconds and check if q key is pressed
    627. # q == quit
    628. if cv2.waitKey(25) & 0xFF == ord('q'):
    629. break
    630. # No more video frames left
    631. else:
    632. break
    633. # Stop when the video is finished
    634. cap.release()
    635. # Release the video recording
    636. result.release()
    637. # Close all windows
    638. cv2.destroyAllWindows()
    639. main()


     

     

     

     

  • 相关阅读:
    SpringCloud(5):Ribbon详解
    (附源码)计算机毕业设计Java办公自动化管理系统
    CTF-php代码审计(MD5)
    html菜单的基本制作
    怎样才能批量查询网站的谷歌PR权重?把手教你批量查询网站谷歌PR权重值
    html里面的伪元素是什么?如何操作?
    计算机软件分类、编程知识体系、编程工作岗位
    OpenHarmony Meetup深圳站招募令
    Python 基础 (二)Python变量与基本数据类型
    【数据结构与算法】分治算法的介绍和汉诺塔程序实现
  • 原文地址:https://blog.csdn.net/ZhangRelay/article/details/125435368