Python Opencv实践 - 车牌定位(纯练手,存在失败场景,可以继续优化)

        使用传统的计算机视觉方法定位图像中的车牌,参考了部分网上的文章,实际定位效果对于我目前使用的网上的图片来说还可以。实测发现对于车身本身是蓝色、或是车牌本身上方有明显边缘的情况这类图片定位效果较差。纯练手项目,仅供参考。代码中imagePreProcess对某些图片定位率相比于imagePreProcess2做预处理的效果要好。后续可以尝试做一个如果imagePreProcess2识别无效后使用imagePreProcess再处理,或者加上阈值自适应打分的机制优化。目前对于我做的练手项目来说足够了。

        注意:以下代码是参考了网上的一些文章后,按照自己的思路写的,定位效果尚可。参考的文章有:python-opencv实战:车牌识别(一):精度还不错的车牌定位_基于阈值分割的车牌定位识别-CSDN博客

 https://www.cnblogs.com/fyunaru/p/12083856.html

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt#过滤矩形的参数
minRectW = 100
minRectH = 50
#判断车牌颜色的参数
#一般情况下,蓝色车牌H分量的值通常都在115附近徘徊
# S分量和V分量因光照不同而差异较大(opencv中H分量的取值范围是0到179,而不是图像学中的0到360;S分量和V分量的取值范围是到255)
deltaH = 15
hsvLower = np.array([115 - deltaH,60,60])
hsvUpper = np.array([115 + deltaH,255,255])#灰度拉伸
def grayScaleStretch(img):maxGray = float(img.max())minGray = float(img.min())for i in range(img.shape[0]):for j in range(img.shape[1]):img[i,j] = 255 / (maxGray - minGray) * (img[i,j] - minGray)return img#图像二值化
def image2Binary(img):#选取灰度最大最小值的中间值maxGray = float(img.max())minGray = float(img.min())threshold = (minGray + maxGray) / 2ret,bin = cv.threshold(img, threshold, 255, cv.THRESH_BINARY)return bin#图像预处理
def imagePreProcess(img):#转换为灰度图imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)#灰度拉伸imgGray = grayScaleStretch(imgGray)#plt.imshow(imgGray, cmap='gray')kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (3,3))#做开运算imgOpen = cv.morphologyEx(imgGray, cv.MORPH_OPEN, kernel)#plt.imshow(imgOpen, cmap='gray')#获得差分图imgDiff = cv.absdiff(imgGray, imgOpen)#plt.imshow(imgDiff, cmap='gray')imgDiff = cv.GaussianBlur(imgDiff, (3,3), 5)#plt.imshow(imgDiff, cmap='gray')#图像二值化imgBinary = image2Binary(imgDiff)#plt.imshow(imgBinary, cmap='gray')cannyEdges = cv.Canny(imgBinary, 127, 200)#plt.imshow(cannyEdges, cmap='gray')#对Canny检测边缘结果做处理kernel = np.ones((3,3), np.uint8)imgOut = cv.morphologyEx(cannyEdges, cv.MORPH_CLOSE, kernel)imgOut = cv.dilate(imgOut, kernel, iterations=1)imgOut = cv.morphologyEx(imgOut, cv.MORPH_OPEN, kernel)#imgOut = cv.erode(imgOut, kernel, iterations=1)imgOut = cv.morphologyEx(imgOut, cv.MORPH_CLOSE, kernel)#plt.imshow(imgOut, cmap='gray')return imgOut#图像预处理2 - 对于某些
def imagePreProcess2(img):imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)#灰度拉伸imgGray = grayScaleStretch(imgGray)imgGray = cv.GaussianBlur(imgGray, (3,3), 5)#进行边缘检测cannyEdges = cv.Canny(imgGray, 180, 230)#二值化imgBinary = image2Binary(cannyEdges)#plt.imshow(imgBinary, cmap='gray')#先做闭运算再做开运算kernel = np.ones((3,3), np.uint8)imgOut = cv.morphologyEx(imgBinary, cv.MORPH_CLOSE, kernel)imgOut = cv.morphologyEx(imgOut, cv.MORPH_OPEN, kernel)imgOut = cv.absdiff(imgBinary, imgOut)imgOut = cv.morphologyEx(imgOut, cv.MORPH_CLOSE, kernel)imgOut = cv.dilate(imgOut, kernel, iterations=1)plt.imshow(imgOut, cmap='gray')return imgOut#debug
def printHSV(hsvSrc):for i in range(hsvSrc.shape[0]):for j in range(hsvSrc.shape[1]):(h,s,v) = hsvSrc[i][j]print(h,s,v)#定位车牌
def locate_plate(imgProcessing, imgOriginal):contours,hierarchy = cv.findContours(imgProcessing, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)carPlateCandidates = []for contour in contours:(x,y,w,h) = cv.boundingRect(contour)#过滤掉一些小的矩形if (w < minRectW or h < minRectH):continue#cv.rectangle(imgOriginal, (int(x), int(y)), (int(x + w),int(y + h)), (0,255,0), 2)carPlateCandidates.append([int(x),int(y),int(x + w),int(y + h)])#plt.imshow(imgOriginal[:,:,::-1])maxMean = 0target = []target_mask = []#依次检查候选车牌列表,用HSV颜色空间判别是否是车牌for candidate in carPlateCandidates:(x0,y0,x1,y1) = candidatecandidateROI = imgOriginal[y0:y1,x0:x1]hsvROI = cv.cvtColor(candidateROI, cv.COLOR_BGR2HSV)mask = cv.inRange(hsvROI, hsvLower, hsvUpper)#print(mask)#plt.imshow(mask, cmap='gray')#使用均值找出蓝色最多的区域mean = cv.mean(mask)#print(mean)if mean[0] > maxMean:maxMean = mean[0]target = candidatetarget_mask = mask#对target的范围进行缩小,找出蓝色刚开始和结束的坐标print(target_mask)nonZeroPoints = cv.findNonZero(target_mask)#print(nonZeroPoints)sortByX = np.sort(nonZeroPoints, axis=0)xMin = sortByX[0][0][0]xMax = sortByX[-1][0][0]print(sortByX)sortByY = np.sort(nonZeroPoints, axis=1)yMin = sortByY[0][0][1]yMax = sortByY[-1][0][1]print(sortByY)print("X min:" + str(xMin) + " X max:" + str(xMax) + " Y min:" + str(yMin) + " Y max:" + str(yMax))(x0,y0,x1,y1) = targetprint("Original:" + str(x0) + "," + str(y0) + "," + str(x1) + "," + str(y1))#target = (x0 + xMin, y0 + yMin, x0 + (xMax - xMin), y0 + yMax - yMin)target = [x0 + xMin, y0 + yMin, x0 + xMax, y0 + yMax]return target#读取图像
imgCarPlate = cv.imread("../../SampleImages/carplate/carplate_chongqing.jpg", cv.IMREAD_COLOR)
#plt.imshow(imgCarPlate[:,:,::-1])
img4locate = imagePreProcess2(imgCarPlate)
target = locate_plate(img4locate, imgCarPlate)
(x0,y0,x1,y1) = target
cv.rectangle(imgCarPlate, (x0,y0), (x1,y1), (0,255,0), 2)
plt.imshow(imgCarPlate[:,:,::-1])

成功的例子: 

 

 

 

 

 

不太成功的例子(轮廓检测的不太好,并且轮廓中蓝色的值过早出现,可以优化判断为连续的蓝色而不是零散的蓝色)

失败的例子(没能检测出小轮廓,车身本身为蓝色,替换为imagePreProcess后能够成功):

         

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/187858.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

科研检测机构服务预约小程序的效果如何

科研检测机构涵盖的业务比较广&#xff0c;比如水质检测、农产品检测、食品检测等&#xff0c;对相关从业者来说&#xff0c;可能需要频繁使用这些业务&#xff0c;或者个人偶尔需要一些东西检测。 对用户和检测机构来说&#xff0c;由于行业的特殊性&#xff0c;在实际发展中…

keepalived+Nginx+邮件

实验场景&#xff1a; 我使用keepalived保证nginx的高可用&#xff0c;我想知道什么时候ip发生漂移&#xff0c;可以让ip发生漂移的时候 我的邮箱收到消息. 如果对keepalived不了解&#xff0c;这有详细解释&#xff1a;keepalived与nginx与MySQL-CSDN博客https://blog.csdn.ne…

竞赛 行人重识别(person reid) - 机器视觉 深度学习 opencv python

文章目录 0 前言1 技术背景2 技术介绍3 重识别技术实现3.1 数据集3.2 Person REID3.2.1 算法原理3.2.2 算法流程图 4 实现效果5 部分代码6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习行人重识别(person reid)系统 该项目…

【Copilot】登录报错 Extension activation failed: “No auth flow succeeded.“(VSCode)

问题描述 Visual Studio Code 登录 GitHub Copilot 插件报错。 在浏览器中成功授权 GitHub 账户&#xff0c;返回 VSCode 后仍然报错。 [ERROR] [default] [2023-11-06T12:34:56.185Z] Extension activation failed: "No auth flow succeeded."原因分析 网络环境问…

山西电力市场日前价格预测【2023-11-12】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-12&#xff09;山西电力市场全天平均日前电价为224.59元/MWh。其中&#xff0c;最高日前电价为434.30元/MWh&#xff0c;预计出现在18:00。最低日前电价为0.00元/MWh&#xff0c;预计出…

SpringBoot 缓存之 @Cacheable 详细介绍

一、简介 1、缓存介绍 Spring 从 3.1 开始就引入了对 Cache 的支持。定义了 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术。并支持使用 JCache&#xff08;JSR-107&#xff09;注解简化我们的开发。&#xfeff; 其…

c语言,将奇数和偶数分类

题目&#xff1a;输入一个整数数组&#xff0c;实现一个函数&#xff0c;来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分&#xff0c;所有偶数位于数组的后半部分。 思路&#xff1a;像冒泡排序那样&#xff0c;相邻两个数比较&#xff0c;两个都是偶数则不…

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:

错误描述如下所示&#xff1a; 我们将错误拉到最下面如下所示为导致异常的原因&#xff1a; Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type com.example.reviewmybatisplus.Service.UserService available: expec…

Perl语言用多线程爬取商品信息并做可视化处理

首先&#xff0c;我们需要使用Perl的LWP::UserAgent模块来发送HTTP请求。然后&#xff0c;我们可以使用HTML::TreeBuilder模块来解析HTML文档。在这个例子中&#xff0c;我们将使用BeautifulSoup模块来解析HTML文档。 #!/usr/bin/perl use strict; use warnings; use LWP::User…

班级新闻管理系统asp.net+sqlserver

班级新闻管理系统 附加功能 新闻图片&#xff0c;点击次数访问自增&#xff0c;每个人都只能增删改查自己发布的新闻&#xff0c;并可以看到所有人发布的新闻 运行前附加数据库.mdf&#xff08;或sql生成数据库&#xff09; 主要技术&#xff1a; 基于asp.net架构和sql serve…

内存条选购注意事项(电脑,笔记本)

电脑内存条的作用、选购技巧以及注意事项详解 - 郝光明的个人空间 - OSCHINA - 中文开源技术交流社区 现在的电脑直接和内存条联系 电脑上的所有输入和输出都只能依靠内存条 现在买双条而不是单条 买两个相同的内存条最好 笔记本先分清是低电压还是标准电压&#xff0c;DD…

前端和空字符串、零比较时请务必使用===

在前端开发中遇到一个问题&#xff0c;以下两条语句的结果都是true。 console.log(0 ""); console.log(false ""); 这就导致了editingId为0的时候&#xff0c;if分支并没有执行&#xff0c;而我的本意是当editingId不是空也不是空字符串的时候执行分支…

可视化 | 3D文字球状标签云

文章目录 &#x1f4da;改编点&#x1f4da;final 改编自echarts 3d词云&#xff08;指向滑动、拖动、缩放、点击、自转 &#xff09; &#x1f4da;改编点 背景透明&#xff1a;background:rgb(0,0,0,0);不用链接&#xff0c;用span&#xff0c;重点span标class"star&q…

3d max软件中的缓存垃圾该如何清理?

使用3d max建模到渲染操作&#xff0c;来回对效果图调整的次数过多时&#xff0c;就会出现一下看不到的垃圾缓存&#xff0c;影响保存的速度&#xff0c;影响效率&#xff01; 对于这类的3d垃圾清理的有什么高效方法呢&#xff1f; 3dmax垃圾清理的常规操作如下&#xff1a; 1、…

跨镜头目标融合__追踪之目标重识别研究(跨镜头目标追踪)

文章目录 标题&#xff1a;跨镜头目标融合&#xff1b;目标重识别&#xff1b;跨镜头目标追踪&#xff1b; 1 目的&#xff1a;2 实现方法/策略&#xff1a;2.1 目标类型位置匹配&#xff08;或考虑结合目标轨迹&#xff09;2.2 目标重识别2.3 目标类型位置匹配(轨迹)目标重识别…

14 # 手写 debounce 防抖方法

什么是防抖 防抖: n 秒后再去执行该事件&#xff0c;若在 n 秒内被重复触发&#xff0c;则重新计时&#xff0c;这个效果跟英雄联盟里的回城技能差不多。 本质上是优化高频率执行代码的一种手段&#xff0c;目的就是降低回调执行频率、节省计算资源。 应用场景&#xff1a; …

使用 huggingface_hub 镜像下载 大模型

download.py &#x1f447; import os # 配置 hf镜像 os.environ[HF_ENDPOINT] https://hf-mirror.com# 设置保存的路径 local_dir "XXXXXX"# 设置仓库id model_id "sensenova/piccolo-large-zh"cmd f"huggingface-cli download --resume-downlo…

Python 列表元素里面含有字典或者列表进行排序

大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 示例1&#xff1a;列表里面含有列表进行排序 s [[1, 2], [100, 2], [33, 3], [25, 6]] s.sort(keylambda k: k[0]) print(s)结果&#xff1a; [[1, 2], [25, 6], [33, 3…

C++动态库

C动态库 动态库文件&#xff08;Dynamic Link Library&#xff0c;DLL&#xff09;是程序在运行时所需要调用的库。静态库文件是程序在编译时所需要调用的库。 1 环境介绍 VS版本&#xff1a;VS2017 编程语言&#xff1a;C 2 功能介绍 使用VS2017项目模板创建C动态库生成…

ARM 基础学习记录 / ARM 裸机编程

汇编程序调用 C 程序详情 在 C 程序和 ARM 汇编程序之间相互调用时必须遵守 ATPCS 规则&#xff0c;其是基于 ARM 指令集和 THUMB 指令集过程调用的规范&#xff0c;规定了调用函数如何传递参数&#xff0c;被调用函数如何获取参数&#xff0c;以何种方式传递函数返回值。 寄存…