使用 getuserMedia() Javascript 拍摄的分辨率错误图像



我想使用javascript getUserMedia功能从手机摄像头截取屏幕截图,但分辨率非常糟糕。

if (navigator.mediaDevices) {
// access the web cam
navigator.mediaDevices.getUserMedia({
video: {
width: { 
min: 1280,
},
height: {
min: 720,
},
facingMode: {
exact: 'environment'
}
}
}).then(function(stream) {
video.srcObject = stream;
video.addEventListener('click', takeSnapshot);
})
.catch(function(error) {
document.body.textContent = 'Could not access the camera. Error: ' + error.name;
});
}

var video = document.querySelector('video'), canvas;
function takeSnapshot(){
var img =  document.createElement('img');
var context;
var width = video.offsetWidth, height = video.offsetHeight;
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height; 
context = canvas.getContext('2d');          
context.webkitImageSmoothingEnabled = false;
context.mozImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
context.drawImage(video, 0,  0, width,  height);    
img.src = canvas.toDataURL('image/jpeg');
}

没有错误代码,但分辨率不好,我无法阅读照片的文字。 有没有一种方法可以从相机获得真实的图像质量?

MediaCapture

这就是您通过getUserMedia使用的内容。

如果您的相机仅允许 1920x1080、1280x720 和 640x480 分辨率,则媒体捕获的浏览器实现可以模拟来自 1280x720 的 480x640 源(请参阅 MediaStream(。从测试(主要是Chrome(开始,浏览器通常会将720缩小到640,然后裁剪中心。有时,当我使用虚拟相机软件时,我看到Chrome在不受支持的分辨率周围添加了人造黑色填充。客户看到成功消息和正确维度的提要,但一个人会看到质量下降。由于此模拟,您无法保证源正确或未缩放。但是,它通常会具有所要求的正确尺寸。

您可以在此处阅读有关约束的信息。它基本上归结为:给我一个接近x的分辨率。然后,浏览器通过自己的实现确定拒绝约束并引发错误、获取分辨率或模拟解决方案。

有关此设计的详细信息,请参阅媒体捕获规范。特别是:

RTCPeerConnection是一个有趣的对象,因为它的行为是 同时作为网络接收器和源 流。作为接收器,它具有源转换功能(例如, 降低比特率、放大/缩小分辨率和调整 帧速率(,并且作为源,它可以更改自己的设置 通过轨道源。

这样做的主要原因是允许n个客户端访问相同的媒体源,但可能需要不同的分辨率,比特率等,因此模拟/缩放/转换尝试解决此问题。不利的一点是,您永远不知道源分辨率是什么。

图像捕获

这可能是您的解决方案。

如果 60FPS 视频不是硬性要求,并且您在兼容性方面有余地,则可以轮询 ImageCapture 以模拟摄像机并从摄像机接收更清晰的图像。

您必须检查客户端支持,然后可能会回退到 MediaCapture。

该 API 支持控制相机功能,例如变焦、亮度、对比度、ISO 和白平衡。最重要的是,图像捕获允许您访问任何可用设备摄像头或网络摄像头的完整分辨率功能。以前在 Web 上拍摄照片的技术使用视频快照(渲染到画布的 MediaCapture(,其分辨率低于静止图像的分辨率。

https://developers.google.com/web/updates/2016/12/imagecapture

及其填充物:

https://github.com/GoogleChromeLabs/imagecapture-polyfill

我只想提一下,当在iOS上使用imagecapture-polyfill在Safari或Chrome中拍照时,我得到的图像质量非常差,直到我在获取MediaStreamTrack和调用ImageCapture构造函数之间添加了2秒的延迟。这不是一个真正的答案,因为我不知道为什么这种延迟是必要的,但也许它无论如何都可以帮助某人。

// Media constraints
const constraints = {
audio: false,
video: {
facingMode: { exact: 'environment' },   // Use the back camera (otherwise the front camera will be used by default)
width: { ideal: 99999 },
height: { ideal: 99999 }
}
};
// MediaStream
navigator.mediaDevices.getUserMedia(constraints).then(async mediaStream => {    // The user will get a notification on the mobile device that this interface is being used
// MediaStreamTrack
const mediaStreamTrack = mediaStream.getVideoTracks()[0];
// ImageCapture
await new Promise(resolve => setTimeout(resolve, 2000));    // For an unknown reason, adding this delay greatly increases image quality on iOS
this.imageCapture = new ImageCapture(mediaStreamTrack);     // Note that iOS doesn't support ImageCapture [as of 2022-11-08] and instead uses the libs/imagecapture-polyfill.js to obtain an image by using the <canvas> instead
// Take picture
return this.imageCapture.takePhoto().then(blob => {
// Upload photo right away
if (blob) {

我还编辑了imagecapture-polyfill.js代码以获得jpeg而不是png,从而大大减少了文件大小。

self.canvasElement.toBlob(resolve, 'image/jpeg'); // [YB 2022-11-02: Output jpeg instead of png]

最新更新