/
imageCapture.html
465 lines (452 loc) · 16 KB
/
imageCapture.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
<!DOCTYPE html>
<html>
<!--
1、二值化 需要高分辨率的图片,二值化精度高,位深度导致彩色图片过大
2、dpi切换(前端目前还没有找到方法更改dpi)
3、分辨率切换,考虑提供常用的分辨率(解决设备拍照画面不全的问题)
4、切换视频源的弹窗确认操作,名称无法显示(是否支持 自定义)
-->
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- 暂时不用 -->
<!-- <script src="ocrad.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/camanjs/4.1.2/caman.full.min.js">
</script>
<title>摄像头拍照</title>
</head>
<body>
<div>
<video id="video" width="800" height="600" controls="">
</video>
</div>
<br />
<div>
<input type="button" title="开启摄像头" value="拍照识别" id="capture" />
<input type="button" title="1" value="切视频源" id="changeV" />
<select name="" id="changDpi">
<option value="1600,1200">标清</option>
<option value="2400,1800">高清</option>
</select>
<select name="" id="videoSources">
</select>
<input type="button" id="save" type="button" value="下载图片" />
<input id="upFile" type="file" accept="image/PNG" value="上传图片" name="file" />
<input type="button" id="clearImg" type="button" value="清除采集项" />
<input type="button" id="grayScale" type="button" value="灰度" />
<input type="button" id="black" type="button" value="二值化(黑白)" />
<!-- <input type="button" id="color" type="button" value="原图(彩色)" />
<input type="button" id="stop" type="button" value="停止拍摄" /> -->
</div>
<!-- 缩放 -->
<canvas id="canvas" width="800" height="600"></canvas>
<canvas id="blackCanvas" width="680" height="420"></canvas>
<script>
window.onload = function () {
//访问用户媒体设备的兼容方法
function getUserMedia(constraints, success, error) {
if (navigator.mediaDevices.getUserMedia) {
//最新的标准API
//alert("最新的标准API")
navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
} else if (navigator.webkitGetUserMedia) {
//webkit核心浏览器
//alert("webkit核心浏览器")
navigator.webkitGetUserMedia(constraints, success, error)
} else if (navigator.mozGetUserMedia) {
//firfox浏览器
//alert("firfox浏览器")
navigator.mozGetUserMedia(constraints, success, error);
} else if (navigator.getUserMedia) {
//旧版API
//alert("旧版API")
navigator.getUserMedia(constraints, success, error);
}
}
//获取页面对象
let video = document.getElementById('video');
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
let model = document.getElementById('modelSet');
let imageWidth =1600;
let imageHeight = 1200;
let scaleRate = 2;
//成功加载设备,播放流文件
function success(stream) {
//兼容webkit核心浏览器
let CompatibleURL = window.URL || window.webkitURL;
//将视频流设置为video元素的源
//video.src = CompatibleURL.createObjectURL(stream);
console.log(video);
console.log(stream)
video.srcObject = stream;
video.play();
}
//出现错误提示
function error(error) {
console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
}
if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator
.mozGetUserMedia) {
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
console.log("enumerateDevices() not supported.");
return;
}
// 列出摄像头和麦克风
var exArray = [];
var checkIndex;
//cyn mark
var select = document.getElementById("select");
//当前设备支持的分辨率
let videoSourcesCount = 1;
navigator.mediaDevices.enumerateDevices().then(function (devices) {
devices.forEach(function (device) {
console.log(device.kind + ": " + device.label +
" id = " + device.deviceId);
if (device.kind == "videoinput") {
//alert(device.label.toString());
exArray.push(device.deviceId);
//下拉框添加设备列表
var videoSources = document.getElementById("videoSources");
var option=document.createElement("option");
option.value= device.deviceId;
var node=document.createTextNode("设备" + videoSourcesCount + device.label+" ID:"+device.deviceId.substr(0,6));
option.appendChild(node);
videoSources.appendChild(option);
videoSourcesCount++;
}
});
checkIndex = exArray.keys();
var mediaOpts = {
video: {
// deviceId: {
// exact: exArray[0]
// },
width: imageWidth,
height: imageHeight
}
};
//调用用户媒体设备, 访问摄像头
getUserMedia(mediaOpts, success, error);
})
.catch(function (err) {
console.log(err.name + ": " + err.message);
});
} else {
alert('不支持访问用户媒体');
}
var img = new Image();
//拍照
document.getElementById('capture').addEventListener('click', function () {
canvas.width = imageWidth;
canvas.height = imageHeight;
context.drawImage(video, 0, 0, imageWidth, imageHeight);
// canvas转为blob并上传
canvas.toBlob(function (blob) {
console.log("blob");
console.log(blob)
// // 图片ajax上传
// var xhr = new XMLHttpRequest();
// // 开始上传
// xhr.open("POST", 'upload.php', true);
// xhr.send(blob);
});
var scale = ((video.width* video.height)/(imageWidth*imageHeight) ) * scaleRate
//console.log(video.width+" "+video.height+" "+imageWidth+" "+imageHeight);
//设置缩放
canvas.style="transform: scale("+scale+");transform-origin: 0 0;";
//canvas.style="transform: scale(0.5);transform-origin: 0 0;";
});
//切换视频源
document.getElementById('changeV').addEventListener('click', function () {
var arrayIndex = checkIndex.next().value;
if (arrayIndex == undefined) {
checkIndex = exArray.keys();
}
var mediaOptsT = {
video: {
deviceId: {
exact: exArray[arrayIndex]
},
}
};
getUserMedia(mediaOptsT, success, error);
});
//选择视频源
document.getElementById('videoSources').addEventListener('change', function () {
changeDpiSources ();
});
//切换分辨率
document.getElementById('changDpi').addEventListener('change', function () {
//切分辨率,视频源需要重新加载
changeDpiSources ();
});
function changeDpiSources (){
//分辨率
var dpi = document.getElementById("changDpi");
//视频源
var videoSources = document.getElementById("videoSources");
var changeWidth = dpi.value.split(",")[0];
var changeHeight = dpi.value.split(",")[1];
if(changeWidth=="1600"){
scaleRate =2;
}else if(changeWidth=="2400"){
scaleRate =3;
}
imageHeight = changeHeight;
imageWidth = changeWidth;
var mediaOptsT = {
video: {
width:imageWidth,
height: imageHeight,
deviceId: videoSources.value
}
};
console.log(mediaOptsT);
getUserMedia(mediaOptsT, success, error);
}
//文件保存下载
document.getElementById('save').addEventListener('click',function (){
//上传时判断是否拍照
var emptyCV = document.createElement('canvas');//系统获取一个空canvas对象
emptyCV.width = canvas.width;
emptyCV.height = canvas.height;
if (canvas.toDataURL() == emptyCV.toDataURL()) {
alert("未采集!无法下载!");
return;
}
//保存图片格式
var type = 'jpg';
var _fixType = function(type) {
type = type.toLowerCase().replace(/jpg/i, 'jpeg');
var r = type.match(/png|jpeg|bmp|gif/)[0];
return 'image/' + r;
}
//获取canvas标签里的图片内容
var dataURL = document.getElementById('canvas').toDataURL("image/jpeg",0.3);
//dataURL = dataURL.replace(_fixType(type),'image/octet-stream');
var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
save_link.href = dataURL;
save_link.download = (new Date()).getTime() + '.' + type;;
//触发下载
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
save_link.dispatchEvent(event);
});
//32位转16位
function bit32to16(chunk) {
const b16 = new Int16Array(chunk.byteLength / 4);
const dv = new DataView(chunk.buffer);
for (let i = 0, offset = 0; offset < chunk.byteLength; i++, offset += 4){
const v = dv.getFloat32(offset, true);
b16[i] = v > 0 ? v * 32767 : v * 32768;
}
return b16.buffer
}
//清除已拍图片
document.getElementById('clearImg').addEventListener('click',function () {
var c=document.getElementById("canvas");
var cxt=c.getContext("2d");
cxt.clearRect(0,0,c.width,c.height);
})
//停止
//采集列表
var ScanImageListJson = {
"ScanImageList": {
"count": "4",
"branchNo": "1",
"custCode": "100267",
"businessArchId": "201907120000000002",
"currentItemIndex": "0",
"TImage": [
{
"index": "1",
"archImageNo": "03",
"imageName": "休眠账户激活申请表",
"imageSet": "2",
"imageDpi": "0",
"imageType": "1",
"haveScan": "1",
"fileSize": "112",
"lowFileSize": "111",
"filePath": " ",
"importLocalFlag": "0",
"datewaterFlag": "0",
"pageNum": "1"
},
{
"index": "2",
"archImageNo": "06",
"imageName": "合并证券账户申请表",
"imageSet": "1",
"imageDpi": "100",
"imageType": "1",
"haveScan": "1",
"fileSize": "5000",
"lowFileSize": "0",
"filePath": "http://10.20.27.95/group1/M00/00/33/oYYBAF0n6YaEaIlAAAAAAAAAAAA808.tif",
"importLocalFlag": "0",
"datewaterFlag": "1",
"pageNum": "3"
},
{
"index": "3",
"archImageNo": "05",
"imageName": "注销证券账户申请表",
"imageSet": "2",
"imageDpi": "200",
"imageType": "1",
"haveScan": "1",
"fileSize": "1000",
"lowFileSize": "0",
"filePath": "http://10.20.27.95/group1/M00/00/33/ooYBAF0n6YaEKA01AAAAAAAAAAA490.tif",
"importLocalFlag": "0",
"datewaterFlag": "0",
"pageNum": "1"
},
{
"index": "0",
"archImageNo": "9A",
"imageName": "证券账户业务申请表(适用于办理证券账户查询、变更、休眠激活、注销、网络服务业务)",
"imageSet": "0",
"imageDpi": "0",
"imageType": "6",
"haveScan": "1",
"fileSize": "0",
"lowFileSize": "0",
"filePath": "http://10.20.27.95/group1/M00/00/33/oYYBAF0n6miENdIEAAAAAAAAAAA403.pdf",
"importLocalFlag": "0",
"datewaterFlag": "0",
"pageNum": "1"
}
]
}
};
// var resultS = JSON.parse(ScanImageListJson);
//原图
let colorImageCv= canvas;
//灰度化
function getGrayScaleImage(){
//彩色图像灰度化
//取得图像数据
var canvasData=document.getElementById("canvas");
var cxt=canvasData.getContext("2d");
var canvasData = cxt.getImageData(0, 0, canvas.width, canvas.height);
//这个循环是取得图像的每一个点,在计算灰度后将灰度设置给原图像
for (var x = 0; x < canvasData.width; x++) {
//alert("x="+x);
for (var y = 0; y < canvasData.height; y++) {
//alert("y="+y);
// Index of the pixel in the array
var idx = (x + y * canvas.width) * 4;
// The RGB values
var r = canvasData.data[idx + 0];
var g = canvasData.data[idx + 1];
var b = canvasData.data[idx + 2];
//更新图像数据
var gray = CalculateGrayValue(r , g , b);
canvasData.data[idx + 0] = gray;
canvasData.data[idx + 1] = gray;
canvasData.data[idx + 2] = gray;
}
}
cxt.putImageData(canvasData, 0, 0);
//计算图像的灰度值,公式为:Gray = R*0.299 + G*0.587 + B*0.114
function CalculateGrayValue(rValue,gValue,bValue){
return parseInt(rValue * 0.299 + gValue * 0.587 + bValue * 0.114);
}
return [canvasData,cxt];
}
//添加点击事件
document.getElementById('grayScale').addEventListener('click',function () {
getGrayScaleImage();
})
//二值化
//一维OTSU图像处理算法
function OTSUAlgorithm(){
var m_pFstdHistogram = new Array();//表示灰度值的分布点概率
var m_pFGrayAccu = new Array();//其中每一个值等于m_pFstdHistogram中从0到当前下标值的和
var m_pFGrayAve = new Array();//其中每一值等于m_pFstdHistogram中从0到当前指定下标值*对应的下标之和
var m_pAverage=0;//值为m_pFstdHistogram【256】中每一点的分布概率*当前下标之和
var m_pHistogram = new Array();//灰度直方图
var i,j;
var temp=0,fMax=0;//定义一个临时变量和一个最大类间方差的值
var nThresh = 0;//最优阀值
//获取灰度图像的信息 //获取图像的灰度图像的信息
function GetGrayImageInfo(){
return getGrayScaleImage();
}
var imageInfo = GetGrayImageInfo();
if(imageInfo == null){
window.alert("图像还没有转化为灰度图像!");
return;
}
//初始化各项参数
for(i=0; i<256; i++){
m_pFstdHistogram[i] = 0;
m_pFGrayAccu[i] = 0;
m_pFGrayAve[i] = 0;
m_pHistogram[i] = 0;
}
//获取图像信息
var canvasData = imageInfo[0];
//获取图像的像素
var pixels = canvasData.data;
//下面统计图像的灰度分布信息
for(i=0; i<pixels.length; i+=4){
//获取r的像素值,因为灰度图像,r=g=b,所以取第一个即可
var r = pixels[i];
m_pHistogram[r]++;
}
//下面计算每一个灰度点在图像中出现的概率
var size = canvasData.width * canvasData.height;
for(i=0; i<256; i++){
m_pFstdHistogram[i] = m_pHistogram[i] / size;
}
//下面开始计算m_pFGrayAccu和m_pFGrayAve和m_pAverage的值
for(i=0; i<256; i++){
for(j=0; j<=i; j++){
//计算m_pFGaryAccu[256]
m_pFGrayAccu[i] += m_pFstdHistogram[j];
//计算m_pFGrayAve[256]
m_pFGrayAve[i] += j * m_pFstdHistogram[j];
}
//计算平均值
m_pAverage += i * m_pFstdHistogram[i];
}
//下面开始就算OSTU的值,从0-255个值中分别计算ostu并寻找出最大值作为分割阀值
for (i = 0 ; i < 256 ; i++){
temp = (m_pAverage * m_pFGrayAccu[i] - m_pFGrayAve[i])
* (m_pAverage * m_pFGrayAccu[i] - m_pFGrayAve[i])
/ (m_pFGrayAccu[i] * (1 - m_pFGrayAccu[i]));
if (temp > fMax){
fMax = temp;
nThresh = i;
}
}
//下面执行二值化过程
for(i=0; i<canvasData.width; i++){
for(j=0; j<canvasData.height; j++){
//取得每一点的位置
var ids = (i + j*canvasData.width)*4;
//取得像素的R分量的值
var r = canvasData.data[ids];
//与阀值进行比较,如果小于阀值,那么将改点置为0,否则置为255
var gray = r>nThresh?255:0;
canvasData.data[ids+0] = gray;
canvasData.data[ids+1] = gray;
canvasData.data[ids+2] = gray;
}
}
//显示二值化图像
var newImage = document.getElementById('canvas').getContext('2d');
newImage.putImageData(canvasData,0,0);
}
document.getElementById('black').addEventListener('click',function () {
OTSUAlgorithm();
})
}
</script>
</body>
</html>