Opencv创建车牌图片识别系统方法详解

网友投稿 308 2022-09-04


Opencv创建车牌图片识别系统方法详解

目录前言包含功能软件版本软件架构参考文档效果图展示车牌检测过程图片车牌文字识别过程部分核心代码

前言

这是一个基于spring boot + maven + opencv 实现的图像识别及训练的Demo项目

包含车牌识别、人脸识别等功能,贯穿样本处理、模型训练、图像处理、对象检测、对象识别等技术点

java语言的深度学习项目,在整个开源社区来说都相对较少;

拥有完整的训练过程、检测、识别过程的开源项目更是少之又少!!

包含功能

蓝、绿、黄车牌检测及车牌号码识别网上常见的轮廓提取车牌算法JAVA实现hsv色彩分割提取车牌算法JAVA实现基于svm算法的车牌检测训练JAVA实现基于ann算法的车牌号码识别训练JAVA实现人脸检测 接下来将实现人脸识别图片处理工具,目前实现了HSV色彩切割,后续将添加更多使用的图片处理工具,用于辅助算法优化

软件版本

jdk 1.8.61+maven 3.0+opencv 4.0.1 ; javacpp1.4.4;opencv-platform 4.0.1-1.4.4spring boot 2.1.5.RELEASEyx-image-recognition 1.0.0版本

软件架构

B/S 架构,前端html + requirejs,后端java

数据库使用 sqlite3.0

接口文档使用swagger 2.0

参考文档

参考了EasyPR C++项目、以及fan-wenjie的EasyPR-Java项目;同时查阅了部分opencv官方4.0.1版本C++的源码,结合个人对java语言的理解,整理出当前项目

liuruoze/EasyPR

fan-wenjie/EasyPR-Java

opencv官方

效果图展示

车牌识别

黄牌识别

绿牌识别

夜间识别

图片提取工具

人脸识别

训练

接口文档

车牌检测过程

高斯模糊:

图像灰度化:

Sobel 算子:

图像二值化:

图像闭操作:

二值图像降噪:

提取外部轮廓:

外部轮廓筛选:

切图:

重置切图尺寸:

车牌检测结果:

图片车牌文字识别过程

车牌检测结果:

debug_char_threshold:

debug_char_clearLiuDing:

debug_specMat:

debug_chineseMat:

debug_char_auxRoi:

部分核心代码

package com.yuxue.service.impl;

import java.io.File;

import java.util.List;

import java.util.Map;

import java.util.Set;

import java.util.Vector;

import org.opencv.core.Core;

import org.opencv.core.CvType;

import org.opencv.core.Mat;

import org.opencv.imgcodecs.Imgcodecs;

import org.opencv.imgproc.Imgproc;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Propagation;

import org.springframework.transaction.annotation.Transactional;

import com.alibaba.druid.util.StringUtils;

import com.alibaba.fastjson.JSONObject;

import com.google.common.collect.Lists;

import com.google.common.collect.Maps;

import com.google.common.collect.Sets;

import com.yuxue.constant.Constant;

import com.yuxue.entity.PlateFileEntity;

import com.yuxue.entity.TempPlateFileEntity;

import com.yuxue.enumtype.PlateColor;

import com.yuxue.mapper.PlateFileMapper;

import com.yuxue.mapper.TempPlateFileMapper;

import com.yuxue.service.PlateService;

import com.yuxue.util.FileUtil;

import com.yuxue.util.GenerateIdUtil;

import com.yuxue.util.PlateUtil;

@Service

public class PlateServiceImpl implements PlateService {

@Autowired

private PlateFileMapper plateFileMapper;

@Autowired

private TempPlateFileMapper tempPlateFileMapper;

static {

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

}

@Override

@Transactional(propagation = Propagation.REQUIRED)

public Object refreshFileInfo() {

File baseDir = new File(Constant.DEFAULT_DIR);

if(!baseDir.exists() || !baseDir.isDirectory()) {

return null;

}

List resultList = Lists.newArrayList();

// 获取baseDir下第一层级的目录, 仅获取文件夹,不递归子目录,遍历

List folderList = FileUtil.listFile(baseDir, ";", false);

folderList.parallelStream().forEach(folder -> {

if(!folder.getName().equals("temp")) {

// 遍历每一个文件夹, 递归获取文件夹下的图片

List imgList = FileUtil.listFile(folder, Constant.DEFAULT_TYPE, true);

if(null != imgList && imgList.size() > 0) {

imgList.parallelStream().forEach(n->{

TempPlateFileEntity entity = new TempPlateFileEntity();

entity.setFilePath(n.getAbsolutePath().replaceAll("\\\\", "/"));

entity.setFileName(n.getName());

entity.setFileType(n.getName().substring(n.getName().lastIndexOf(".") + 1));

resultList.add(entity);

});

}

}

});

tempPlateFileMapper.turncateTable();

tempPlateFileMapper.batchInsert(resultList);

tempPlateFileMapper.updateFileInfo();

return 1;

}

@Override

public Object recognise(String filePath, boolean reRecognise) {

filePath = filePath.replaceAll("\\\\", "/");

File f = new File(filePath);

PlateFileEntity entity = null;

Map paramMap = Maps.newHashMap();

paramMap.put("filePath", filePath);

List list= plateFileMapper.selectByCondition(paramMap);

if(null == list || list.size() <= 0) {

if(FileUtil.checkFile(f)) {

entity = new PlateFileEntity();

entity.setFileName(f.getName());

entity.setFilePath(f.getAbsolutePath().replaceAll("\\\\", "/"));

entity.setFileType(f.getName().substring(f.getName().lastIndexOf(".") + 1));

plateFileMapper.insertSelective(entity);

}

reRecognise = true;

} else {

entity = list.get(0);

}

if(reRecognise || StringUtils.isEmpty(entity.getTempPath())) {

doRecognise(f, entity); // 重新识别

entity = plateFileMapper.selectByPrimaryKey(entity.getId()); // 重新识别之后,重新获取一下数据

}

// 查询debug文件

if(!StringUtils.isEmpty(entity.getTempPath())) {

Vector debugFiles = new Vector();

FileUtil.getFiles(entity.getTempPath(), debugFiles);

entity.setDebugFiles(debugFiles);

}

return entity;

}

@Override

public Object recogniseAll() {

// 查询到还没有进行车牌识别的图片

List list = plateFileMapper.getUnRecogniseList();

list.parallelStream().forEach(n->{

File f = new File(n.getFilePath());

if(FileUtil.checkFile(f)) {

doRecognise(f, n);

}

});

return 1;

}

/**

* 单张图片 车牌识别

* 拷贝文件到临时目录

* 过程及结果更新数据库

* @param f

* @param e

* @return

*/

public Object doRecognise(File f, PlateFileEntity e) {

if(!f.exists()) {

return null;

}

String ct = GenerateIdUtil.getStrId();

String targetPath = Constant.DEFAULT_TEMP_DIR + ct + (f.getName().substring(f.getName().lastIndexOf(".")));

FileUtil.copyAndRename(f.getAbsolutePath(), targetPath); // 拷贝文件并且重命名

// 创建临时目录, 存放过程图片

String tempPath = Constant.DEFAULT_TEMP_DIR + ct + "/";

FileUtil.createDir(tempPath);

e.setTempPath(tempPath);

Boolean debug = false;

Vector dst = new Vector();

PlateUtil.getPlateMat(targetPath, dst, debug, tempPath);

Set plates = Sets.newHashSet();

dst.stream().forEach(inMat -> {

PlateColor color = PlateUtil.getPlateColor(inMat, true, false, tempPath);

String plate = PlateUtil.charsSegment(inMat, color, debug, tempPath);

plates.add("<" + plate + "," + color.desc + ">");

});

e.setRecoPlate(plates.toString());

new File(targetPath).delete(); // 删除拷贝的临时文件

plateFileMapper.updateByPrimaryKeySelective(e);

return 1;

}

@Override

public Object getImgInfo(String imgPath) {

Map result = Maps.newHashMap();

String ct = GenerateIdUtil.getStrId();

File f = new File(imgPath);

if(f.exists()) {

String targetPath = Constant.DEFAULT_TEMP_DIR + ct + (f.getName().substring(f.getName().lastIndexOf(".")));

FileUtil.copyAndRename(f.getAbsolutePath(), targetPath);

result.put("targetPath", targetPath); // 返回临时路径给前端

// 获取图片的基本信息

Mat inMat = Imgcodecs.imread(targetPath);

result.put("rows", inMat.rows());

result.put("cols", inMat.cols());

}

return result;

}

@Override

public Object getHSVValue(String imgPath, Integer row, Integer col) {

Map result = Maps.newHashMap();

Mat inMat = Imgcodecs.imread(imgPath);

double[] rgb = inMat.get(row, col);

result.put("RGB", JSONObject.toJSONString(rgb));

Mat dst = new Mat(inMat.rows(), inMat.cols(), CvType.CV_32FC3);

Imgproc.cvtColor(inMat, dst, Imgproc.COLOR_BGR2HSV); // 转到HSV空间进行处理

double[] hsv = dst.get(row, col);

result.put("HSV", (int)hsv[0] + ", " + (int)hsv[1] + ", " + (int)hsv[2]);

return result;

}

}

package com.znz.service.impl;

import com.znz.service.PlateTypeService;

import com.znz.entity.PlateTypeEntity;

import com.znz.mapper.PlateTypeMapper;

import com.github.pagehelper.PageHelper;

import com.github.pagehelper.PageInfo;

import org.springframework.transaction.annotation.Transactional;

import org.springframework.transaction.annotation.Propagation;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.util.HashMap;

import java.util.Map;

import java.util.List;

/**

* 服务实现层

* @author znz

* @date 2020-09-30T16:54:41.823

*/

@Service

public class PlateTypeServiceImpl implements PlateTypeService {

@Autowired

private PlateTypeMapper plateTypeMapper;

@Override

public PlateTypeEntity getByPrimaryKey(Integer id) {

PlateTypeEntity entity = plateTypeMapper.selectByPrimaryKey(id);

return entity;

}

@Override

public PageInfo queryByPage(Integer pageNo, Integer pageSize, Map map) {

PageHelper.startPage(pageNo, pageSize);

PageInfo page = new PageInfo(plateTypeMapper.selectByCondition(map));

return page;

}

@Override

public List queryByCondition(Map map) {

return plateTypeMapper.selectByCondition(map);

}

@Override

@Transactional(propagation = Propagation.REQUIRED)

public Map save(PlateTypeEntity plateTypeEntity) {

plateTypeEntity.sIEDPcZetId(0);

plateTypeMapper.insertSelective(plateTypeEntity);

Map result = new HashMap<>();

result.put("id" , plateTypeEntity.getId());

return result;

}

@Override

@Transactional(propagation = Propagation.REQUIRED)

public Integer deleteById(Integer id){

return plateTypeMapper.deleteByPrimaryKey(id);

}

@Override

@Transactional(propagation = Propagation.REQUIRED)

public Integer updateById(PlateTypeEntity plateTypeEntity) {

if(null == plateTypeEntity || plateTypeEntity.getId() <= 0){

return 0;

}

return plateTypeMapper.updateByPrimaryKeySelective(plateTypeEntity);

}

}

package com.znz.service.impl;

import com.github.pagehelper.PageHelper;

import com.github.pagehelper.PageInfo;

import com.google.common.collect.Lists;

import com.google.common.collect.Maps;

import com.znz.entity.SystemMenuEntity;

import com.znz.mapper.SystemMenuMapper;

import com.znz.service.SystemMenuService;

import org.springframework.transaction.annotation.Transactional;

import org.springframework.transaction.annotation.Propagation;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/**

* 服务实现层

* @author znz

* @date 2021-06-20 16:15:23

*/

@Service

public class SystemMenuServiceImpl implements SystemMenuService {

@Autowired

private SystemMenuMapper systemMenuMapper;

@Override

public SystemMenuEntity getByPrimaryKey(Integer id) {

SystemMenuEntity entity = systemMenuMapper.selectByPrimaryKey(id);

return entity;

}

@Override

public PageInfo queryByPage(Integer pageNo, Integer pageSize, Map map) {

PageHelper.startPage(pageNo, pageSize);

PageInfo page = new PageInfo(systemMenuMapper.selectByCondition(map));

return page;

}

@Override

public List queryByCondition(Map map) {

return systemMenuMapper.selectByCondition(map);

}

@Override

@Transactional(propagation = Propagation.REQUIRED)

public Map save(SystemMenuEntity entity) {

entity.setId(0);

systemMenuMapper.insertSelective(entity);

Map result = new HashMap<>();

result.put("id" , entity.getId());

return result;

}

@Override

@Transactional(propagation = Propagation.REQUIRED)

public Integer deleteById(Integer id){

return systemMenuMapper.deleteByPrimaryKey(id);

}

@Override

@Transactional(propagation = Propagation.REQUIRED)

public Integer updateById(SystemMenuEntity systemMenuEntity) {

if(null == systemMenuEntity || systemMenuEntity.getId() <= 0){

return 0;

}

return systemMenuMapper.updateByPrimaryKeySelective(systemMenuEntity);

}

@Override

public Object getUserMenu() {

Map map = Maps.newHashMap();

map.put("showFlag", 1);

List menus = systemMenuMapper.selectByCondition(map);

//按层级封装,最多三级

Map result = Maps.newHashMap();

result.put("first", menus.stream().filter(n -> {

return n.getMenuLevel() == 1;

}));

result.put("second", menus.stream().filter(n -> {

return n.getMenuLevel() == 2;

}));

result.put("third", menus.stream().filter(n -> {

return n.getMenuLevel() == 3;

}));

return result;

}

}

package com.znz.service.impl;

import java.io.File;

import java.util.List;

import org.springframework.stereotype.Service;

import com.alibaba.druid.util.StringUtils;

import com.alibaba.fastjson.JSONObject;

import com.google.common.collect.Lists;

import com.znz.constant.Constant;

import com.znz.exception.ResultReturnException;

import com.znz.service.FileService;

import com.znz.util.FileUtil;

@Service

public class FileServiceImpl implements FileService {

@Override

public List getFileTreeByDir(String rootPath, String dir, String typeFilter) {

if(StringUtils.isEmpty(dir)){

if(StringUtils.isEmpty(rootPath)){

dir = Constant.DEFAULT_DIR;

} else {

dir = rootPath;

}

}

if(StringUtils.isEmpty(typeFilter)){

typeFilter = Constant.DEFAULT_TYPE;

}

File f = new File(dir);

List list = FileUtil.listFile(f, typeFilter, false);

List result = Lists.newArrayList();

list.stream().forEach(n->{

JSONObject jo = new JSONObject();

jo.put("id", n.getAbsolutePath());

jo.put("pid", n.getParentFile().getAbsolutePath());

jo.put("filePath", n.getAbsolutePath());

jo.put("fileName", n.getName());

jo.put("isDir", n.isDirectory());

result.add(jo);

});

return result;

}

@Override

public File readFile(String filePath) {

File f = new File(filePath);

if(!f.exists() || f.isDirectory()) {

throw new ResultReturnException("filePath参数异常,找不到指定的文件: " + filePath);

}

if(!f.exists() || f.isDirectory()) {

throw new ResultReturnException("读取图片异常:" + f.getName());

}

return f;

}

}

以上就是Opencv创建车牌图片识别系统方法详解的详细内容,更多关于Opencv车牌图片识别系统的资料请关注我们其它相关文章!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:【图像去噪】基于Wiener、Non-Local Means、Lucy_Richardson、Lee、kuwahara、Bilateral多种滤波器实现CT图像去噪含Matlab源码(图像去噪技术原理)
下一篇:【图像检测】基于计算机视觉实现遥感图像变换检测含Matlab源码(基于matlab的遥感图像处理)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~