Canvas簡單驗證碼識別

有感於canvas無窮的魅力,使用canvas折騰了一個簡單的驗證碼識別。固然是最簡單的驗證碼識別了,不過準確率還好能達到100%。javascript

首先看一下咱們準備識別的驗證碼,綠色的背景,白色的噪點,黑色的文字(數字0-9),位置和顏色固定,沒有旋轉,夠簡單吧。html

p1

思路:java

一、收集驗證碼樣本,要包括0-9全部的數字。chrome

二、用ps等圖像處理工具分析咱們將要識別的驗證碼,得出第一個文字距離左邊的位置,字距離頂部的位置,字的寬高以及字與字之間的間隔。這個過程要儘量的精確,這是咱們後期驗證碼識別是否正確的基本。canvas

三、對驗證碼樣本進行二值化,得出每一個數字對應的二值化序列組成素材庫。dom

四、取須要識別的圖片的每一個數字的二值化序列和素材庫中的序列進行比對,比較其類似程度,得出對應的數字。工具

實現代碼:ui

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Canvas簡單驗證碼識別</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
</head>
<body>
<img src="#" id="code" align="absmiddle"  alt="">
<button id="recognize">識別</button>
<p>點擊圖片刷新驗證碼</p>
<script type="text/javascript">
	var OCR = (function(window,document,undefined){
		var offsetX,offsetY = 6,fontWidth,fontHeight,gap = 13,source,srcs,kus,codeId,recId;
		function init(codeContainerId,recognizeId){
			offsetX = 5;
			offsetY = 6
			fontWidth = 8;
			fontHeight = 10;
			gap = 13;
			source = {};
			srcs = ['images/p1.png','images/p2.png','images/p3.png','images/p4.png','images/p5.png','images/p6.png','images/p7.png','images/p8.png','images/p9.png','images/p10.png','images/p11.png','images/p12.png','images/p13.png','images/p14.png'];
			kus = [["3","2","2","1"],["4","6","7","5"],["9","8","1","6"],["0","3","5","0"]];
			codeId = codeContainerId;
			recId = recognizeId;
			initSource();
			getCode();
			addEvent();
		}
		function initSource(){
			for(var i=0;i<4;i++){
				(function(){
					addSource(srcs[i],kus[i]);
				})();
			}
		}
		function getCode(){
			var im = document.getElementById("code"),
				randPic = srcs[(~~(Math.random()*srcs.length))];
			im.src = randPic;
		}
		function addSource(pic,numArr){
			var im = new Image(),
				canvas = document.createElement("canvas"),
				ctx = canvas.getContext("2d");
			im.onload = function(){
				canvas.width = this.width;
				canvas.height = this.height;
				ctx.drawImage(im,0,0);
				var imgData = ctx.getImageData(0,0,80,20);
				imgData = binaryzationImageData(imgData);
				ctx.putImageData(imgData,0,0);
				for(var i=1;i<=4;i++){
					(function(i){
						var imgData = ctx.getImageData(offsetX+gap*(i-1)+fontWidth*(i-1),offsetY,fontWidth,fontHeight);
						!source[numArr[i-1]] && (source[numArr[i-1]] = imgData.data.join("").replace(/255/g,"1"));
					})(i);
				}
			}
			im.src = pic;
		}
		function binaryzationImageData(imgData){
			for(var i=0;i<imgData.width*imgData.height;i++){
				var r = imgData.data[i*4+0],
					g = imgData.data[i*4+1],
					b = imgData.data[i*4+2];
				var gray = 0.299 * r + 0.587 * g + 0.114 * b;
				if(gray<=130){
					gray = 0;
				}else{
					gray = 255;
				}
				imgData.data[i*4+0] = imgData.data[i*4+1] = imgData.data[i*4+2] = gray;
			}
			return imgData;
		}
		function recognize(im){
			var canvas = document.createElement("canvas"),
				ctx = canvas.getContext("2d"),
				code = '';
			canvas.width = im.width;
			canvas.height = im.height;
			ctx.drawImage(im,0,0);
			for(var i=1;i<=4;i++){
				var imgData = ctx.getImageData(offsetX+gap*(i-1)+fontWidth*(i-1),offsetY,fontWidth,fontHeight);
				imgData = binaryzationImageData(imgData);
				var str = imgData.data.join("").replace(/255/g,"1");
				for(var index in source){
					if(compare(source[index],str)>=99){
						code += index;
						break;
					}
				}
			}
			alert(code);
		}
		function getObjectLength(o){
			var len = 0;
			for(var index in o){
				if(o.hasOwnProperty(index)){
					len ++;
				}
			}
			return len;
		}
		function compare(x, y) {
			var x = x.split(""),
				y = y.split(""),
				z = 0,
				s = Math.max(x.length,y.length),
				a = x.shift(),
				b = y.shift();
			while(a !== undefined && b !== undefined) {
				if (a === b) {
					z++;
				}
				a = x.shift();
				b = y.shift();
			}
			return z/s * 100;
		}
		function addEvent(){
			document.getElementById(recId).onclick = function(){
				recognize(document.getElementById(codeId));
			}
			document.getElementById(codeId).onclick = function(){
				getCode();
			}
		}
		return { init : init }
	})(window,document);

	OCR.init("code","recognize");
</script>
</body>
</html>

在線Demo:http://demo.deanhan.cn/recognizethis

轉自:https://www.deanhan.cn/js-ocr.htmlcode

相關文章
相關標籤/搜索