Last active
April 12, 2019 16:49
-
-
Save Duologic/27f9185a565b3f32721850298db1811f to your computer and use it in GitHub Desktop.
Tesseract POC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src='https://cdn.jsdelivr.net/gh/naptha/[email protected]/dist/tesseract.min.js'></script> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/camanjs/4.0.0/caman.full.js'></script> | |
<script type="text/javascript"> | |
var stopIt = false; | |
var sleep = function (ms) { | |
return new Promise(resolve => setTimeout(resolve, ms)); | |
} | |
// crop out the required pieces | |
var captureImage = function(x, y, width, height) { | |
var video = document.getElementById("videoElement"); | |
var canvas = document.createElement("canvas"); | |
canvas.width = width; | |
canvas.height = height; | |
canvas.getContext('2d').drawImage(video, x, y, width, height, 0, 0, width, height); | |
return canvas; | |
}; | |
// render the image with Caman with random exposure and contrast | |
var renderImage = function(canvas, name, callback) { | |
var output = document.getElementById('output'); | |
var exposure = Math.floor(Math.random() * Math.floor(10))*10 | |
var contrast = Math.floor(Math.random() * Math.floor(10))*10 | |
var img = document.getElementById('image'+name+exposure+contrast); | |
if(img === null){ | |
img = document.createElement("img"); | |
img.id = 'image'+name+exposure+contrast; | |
} | |
img.src = canvas.toDataURL(); | |
output.append(img); | |
output.append(document.createElement('br')); | |
console.log(exposure); | |
console.log(contrast); | |
Caman(img, function () { | |
this.greyscale(); | |
this.exposure(exposure); | |
this.contrast(contrast); | |
this.render(callback(this.canvas)); | |
}); | |
}; | |
// do the actual OCR with Tesseract doing the heavy lifting | |
var doOCR = function(image, characters, callback) { | |
var min_length = 3; | |
Tesseract | |
.recognize(image, {tessedit_char_whitelist: characters, | |
certainty_scale: 80}) | |
.progress(function (p) { | |
/*console.log('progress', p);*/ | |
}) | |
.then(function (result) { | |
console.log('result', result); | |
var confidence = 0; | |
var best_match; | |
for(i=0; i<result.words.length; i++){ | |
var word = result.words[i]; | |
if(word.text.length > min_length && word.confidence > confidence){ | |
best_match = word; | |
} | |
} | |
callback(best_match); | |
}); | |
} | |
// tie it all together | |
var getWord = function(canvas, name, characters, callback) { | |
renderImage(canvas, name, function(canvas){ | |
var img = canvas.getContext('2d'); | |
doOCR(img, characters, function(word){ | |
if(word !== undefined) { | |
console.log('confidence', word.confidence); | |
console.log('word', word.text); | |
} | |
callback(word); | |
}); | |
}); | |
}; | |
var setClass = function(element, cls) { | |
element.classList.remove('doing'); | |
element.classList.remove('complete'); | |
element.classList.add(cls); | |
} | |
// get the words and drop the words with confidence into the <input> | |
var grab = function(canvas, elid, characters, callback) { | |
var confidence = 0 | |
var best_match = ''; | |
setClass(document.getElementById(elid), 'doing'); | |
getWord(canvas, elid, characters, function(word) { | |
if(word !== undefined && confidence < word.confidence){ | |
confidence = word.confidence; | |
best_match = word.text; | |
} | |
if(confidence > 80) { | |
document.getElementById(elid).value = word.text.toUpperCase(); | |
setClass(document.getElementById(elid), 'complete'); | |
return | |
} | |
if(confidence > 60) { | |
document.getElementById(elid).value = best_match.toUpperCase(); | |
setClass(document.getElementById(elid), 'best_match'); | |
} | |
if(confidence < 80) { | |
if(stopIt){ | |
return | |
} | |
sleep(2); | |
callback(); | |
} | |
}); | |
}; | |
var grabLicensePlate = function() { | |
var canvas = captureImage(415, 145, 120, 25); | |
var elid = 'licenseplate'; | |
var characters = '-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; | |
grab(canvas, elid, characters, grabLicensePlate) | |
}; | |
var grabChassisnumber = function() { | |
var canvas = captureImage(370, 370, 215, 30); | |
var elid = 'chassisnumber'; | |
var characters = '()ABCDEFGHJKLMNPRSTUVWXYZ0123456789' | |
grab(canvas, elid, characters, grabChassisnumber) | |
}; | |
</script> | |
<style> | |
.doing { | |
border-color: red; | |
} | |
.doing.best_match { | |
border-color: orange; | |
} | |
.complete { | |
border-color: green; | |
} | |
body { | |
margin: 0px 0px; | |
padding: 0px 0px; | |
} | |
input { | |
width: 600px; | |
font-size: 20px; | |
} | |
#videoElement, | |
.container { | |
width: 640px; | |
height: 480px; | |
} | |
#output, | |
.container { | |
position: relative; | |
} | |
#output{ | |
display: none; | |
} | |
.block { | |
border: 1px solid black; | |
position: absolute; | |
background-color: white; | |
opacity: .6; | |
} | |
.block.PLATE { | |
left: 405px; | |
top: 145px; | |
width: 140px; | |
height: 30px; | |
} | |
.block.VIN { | |
left: 365px; | |
top: 360px; | |
width: 230px; | |
height: 40px; | |
} | |
#videoElement { | |
background-color: #666; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<video autoplay="true" controls="true" id="videoElement"></video> | |
<div class="block PLATE"></div> | |
<div class="block VIN"></div> | |
</div> | |
<div id="output"></div> | |
<input type="text" id='licenseplate'/> | |
<input type="text" id='chassisnumber'/> | |
<script type="text/javascript"> | |
var video = document.querySelector("#videoElement"); | |
var constraints = { | |
video: | |
{ | |
width: 640, | |
height: 480, | |
facingMode: 'environment' | |
} | |
} | |
if (navigator.mediaDevices.getUserMedia) { | |
navigator.mediaDevices.getUserMedia(constraints) | |
.then(function(stream) { | |
video.srcObject = stream; | |
}) | |
.catch(function(err) { | |
console.log(err.name + ": " + err.message); | |
alert(err.name + ": " + err.message); | |
}); | |
} | |
video.onpause = function() { | |
stopIt = true; | |
} | |
video.onplaying = function() { | |
stopIt = false; | |
grabLicensePlate(); | |
grabChassisnumber(); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment