在本次分享中,我将以优达学城(udacity)无人驾驶工程师学位中提供的高级车道线检测项目为例,介绍普适性更好,且更为鲁棒的车道线检测技术,用于处理那些无人驾驶中常见的(如路面颜色变化、路边障碍物阴影等导致的)光线变化剧烈和弯道的场景。
	按照惯例,在介绍计算机视觉技术前,我们先讨论一下这次分享的输入和输出。
	输入
	一个连续的视频,视频中的左车道线为黄色实线,右车道线为白色虚线。无人车会经过路面颜色突变、路边树木影子干扰、车道线不清晰和急转弯的路况。
	输出
	左、右车道线的三次曲线方程,及其有效距离。最后将车道线围成的区域显示在图像上,如下图所示。
输入和输出都定义清楚后,我们开始探讨高级车道线检测的算法,并对每帧视频图像中的车道线进行检测。
	摄像机标定
	相信大家都多少听说过鱼眼相机,最常见的鱼眼相机是辅助驾驶员倒车的后向摄像头。也有很多摄影爱好者会使用鱼眼相机拍摄图像,最终会有高大上的大片效果,如下图所示。
图片来源:优达学城(udacity)无人驾驶工程师课程
	使用鱼眼相机拍摄的图像虽然高大上,但存在一个很大的问题——畸变(distortion)。如上图所示,走道上的栏杆应该是笔直延伸出去的。然而,栏杆在图像上的成像却是弯曲的,这就是图像畸变,畸变会导致图像失真。
	使用车载摄像机拍摄出的图像,虽然没有鱼眼相机的畸变这么夸张,但是畸变是客观存在的,只是人眼难以察觉。使用有畸变的图像做车道线的检测,检测结果的精度将会受到影响,因此进行图像处理的第一步工作就是去畸变。
	为了解决车载摄像机图像的畸变问题,摄像机标定技术应运而生。
	摄像机标定是通过对已知的形状进行拍照,通过计算该形状在真实世界中位置与在图像中位置的偏差量(畸变系数),进而用这个偏差量去修正其他畸变图像的技术。
	原则上,可以选用任何的已知形状去校准摄像机,不过业内的标定方法都是基于棋盘格的。因为它具备规则的、高对比度图案,能非常方便地自动化检测各个棋盘格的交点,十分适合标定摄像机的标定工作。如下图所示为标准的10x7(7行10列)的棋盘格。
opencv库为摄像机标定提供了函数cv2.findchessboardcorners(),它能自动地检测棋盘格内4个棋盘格的交点(2白2黑的交接点)。我们只需要输入摄像机拍摄的完整棋盘格图像和交点在横纵向上的数量即可。随后我们可以使用函数cv2.drawchessboardcorners()绘制出检测的结果。
	棋盘格原图如下所示:
图片出处:https://github.com/udacity/carnd-advanced-lane-lines/blob/master/camera_cal/calibration2.jpg
	使用opencv自动交点检测的结果如下:
获取交点的检测结果后,使用函数cv2.calibratecamera()即可得到相机的畸变系数。
	为了使摄像机标定得到的畸变系数更加准确,我们使用车载摄像机从不同的角度拍摄20张棋盘格,将所有的交点检测结果保存,再进行畸变系数的的计算。
	我们将读入图片、预处理图片、检测交点、标定相机的一系列操作,封装成一个函数,如下所示:
	# step 1 : calculate camera distortion coefficientsdef getcameracalibrationcoefficients(chessboardname, nx, ny):  # prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)  objp = np.zeros((ny * nx, 3), np.float32)  objp[:,:2] = np.mgrid[0:nx, 0:ny].t.reshape(-1,2)    # arrays to store object points and image points from all the images.  objpoints = [] # 3d points in real world space  imgpoints = [] # 2d points in image plane.    images = glob.glob(chessboardname)  if len(images) > 0:    print(images num for calibration : , len(images))  else:    print(no image for calibration.)    return    ret_count = 0  for idx, fname in enumerate(images):    img = cv2.imread(fname)    gray = cv2.cvtcolor(img, cv2.color_bgr2gray)    img_size = (img.shape[1], img.shape[0])    # finde the chessboard corners    ret, corners = cv2.findchessboardcorners(gray, (nx, ny), none)    # if found, add object points, image points    if ret == true:      ret_count += 1      objpoints.append(objp)      imgpoints.append(corners)        ret, mtx, dist, rvecs, tvecs = cv2.calibratecamera(objpoints, imgpoints, img_size, none, none)  print('do calibration successfully')  return ret, mtx, dist, rvecs, tvecs
	需要标定的一系列图片如下图所示:
图片出处:https://github.com/udacity/carnd-advanced-lane-lines/tree/master/camera_cal
	调用之前封装好的函数,获取畸变参数。
	nx = 9 ny = 6 ret, mtx, dist, rvecs, tvecs = getcameracalibrationcoefficients('camera_cal/calibration*.jpg', nx, ny)
	随后,使用opencv提供的函数cv2.undistort(),传入刚刚计算得到的畸变参数,即可将畸变的图像进行畸变修正处理。
	# step 2 : undistort image def undistortimage(distortimage, mtx, dist):  return cv2.undistort(distortimage, mtx, dist, none, mtx)
	以畸变的棋盘格图像为例,进行畸变修正处理
	# read distorted chessboard image test_distort_image = cv2.imread('./camera_cal/calibration4.jpg') # do undistortion test_undistort_image = undistortimage(test_distort_image, mtx, dist)
	畸变图像如下图所示:
图像出处:https://github.com/udacity/carnd-advanced-lane-lines/blob/master/camera_cal/calibration4.jpg
	复原后的图像如下图所示:
同理,我们将摄像机拍摄到的实际路况进行畸变修正处理。
	test_distort_image = cv2.imread('test_images/straight_lines1.jpg') # do undistortion test_undistort_image = undistortimage(test_distort_image, mtx, dist)
	原始畸变图像如下所示:
图片出处:https://github.com/udacity/carnd-advanced-lane-lines/blob/master/test_images/straight_lines1.jpg
	畸变修正后的图像如下所示:
可以看到离镜头更近的左侧、右侧和下侧的图像比远处的畸变修正更明显。
	筛选图像
	从我们作为输入的视频可以看出,车辆会经历颠簸、车道线不清晰、路面颜色突变,路边障碍物阴影干扰等复杂工况。因此,需要将这些复杂的场景筛选出来,确保后续的算法能够在这些复杂场景中正确地检测出车道线。
	使用以下代码将视频中的图像数据提取,进行畸变修正处理后,存储在名为original_image的文件夹中,以供挑选。
	video_input = 'project_video.mp4' cap = cv2.videocapture(video_input) count = 1 while(true):  ret, image = cap.read()  if ret:    undistort_image = undistortimage(image, mtx, dist)    cv2.imwrite('original_image/' + str(count) + '.jpg', undistort_image)    count += 1  else:    break cap.release()
	在original_image文件夹中,挑选出以下6个场景进行检测。这6个场景既包含了视频中常见的正常直道、正常弯道工况,也包含了具有挑战性的阴影、明暗剧烈变化的工况。如下图所示:
无阴影、颜色无明暗变换的直道
无阴影、颜色无明暗变换的弯道
有小面积阴影、颜色由暗到亮的直道
无阴影、道路标志线不清晰的弯道
有大面积阴影、颜色由暗到亮的弯道
有大面积阴影、颜色由亮到暗的弯道
	如果后续的高级车道线检测算法能够完美处理以上六种工况,那将算法应用到视频中,也会得到完美的车道线检测效果。
	透视变换
	在完成图像的畸变修正后,就要将注意力转移到车道线。与《无人驾驶技术入门(十四)| 初识图像之初级车道线检测》中技术类似,这里需要定义一个感兴趣区域。很显然,我们的感兴趣区域就是车辆正前方的这个车道。为了获取感兴趣区域,我们需要对自车正前方的道路使用一种叫做透视变换的技术。
	“透视”是图像成像时,物体距离摄像机越远,看起来越小的一种现象。在真实世界中,左右互相平行的车道线,会在图像的最远处交汇成一个点。这个现象就是“透视成像”的原理造成的。
	以立在路边的交通标志牌为例,它在摄像机所拍摄的图像中的成像结果一般如下下图所示:
图片来源:优达学城(udacity)无人驾驶工程师课程
	在这幅图像上,原本应该是正八边形的标志牌,成像成为一个不规则的八边形。
	通过使用透视变换技术,可以将不规则的八边形投影成规则的正八边形。应用透视变换后的结果对比如吐下:
图片来源:优达学城(udacity)无人驾驶工程师课程
	透视变换的原理:首先新建一幅跟左图同样大小的右图,随后在做图中选择标志牌位于两侧的四个点(如图中的红点),记录这4个点的坐标,我们称这4个点为src_points。图中的4个点组成的是一个平行四边形。
	由先验知识可知,左图中4个点所围成的平行四边形,在现实世界中是一个长方形,因此在右边的图中,选择一个合适的位置,选择一个长方形区域,这个长方形的4个端点一一对应着原图中的src_points,我们称新的这4个点为dst_points。
	得到src_points,dst_points后,我们就可以使用opencv中计算投影矩阵的函数cv2.getperspectivetransform(src_points, dst_points)算出src_points到dst_points的投影矩阵和投影变换后的图像了。
	使用opencv库实现透视变换的代码如下:
	# step 3 : warp image based on src_points and dst_points # the type of src_points & dst_points should be like # np.float32([ [0,0], [100,200], [200, 300], [300,400]]) def warpimage(image, src_points, dst_points):  image_size = (image.shape[1], image.shape[0])  # rows = img.shape[0] 720  # cols = img.shape[1] 1280  m = cv2.getperspectivetransform(src, dst)  minv = cv2.getperspectivetransform(dst, src)  warped_image = cv2.warpperspective(image, m,image_size, flags=cv2.inter_linear)    return warped_image, m, minv
	同理,对于畸变修正过的道路图像,我们同样使用相同的方法,将我们感兴趣的区域做透视变换。
	如下图所示,我们选用一张在直线道路上行驶的图像,沿着左右车道线的边缘,选择一个梯形区域,这个区域在真实的道路中应该是一个长方形,因此我们选择将这个梯形区域投影成为一个长方形,在右图横坐标的合适位置设置长方形的4个端点。最终的投影结果就像“鸟瞰图”一样。
图片出处:https://github.com/udacity/carnd-advanced-lane-lines/tree/master/examples/warped_straight_lines.jpg
	使用以下代码,通过不断调整src和dst的值,确保在直线道路上,能够调试出满意的透视变换图像。
	test_distort_image = cv2.imread('test_images/test4.jpg')# 畸变修正test_undistort_image = undistortimage(test_distort_image, mtx, dist)# 左图梯形区域的四个端点src = np.float32([[580, 460], [700, 460], [1096, 720], [200, 720]])# 右图矩形区域的四个端点dst = np.float32([[300, 0], [950, 0], [950, 720], [300, 720])test_warp_image, m, minv = warpimage(test_undistort_image, src, dst)
	最终,我们把筛选出的6幅图统一应用调整好的src、dst做透视变换,结果如下:
无阴影、颜色无明暗变换的直道
无阴影、颜色无明暗变换的弯道
有小面积阴影、颜色由暗到亮的直道
无阴影、道路标志线不清晰的弯道
有大面积阴影、颜色由暗到亮的弯道
有大面积阴影、颜色由亮到暗的弯道
	可以看到,越靠图片下方的图像越清晰,越上方的图像越模糊。这是因为越远的地方,左图中的像素点越少。而无论是远处还是近处,需要在右图中填充的像素点数量是一样的。左图近处有足够多的点去填充右图,而左图远处的点有限,只能通过插值的方式创造“假的”像素点进行填充,所以就不那么清晰了。
	提取车道线
	在《无人驾驶技术入门(十四)| 初识图像之初级车道线检测》中,我们介绍了通过canny边缘提取算法获取车道线待选点的方法,随后使用霍夫直线变换进行了车道线的检测。在这里,我们也尝试使用边缘提取的方法进行车道线提取。
	需要注意的是,canny边缘提取算法会将图像中各个方向、明暗交替位置的边缘都提取出来,很明显,canny边缘提取算法在处理有树木阴影的道路时,会将树木影子的轮廓也提取出来,这是我们不愿意看到的。
	因此我们选用sobel边缘提取算法。sobel相比于canny的优秀之处在于,它可以选择横向或纵向的边缘进行提取。从投影变换后的图像可以看出,我们关心的正是车道线在横向上的边缘突变。
	封装一下opencv提供的cv2.sobel()函数,将进行边缘提取后的图像做二进制图的转化,即提取到边缘的像素点显示为白色(值为1),未提取到边缘的像素点显示为黑色(值为0)。
	def abssobelthreshold(img, orient='x', thresh_min=30, thresh_max=100):  # convert to grayscale  gray = cv2.cvtcolor(img, cv2.color_rgb2gray)  # apply x or y gradient with the opencv sobel() function  # and take the absolute value  if orient == 'x':    abs_sobel = np.absolute(cv2.sobel(gray, cv2.cv_64f, 1, 0))  if orient == 'y':    abs_sobel = np.absolute(cv2.sobel(gray, cv2.cv_64f, 0, 1))  # rescale back to 8 bit integer  scaled_sobel = np.uint8(255*abs_sobel/np.max(abs_sobel))  # create a copy and apply the threshold  binary_output = np.zeros_like(scaled_sobel)  # here i'm using inclusive (>=, = thresh_min) & (scaled_sobel  thresh[0]) & (l_channel  100:    lab_b = lab_b*(255/np.max(lab_b))  # 2) apply a threshold to the l channel  binary_output = np.zeros_like(lab_b)  binary_output[((lab_b > thresh[0]) & (lab_b = win_y_low) & (nonzeroy = win_xleft_low) & (nonzerox = win_y_low) & (nonzeroy = win_xright_low) & (nonzerox  minpix pixels, recenter next window on their mean position    if len(good_left_inds) > minpix:      leftx_current = np.int(np.mean(nonzerox[good_left_inds]))    if len(good_right_inds) > minpix:          rightx_current = np.int(np.mean(nonzerox[good_right_inds]))  # concatenate the arrays of indices (previously was a list of lists of pixels)  try:    left_lane_inds = np.concatenate(left_lane_inds)    right_lane_inds = np.concatenate(right_lane_inds)  except valueerror:    # avoids an error if the above is not implemented fully    pass  # extract left and right line pixel positions  leftx = nonzerox[left_lane_inds]  lefty = nonzeroy[left_lane_inds]  rightx = nonzerox[right_lane_inds]  righty = nonzeroy[right_lane_inds]  return leftx, lefty, rightx, righty, out_img def fit_polynomial(binary_warped, nwindows=9, margin=100, minpix=50):  # find our lane pixels first  leftx, lefty, rightx, righty, out_img = find_lane_pixels(    binary_warped, nwindows, margin, minpix)  # fit a second order polynomial to each using `np.polyfit`  left_fit = np.polyfit(lefty, leftx, 2)  right_fit = np.polyfit(righty, rightx, 2)  # generate x and y values for plotting  ploty = np.linspace(0, binary_warped.shape[0]-1, binary_warped.shape[0] )  try:    left_fitx = left_fit[0]*ploty**2 + left_fit[1]*ploty + left_fit[2]    right_fitx = right_fit[0]*ploty**2 + right_fit[1]*ploty + right_fit[2]  except typeerror:    # avoids an error if `left` and `right_fit` are still none or incorrect    print('the function failed to fit a line!')    left_fitx = 1*ploty**2 + 1*ploty    right_fitx = 1*ploty**2 + 1*ploty  ## visualization ##  # colors in the left and right lane regions  out_img[lefty, leftx] = [255, 0, 0]  out_img[righty, rightx] = [0, 0, 255]  # plots the left and right polynomials on the lane lines  #plt.plot(left_fitx, ploty, color='yellow')  #plt.plot(right_fitx, ploty, color='yellow')  return out_img, left_fit, right_fit, ploty
	对以上6种工况进行车道线检测,处理结果如下图所示。
无阴影、颜色无明暗变换的直道
无阴影、颜色无明暗变换的弯道
有小面积阴影、颜色由暗到亮的直道
无阴影、道路标志线不清晰的弯道
有大面积阴影、颜色由暗到亮的弯道
有大面积阴影、颜色由亮到暗的弯道
	跟踪车道线
	视频数据是连续的图片,基于连续两帧图像中的车道线不会突变的先验知识,我们可以使用上一帧检测到的车道线结果,作为下一帧图像处理的输入,搜索上一帧车道线检测结果附近的点,这样不仅可以减少计算量,而且得到的车道线结果也更稳定,如下图所示。
图片出处:优达学城(udacity)无人驾驶工程师学位
	图中的细黄线为上一帧检测到的车道线结果,绿色阴影区域为细黄线横向扩展的一个区域,通过搜索该区域内的白点坐标,即可快速确定当前帧中左右车道线的待选点。
	使用上一帧的车道线检测结果进行车道线跟踪的代码如下:
	# step 6 : track lane lines based the latest lane line result def fit_poly(img_shape, leftx, lefty, rightx, righty):   ### to-do: fit a second order polynomial to each with np.polyfit() ###  left_fit = np.polyfit(lefty, leftx, 2)  right_fit = np.polyfit(righty, rightx, 2)  # generate x and y values for plotting  ploty = np.linspace(0, img_shape[0]-1, img_shape[0])  ### to-do: calc both polynomials using ploty, left_fit and right_fit ###  left_fitx = left_fit[0]*ploty**2 + left_fit[1]*ploty + left_fit[2]  right_fitx = right_fit[0]*ploty**2 + right_fit[1]*ploty + right_fit[2]    return left_fitx, right_fitx, ploty, left_fit, right_fit def search_around_poly(binary_warped, left_fit, right_fit):  # hyperparameter  # choose the width of the margin around the previous polynomial to search  # the quiz grader expects 100 here, but feel free to tune on your own!  margin = 60  # grab activated pixels  nonzero = binary_warped.nonzero()  nonzeroy = np.array(nonzero[0])  nonzerox = np.array(nonzero[1])    ### to-do: set the area of search based on activated x-values ###  ### within the +/- margin of our polynomial function ###  ### hint: consider the window areas for the similarly named variables ###  ### in the previous quiz, but change the windows to our new search area ###  left_lane_inds = ((nonzerox > (left_fit[0]*(nonzeroy**2) + left_fit[1]*nonzeroy +          left_fit[2] - margin)) & (nonzerox  (right_fit[0]*(nonzeroy**2) + right_fit[1]*nonzeroy +          right_fit[2] - margin)) & (nonzerox < (right_fit[0]*(nonzeroy**2) +          right_fit[1]*nonzeroy + right_fit[2] + margin)))    # again, extract left and right line pixel positions  leftx = nonzerox[left_lane_inds]  lefty = nonzeroy[left_lane_inds]  rightx = nonzerox[right_lane_inds]  righty = nonzeroy[right_lane_inds]  # fit new polynomials  left_fitx, right_fitx, ploty, left_fit, right_fit = fit_poly(binary_warped.shape, leftx, lefty, rightx, righty)    ## visualization ##  # create an image to draw on and an image to show the selection window  out_img = np.dstack((binary_warped, binary_warped, binary_warped))*255  window_img = np.zeros_like(out_img)  # color in left and right line pixels  out_img[nonzeroy[left_lane_inds], nonzerox[left_lane_inds]] = [255, 0, 0]  out_img[nonzeroy[right_lane_inds], nonzerox[right_lane_inds]] = [0, 0, 255]  # generate a polygon to illustrate the search window area  # and recast the x and y points into usable format for cv2.fillpoly()  left_line_window1 = np.array([np.transpose(np.vstack([left_fitx-margin, ploty]))])  left_line_window2 = np.array([np.flipud(np.transpose(np.vstack([left_fitx+margin,               ploty])))])  left_line_pts = np.hstack((left_line_window1, left_line_window2))  right_line_window1 = np.array([np.transpose(np.vstack([right_fitx-margin, ploty]))])  right_line_window2 = np.array([np.flipud(np.transpose(np.vstack([right_fitx+margin,               ploty])))])  right_line_pts = np.hstack((right_line_window1, right_line_window2))  # draw the lane onto the warped blank image  cv2.fillpoly(window_img, np.int_([left_line_pts]), (0,255, 0))  cv2.fillpoly(window_img, np.int_([right_line_pts]), (0,255, 0))  result = cv2.addweighted(out_img, 1, window_img, 0.3, 0)    # plot the polynomial lines onto the image  #plt.plot(left_fitx, ploty, color='yellow')  #plt.plot(right_fitx, ploty, color='yellow')  ## end visualization steps ##    return result, left_fit, right_fit, ploty
	对以上6种工况进行车道线跟踪,处理结果如下图所示。
无阴影、颜色无明暗变换的直道
无阴影、颜色无明暗变换的弯道
有小面积阴影、颜色由暗到亮的直道
无阴影、道路标志线不清晰的弯道
有大面积阴影、颜色由暗到亮的弯道
有大面积阴影、颜色由亮到暗的弯道
	以上,我们就完成了在透视变换结果上的车道线检测和跟踪。
	逆投影到原图
	我们在计算透视变换矩阵时计算了两个矩阵m和minv,使用m能够实现透视变换,使用minv能够实现逆透视变换。
	m = cv2.getperspectivetransform(src, dst) minv = cv2.getperspectivetransform(dst, src)
	我们将两条车道线所围成的区域涂成绿色,并将结果绘制在“鸟瞰图”上后,使用逆透视变换矩阵反投到原图上,即可实现在原图上的可视化效果。代码如下:
	# step 7 : draw lane line result on undistorted image def drawing(undist, bin_warped, color_warp, left_fitx, right_fitx):  # create an image to draw the lines on  warp_zero = np.zeros_like(bin_warped).astype(np.uint8)  color_warp = np.dstack((warp_zero, warp_zero, warp_zero))  # recast the x and y points into usable format for cv2.fillpoly()  pts_left = np.array([np.transpose(np.vstack([left_fitx, ploty]))])  pts_right = np.array([np.flipud(np.transpose(np.vstack([right_fitx, ploty])))])  pts = np.hstack((pts_left, pts_right))  # draw the lane onto the warped blank image  cv2.fillpoly(color_warp, np.int_([pts]), (0,255, 0))  # warp the blank back to original image space using inverse perspective matrix (minv)  newwarp = cv2.warpperspective(color_warp, minv, (undist.shape[1], undist.shape[0]))  # combine the result with the original image  result = cv2.addweighted(undist, 1, newwarp, 0.3, 0)  return result
	以上6个场景的左右车道线绘制结果如下所示:
无阴影、颜色无明暗变换的直道
无阴影、颜色无明暗变换的弯道
有小面积阴影、颜色由暗到亮的直道
无阴影、道路标志线不清晰的弯道
有大面积阴影、颜色由暗到亮的弯道
有大面积阴影、颜色由亮到暗的弯道
	处理视频
	在一步步完成摄像机标定、图像畸变校正、透视变换、提取车道线、检测车道线、跟踪车道线后,我们在图像上实现了复杂环境下的车道线检测算法。现在我们将视频转化为图片,然后一帧帧地对视频数据进行处理,然后将车道线检测结果存为另一段视频。
	高级车道线检测算法效果
	视频中左上角出现的道路曲率和车道偏离量的计算都是获取车道线曲线方程后的具体应用,这里不做详细讨论。
	结语
	以上就是《再识图像之高级车道线检测》的全部内容,本次分享中介绍的摄像机标定、投影变换、颜色通道、滑动窗口等技术,在计算机视觉领域均得到了广泛应用。
	处理复杂道路场景下的视频数据是一项及其艰巨的任务。仅以提取车道线的过程为例,使用设定规则的方式提取车道线,虽然能够处理项目视频中的场景,但面对变化更为恶劣的场景时,还是无能为力。现阶段解决该问题的方法就是通过深度学习的方法,拿足够多的标注数据去训练模型,才能尽可能多地达到稳定的检测效果。
			
			
       	 	
    	Qorvo与National Instruments联合演示业内首款5G RF前端模块
         	 	
    	BOSHIDA电源模块 电源故障管理 电气安全的注意事项
         	 	
    	ZigBee技术在智慧养老中的作用
         	 	
    	铠侠开发出约170层的NAND闪存
         	 	
    	射频识别技术的特点是什么 射频识别技术的构成及工作原理
         	 	
    	用于无人驾驶技术中的车道线检测技术
         	 	
    	射频微波基础知识科普
         	 	
    	昇润科技新推全网超小体积 5.0 低功耗蓝牙模组
         	 	
    	数据存储在大数据时代的思维转变和应对
         	 	
    	NB-IoT在智能家居中应用及市场前景
         
       	 	
    	2018未来趋势发布大会亮相未来生活节
         	 	
    	如何组织PID命名空间的各种ID?PID命名空间基本概念简析
         	 	
    	首例!科创板上会取消审议!这家国内知名芯片企业到底怎么了?
         	 	
    	智能监控系统:视频监控行业的一次新的革命
         	 	
    	放电管的特点及应用
         	 	
    	针对嵌入式设备中网络威胁的入侵检测和防御系统的算法
         	 	
    	实体零售业怎样加入人工智能技术
         	 	
    	科技之光照耀医界:AR与AI能为医疗带来什么?
         	 	
    	万众瞩目的“双马”对话上演!马化腾反对产业割裂和技术脱钩
         	 	
    	如何检测印刷电路板上的故障组件