第十三周周总结
2020.05.16
本周完成了视频中截取帧图篇,并识别图片中车牌号的功能。
识别基本思路:先是车牌提取,识别图中车牌位置并保存车牌图片(流程:高斯去噪、灰度处理、sobel边缘检测、自适应阈值处理、闭运算、中值滤波去除噪点、轮廓绘制、遍历所有轮廓,去除车牌(车牌 宽>2倍高、为了识别准确,只识别靠近摄像头的车牌号,远处车牌号太不清楚,选择y>500,x<1250、轮廓宽<100 并且>50))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | # 导入所需模块 import cv2 from matplotlib import pyplot as plt def cp_tiqu(name): # 加载图片 rawImage = cv2.imread(name) # plt_show0('yuantu',rawImage) # 高斯去噪 image = cv2.GaussianBlur(rawImage, ( 3 , 3 ), 0 ) # 预览效果 # plt_show0('GaussianBlur',image) # 灰度处理 gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) plt_show( 'COLOR_RGB2GRAY' , gray_image) # sobel算子边缘检测(做了一个y方向的检测) Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1 , 0 ) # Sobel_y = cv2.Sobel(image, cv2.CV_16S, 0, 1) absX = cv2.convertScaleAbs(Sobel_x) # 转回uint8 # absY = cv2.convertScaleAbs(Sobel_y) # dst = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) image = absX plt_show( 'Sobel bianyuan' , image) # 自适应阈值处理 ret, image = cv2.threshold(image, 0 , 255 , cv2.THRESH_OTSU) plt_show( 'threshold yuzhi' , image) # 闭运算,是白色部分练成整体 kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, ( 3 , 3 )) print (kernelX) image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernelX, iterations = 2 ) plt_show( 'biyunsuan' , image) # 去除一些小的白点 kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, ( 20 , 1 )) kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, ( 1 , 19 )) ''' # 膨胀,腐蚀 image = cv2.dilate(image, kernelX) image = cv2.erode(image, kernelX) # 腐蚀,膨胀 image = cv2.erode(image, kernelY) image = cv2.dilate(image, kernelY) plt_show('pengzhangfushi',image) ''' # 中值滤波去除噪点 image = cv2.medianBlur(image, 15 ) plt_show( 'chu zao' , image) # 轮廓检测 # cv2.RETR_EXTERNAL表示只检测外轮廓 # cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息 contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 绘制轮廓 image1 = rawImage.copy() cv2.drawContours(image1, contours, - 1 , ( 0 , 255 , 0 ), 5 ) plt_show0( 'lunkuo' , image1) # 筛选出车牌位置的轮廓 # 这里我只做了一个车牌的长宽比在3:1到4:1之间这样一个判断 num = 1 for item in contours: # cv2.boundingRect用一个最小的矩形,把找到的形状包起来 rect = cv2.boundingRect(item) x = rect[ 0 ] y = rect[ 1 ] weight = rect[ 2 ] height = rect[ 3 ] # 440mm×140mm # if (weight > (height * 3)) and (weight < (height * 4)) and y > 500: if (weight > (height * 2 )) and y > 500 and x < 1250 and weight < 100 and weight > 50 : image = rawImage[y:y + height, x:x + weight] # cv_show('image',image) # 图像保存 image_name = 'car' + str (num) + '.jpg' print (image_name) plt_show0( 'save' , image) cv2.imwrite(image_name, image) num + = 1 if __name__ = = '__main__' : cp_tiqu( "120.jpg" ) |
原图:
获取车牌图片信息:
第二步:将车牌图篇分割为一个个字符图片
思路:高斯去噪、灰度处理、自适应阈值、计算二值、轮廓绘制、筛选各个字符位置的轮廓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | # 导入所需模块 import cv2 from matplotlib import pyplot as plt def zifu_tiqu(name): # 加载图片 rawImage = cv2.imread(name) plt_show0( 'yuantu' , rawImage) # 高斯去噪 image = cv2.GaussianBlur(rawImage, ( 3 , 3 ), 0 ) # 预览效果 plt_show0( 'GaussianBlur' , image) # 灰度处理 gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) plt_show( 'gray image' , gray_image) # 自适应阈值处理 ret, image = cv2.threshold(gray_image, 0 , 255 , cv2.THRESH_OTSU) plt_show( 'yuzhi' , image) # 计算二值图像黑白点的个数,处理绿牌照问题,让车牌号码始终为白色 area_white = 0 area_black = 0 height, width = image.shape print (image.shape) for i in range (height): for j in range (width): if image[i, j] = = 255 : area_white + = 1 else : area_black + = 1 #if area_white > area_black: # ret, image = cv2.threshold(gray_image, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV) #plt_show('erzhi', image) kernel = cv2.getStructuringElement(cv2.MORPH_RECT, ( 1 , 1 )) contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 绘制轮廓 image1 = rawImage.copy() cv2.drawContours(image1, contours, - 1 , ( 0 , 255 , 0 ), 1 ) plt_show0( 'lun kuo' , image1) # 筛选出各个字符的位置的轮廓 words = [] for item in contours: # cv2.boundingRect用一个最小的矩形,把找到的形状包起来 word = [] rect = cv2.boundingRect(item) x = rect[ 0 ] y = rect[ 1 ] weight = rect[ 2 ] height = rect[ 3 ] word.append(x) word.append(y) word.append(weight) word.append(height) words.append(word) words = sorted (words, key = lambda s: s[ 0 ], reverse = False ) print (words) i = 0 for word in words: if (word[ 3 ] > (word[ 2 ])) and (word[ 3 ] < (word[ 2 ] * 5 )): i = i + 1 image = rawImage[word[ 1 ]:word[ 1 ] + word[ 3 ], word[ 0 ]:word[ 0 ] + word[ 2 ]] plt_show0( 'single' , image) print ( 'test2_' + str (i) + '.jpg' ) cv2.imwrite( 'chepai/test2_' + str (i) + '.jpg' , image |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· PPT革命!DeepSeek+Kimi=N小时工作5分钟完成?
· What?废柴, 还在本地部署DeepSeek吗?Are you kidding?
· DeepSeek企业级部署实战指南:从服务器选型到Dify私有化落地
· 程序员转型AI:行业分析
· 重磅发布!DeepSeek 微调秘籍揭秘,一键解锁升级版全家桶,AI 玩家必备神器!