欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-24 10:55:54
目录前言包含功能软件版本软件架构参考文档效果图展示车牌检测过程图片车牌文字识别过程部分核心代码前言这是一个基于spring boot + maven + opencv 实现的图像识别及训练的demo项...

前言

这是一个基于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.4
  • spring boot 2.1.5.release
  • yx-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官方

效果图展示

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

车牌识别

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

黄牌识别

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

绿牌识别

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

夜间识别

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

图片提取工具

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

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

人脸识别

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

训练

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

接口文档

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

车牌检测过程

高斯模糊:

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

图像灰度化:

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

sobel 算子:

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

图像二值化:

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

图像闭操作:

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

二值图像降噪:

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

提取外部轮廓:

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

外部轮廓筛选:

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

切图:

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

重置切图尺寸:

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

车牌检测结果:

图片车牌文字识别过程

车牌检测结果:

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

debug_char_threshold:

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

debug_char_clearliuding:

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

debug_specmat:

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

debug_chinesemat:

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

debug_char_auxroi:

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

部分核心代码

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<tempplatefileentity> resultlist = lists.newarraylist();
 
        // 获取basedir下第一层级的目录, 仅获取文件夹,不递归子目录,遍历
        list<file> folderlist = fileutil.listfile(basedir, ";", false);
        folderlist.parallelstream().foreach(folder -> {
            if(!folder.getname().equals("temp")) {
                // 遍历每一个文件夹, 递归获取文件夹下的图片
                list<file> 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<string, object> parammap = maps.newhashmap();
        parammap.put("filepath", filepath);
        list<platefileentity> 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<string> debugfiles = new vector<string>();
            fileutil.getfiles(entity.gettemppath(), debugfiles);
            entity.setdebugfiles(debugfiles);
        }
        return entity;
    }
 
    @override
    public object recogniseall() {
        // 查询到还没有进行车牌识别的图片
        list<platefileentity> 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<mat> dst = new vector<mat>();
        plateutil.getplatemat(targetpath, dst, debug, temppath);
 
        set<string> 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<string, object> 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<string, object> 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<platetypeentity> querybypage(integer pageno, integer pagesize, map<string, object> map) {
    	pagehelper.startpage(pageno, pagesize);
		pageinfo<platetypeentity> page = new pageinfo(platetypemapper.selectbycondition(map));
		return page;
    }
    
    @override
    public list<platetypeentity> querybycondition(map<string, object> map) {
		return platetypemapper.selectbycondition(map);
    }
    
    @override
    @transactional(propagation = propagation.required)
    public map<string, object> save(platetypeentity platetypeentity) {
    	platetypeentity.setid(0);
    	platetypemapper.insertselective(platetypeentity);
    	
    	map<string, object> 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<systemmenuentity> querybypage(integer pageno, integer pagesize, map<string, object> map) {
    	pagehelper.startpage(pageno, pagesize);
		pageinfo<systemmenuentity> page = new pageinfo(systemmenumapper.selectbycondition(map));
		return page;
    }
    
    @override
	public list<systemmenuentity> querybycondition(map<string, object> map) {
		return systemmenumapper.selectbycondition(map);
	}
    
    @override
    @transactional(propagation = propagation.required)
    public map<string, object> save(systemmenuentity entity) {
    	entity.setid(0);
    	systemmenumapper.insertselective(entity);
    	
    	map<string, object> 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<string, object> map = maps.newhashmap();
        map.put("showflag", 1);
        list<systemmenuentity> menus = systemmenumapper.selectbycondition(map);
        
        //按层级封装,最多三级
        map<string, object> 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<jsonobject> 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<file> list = fileutil.listfile(f, typefilter, false);
        list<jsonobject> 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车牌图片识别系统的资料请关注其它相关文章!