汉字验证码识别——OpenCV(JAVA环境)

一、概述

1.1 问题描述

       验证码类型如图1所示,需要从图中六个汉字中识别出两个相同的汉字,汉字中有繁体字,字体经过扭曲和旋转处理,汉字周围存在粗细不同,颜色各异的干扰线。

图1

1.2 背景概述

       识别常见的验证码一般需要经过以下步骤:

  1. 预处理,包括去灰度、调节亮度以及对比度、腐蚀膨胀、滤波去噪点、去干扰、二值化等,其中去干扰的方式有很多种,例如干扰线比较细而验证码比较粗,可以检测单个像素点相邻像素与该像素间是否有颜色突变,若有则认为是干扰线,或者干扰线与验证码之间有明显的颜色差异,可以根据颜色加以区分;
  2. 分割,位置固定的可以按确定尺寸分割,不固定位置的可以利用轮廓检测技术确定大致位置,再进行分割,分割效果受验证码图片中字符间的紧密程度以及预处理效果的影响;
  3. 训练,将分割得到的样本利用相应算法进行训练,提高识别率;
  4. 识别

       验证码形式各异,基本没有统一的方式解决所有类型的验证码识别问题,需要根据具体情况具体分析。

1.3 解决思路

      对于图1所示的验证码类型,背景颜色为白色,汉字颜色鲜明,噪点也非常少,可以把重点放在如何去除干扰线的问题上,仔细观察可以发现干扰线的颜色基本与汉字的颜色不同,且图片基本可以划分为6个区域,不同验证码图片在相同区域内,汉字颜色是相同的。而最终的目的也只是找出相同的汉字,所以可以把问题简化为从六张图片中找出两个最相似的图片。具体的解决思路如下:

  1. 将一张验证码图片等比例分割成6张含有单个汉字的图片;
  2. 对每张图片进行预处理,拾取汉字颜色作为目标颜色,去除图片中其他颜色以达到去干扰的目的,由于图片颜色通常都会进行渐变处理,所以按照RGB方式处理将不太方便,而本文采用HSV方式来表征颜色——HSV对肉眼可见的颜色可以通过具体的范围值加以区分。最后将去除干扰后的图片进行二值化处理;
  3. 由于图片中的汉字进行了扭曲和旋转处理,汉字在图片中的相对位置也有所变化,所以无法通过比较对应位置像素点颜色的方式加以比较。本文采用图像识别中的SIFT算法——SIFT算法具有尺度不变性和旋转不变性,分别提取图片中的特征值并两两比较,找出并统计两张图片中相似的特征点个数,个数最多的就认为是相似度最高的两张图片,即两个相同的汉字。

二、具体过程

2.1 配置opencv(JAVA环境)

  1. 下载opencv 2.4.13.6并配置环境变量https://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.13/opencv-2.4.13.6-vc14.exe/download
    由于需要用到SIFT算法,而opencv 3.0以上版本将SIFT算法移至第三方库中,需要重新编译才能使用,为了方便,本文使用opencv 2.4.13.6 这一版本。
    ——path配置到opencv的bin目录下。
  2. 添加opencv的jar包,并静态加载dll文件
  	String x64 = " .../opencv/build/java/x64/";
  	System.load(x64 + "opencv_java2413.dll");

       或者在添加jar包后再在IDEA中配置Edit Configuration–VM options:-Djava.library.path= …\opencv\build\java\x64,再静态加载library

	System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

2.2 分割

	//读取图片
	Mat src = imread(file.getAbsolutePath());
    int eachHeight=src.rows()/2;
	int eachWidth=src.cols()/3;
	Rect rect;
	Mat dst;
	for (int i = 0; i < 6; i++) {
		//按起始坐标及宽高大小进行分割
		rect = new Rect((i % 3) * eachWidth, (i / 3) *eachHeight,eachWidth,eachHeight);
		dst= new Mat(src,rect);
	}

        分割效果如下:

图2

2.3 去干扰

	//将RGB图片转化为HSV格式
	Imgproc.cvtColor(image, dst, Imgproc.COLOR_BGR2HSV);
	Scalar lowerScalar=null;
	Scalar upperScalar=null;
	//根据字体颜色设置目标颜色的数值范围
	switch (index){
		//yellow
		case 0:
		case 4:
				lowerScalar=new Scalar(26,60,60);
				upperScalar=new Scalar(33,255,220);
				break;
		//purple
		case 1:
		case 5:
				lowerScalar=new Scalar(125,10,10);
				upperScalar=new Scalar(155,255,220);
				break;
		//green
		case 2:
				lowerScalar=new Scalar(35,43,46);
				upperScalar=new Scalar(77,255,220);
				break;
		//blue
		case 3:
				lowerScalar=new Scalar(100,43,46);
				upperScalar=new Scalar(124,255,220);
	}
	//只留下目标颜色的内容
	Core.inRange(dst,lowerScalar,upperScalar,dst);

        inRange之后的效果如下,在一定程度上将干扰线去除:

图3

2.4 识别

2.4.1 提取特征点

	//灰度图转换
	Imgproc.cvtColor(image, image, Imgproc.COLOR_RGB2GRAY);
	//提取特征点
	MatOfKeyPoint keyPoint =new MatOfKeyPoint();
	FeatureDetector FeatureDetector=FeatureDetector.create(FeatureDetector.SIFT);
	DescriptorExtractor descriptorExtractor=DescriptorExtractor.create(DescriptorExtractor.SIFT);
	FeatureDetector.detect(image,keyPoint);

	//特征点描述,为下边的特征点匹配做准备
	Mat imageDesc=new Mat();
	descriptorExtractor.compute(image,keyPoint,imageDesc);

2.4.2 特征点匹配

	DescriptorMatcher descriptorMatcher= descriptorMatcher=DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
	//匹配器训练
	List<Mat> matList=new ArrayList<>();
	matList.add(imageDesc1);
	descriptorMatcher.add(matList);
	descriptorMatcher.train();
	
	//得到最相近和次相近的匹配点
	List<MatOfDMatch> matches=new ArrayList<>();
	descriptorMatcher.knnMatch(imageDesc2,matches,2);
	
	DMatch[] dMatches=null;
	 List<DMatch> goodMatch = new LinkedList<>();
	// Lowe's algorithm,获取优秀匹配点
	for (int i = 0; i < matches.size(); i++) {
		dMatches=matches.get(i).toArray();
		//比较最接近和次接近匹配点的距离差,若比例系数小于0.8则认为是优秀匹配点
		if(dMatches[0].distance<0.8*dMatches[1].distance) {
			goodMatch.add(dMatches[0]);
		}
	}
	
	MatOfDMatch goodMatOfDMatch=new MatOfDMatch();
	goodMatOfDMatch.fromList(goodMatch);
	Mat OutImage = new Mat();
	//得到最终匹配图
	Features2d.drawMatches(img2, keyPoint2, img1, keyPoint1, goodMatOfDMatch, OutImage);

        最终的匹配点数为:

012345
16
293
3337
49541
55313283

       匹配点数最多的前两组图片分别为 Pic.2Pic.5Pic.3Pic.5,具体情况如下所示:

图4

三、总结

  1. 如果干扰线穿插在汉字周围,且条数比较多,那么根据颜色进行筛选很容易将汉字笔画打断成一个个零散的点,识别率降低;
  2. 不同汉字之间也能找到对应的特征匹配点;
  3. 笔画越多,结构相近的汉字可能找到的特征匹配点越多;
  4. 目标汉字如果笔画少,而干扰汉字笔画多,且结构相近,则很可能得不到想要的结果;
  5. 初步测试该方法的验证码识别率在 60% 以上。
### 回答1: 人脸识别系统是一种利用计算机技术对人脸进行识别和验证的系统。其中,opencv人脸检测是一种基于opencv库的人脸检测算法,可以通过计算机视觉技术对图像或视频中的人脸进行检测和识别,具有高效、准确、实时等特点,广泛应用于安防、人机交互、智能家居等领域。 ### 回答2: 人脸识别系统是一种可以通过对人脸进行特征提取、比对和识别的技术,目前已广泛应用在生物特征识别、安防监控等领域。而OpenCV人脸检测是在计算机视觉领域中应用广泛的一种算法。 OpenCV是一个开源计算机视觉库,提供了很多图像处理和机器视觉算法,其中人脸检测是OpenCV中应用最广泛的算法之一。OpenCV人脸检测的基本思路是利用Haar-like特征进行人脸检测。 Haar-like特征是一组由Viola和Jones在2001年提出的能够对图像进行分类的特征,主要由白色和黑色的矩形块组成。这些特征可以在人脸区域和非人脸区域产生显著的区别,因此可以用来进行人脸检测。在OpenCV中,利用Adaboost算法来训练分类器,从而实现人脸检测。 OpenCV人脸检测有以下几个优点: 1. 检测速度快:OpenCV的人脸检测算法可以实现实时检测,能够处理实时视频,并对每一帧进行人脸检测。 2. 高检测率和低误检率:OpenCV人脸检测算法经过大量的训练和优化,能够准确地检测人脸,且误检率低。 3. 应用广泛:由于OpenCV是一个开源库,其特性与应用广泛,可以应用于不同领域的人脸检测。 4. 动态人脸识别OpenCV人脸检测算法能够在不同角度、不同光照条件下对人脸进行检测和识别。 5. 简单易用:OpenCV提供了简单的API调用,即可完成人脸检测。同时,OpenCV还提供了丰富的文档和示例,使得人脸检测的实现变得更加简单。 总之,OpenCV人脸检测算法是一种可靠的人脸检测技术,可以广泛应用于不同领域。通过不断地优化和训练,OpenCV的人脸检测算法仍有望在未来得到进一步的提升。 ### 回答3: 人脸识别是一种高科技应用,它可以在不进行人工干预的情况下识别人们的身份。在过去的几年里,随着计算机技术的不断发展壮大,人脸识别技术得到了迅速的发展和应用。 Opencv人脸检测是一种常见的人脸识别技术,它可以快速、准确地检测人脸并提取出相关的数据信息。Opencv人脸检测使用基于统计学的模型,可以快速检索出整张图像中的所有人脸,并用边缘高亮标出。其识别空间包括面部区域,由眼睛、口鼻、眉毛和脸型等特征组成。而为了提高识别的准确度,Opencv人脸检测还涉及到其他一些算法,比如特征提取、人脸分类和智能识别Opencv人脸检测是非常重要的安全工具,它可以用于认证和安全访问控制、图像搜索和媒体应用。在计算机视觉和机器学习领域,Opencv人脸检测是重要的探究之一,因为对于如何解决图像多样性问题的机器人操作的研究而言,人脸检测是非常关键的。Opencv人脸检测还可以用于许多领域,如自然语言处理、光学字符识别等,进一步方便了计算机与人类之间的交流。 在未来,Opencv人脸检测技术有望得以发展与扩展,实现更加准确、精密的人脸识别,为广大人民群众的生产生活提供更多的便利与保障。诚然,Opencv人脸检测仅仅是人脸识别的一个小部分,但它在其中占有重要的地位,在此我们真诚地期待着Opencv人脸检测技术能够顺利地实现更深入的发展。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值