ถ่ายรูปและควบคุมการตั้งค่ากล้อง

Miguel Casas-Sanchez
Sam Dutton
Sam Dutton
François Beaufort
François Beaufort

การจับภาพเป็น API สำหรับถ่ายภาพนิ่งและกำหนดค่าฮาร์ดแวร์กล้อง API นี้มีให้บริการใน Chrome 59 ใน Android และเดสก์ท็อป นอกจากนี้ เรายังได้เผยแพร่ไลบรารี polyfill ของ ImageCapture ด้วย

API ช่วยให้ควบคุมฟีเจอร์ต่างๆ ของกล้อง เช่น การซูม, ความสว่าง, คอนทราสต์, ISO และไวท์บาลานซ์ได้ และเหนือสิ่งอื่นใด การจับภาพยังช่วยให้คุณ เข้าถึงความสามารถแบบเต็มความละเอียดของกล้องหรือเว็บแคมที่มีอยู่ได้ เทคนิคก่อนหน้านี้ในการถ่ายรูปบนเว็บได้ใช้สแนปชอ��วิดีโอ ซึ่งมีความละเอียดต่ำกว่าสำหรับภาพนิ่ง

ออบเจ็กต์ ImageCapture สร้างขึ้นโดยมี MediaStreamTrack เป็นแหล่งที่มา จากนั้น API จะมีวิธีการจับภาพ 2 วิธี ได้แก่ takePhoto() และ grabFrame() และวิธีดึงข้อมูลความสามารถและการตั้งค่าของกล้อง รวมถึงเปลี่ยนการตั้งค่าเหล่านั้น

การก่อสร้าง

Image Capture API มีสิทธิ์เข้าถึงกล้องผ่าน MediaStreamTrack ที่ได้รับจาก getUserMedia()

navigator.mediaDevices.getUserMedia({video: true})
    .then(gotMedia)
    .catch(error => console.error('getUserMedia() error:', error));

function gotMedia(mediaStream) {
    const mediaStreamTrack = mediaStream.getVideoTracks()[0];
    const imageCapture = new ImageCapture(mediaStreamTrack);
    console.log(imageCapture);
}

คุณสามารถลองใช้โค้ดนี้ได้จากคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บ

จับภาพ

การจับภาพทำได้ 2 วิธี ได้แก่ การจับภาพแบบเต็มเฟรมและการจับภาพด่วน takePhoto() แสดงผล Blob ผลที่ได้จากการรับแสงเดี่ยวของภาพถ่าย ซึ่งดาวน์โหลด จัดเก็บโดยเบราว์เซอร์ หรือแสดงไว้ในองค์ประกอบ <img> ได้ วิธีนี้ใช้ความละเอียดของกล้องถ่ายภาพสูงสุดที่มี เช่น

const img = document.querySelector('img');
// ...
imageCapture.takePhoto()
    .then(blob => {
    img.src = URL.createObjectURL(blob);
    img.onload = () => { URL.revokeObjectURL(this.src); }
    })
    .catch(error => console.error('takePhoto() error:', error));

grabFrame() จะแสดงผลออบเจ็กต์ ImageBitmap ซึ่งเป็นภาพรวมของวิดีโอสด ซึ่งอาจวาดบน <canvas> แล้วผ่านการประมวลผลหลังการเลือกสีเพื่อเปลี่ยนค่าสี โปรดทราบว่า ImageBitmap จะมีเฉพาะความละเอียดของแหล่งที่มาของวิดีโอ ซึ่งโดยปกติจะต่ำกว่าความสามารถในการถ่ายภาพนิ่งของกล้อง เช่น

const canvas = document.querySelector('canvas');
// ...
imageCapture.grabFrame()
    .then(imageBitmap => {
    canvas.width = imageBitmap.width;
    canvas.height = imageBitmap.height;
    canvas.getContext('2d').drawImage(imageBitmap, 0, 0);
    })
    .catch(error => console.error('grabFrame() error:', error));

ความสามารถและการตั้งค่า

คุณเปลี่ยนแปลงการตั้งค่าการบันทึกได้หลายวิธี ขึ้นอยู่กับว่าการเปลี่ยนแปลงจะแสดงใน MediaStreamTrack หรือเห็นหลังจาก takePhoto() เท่านั้น ตัวอย่างเช่น การเปลี่ยนแปลงในระดับ zoom จะมีผลกับ MediaStreamTrack ทันที ในขณะที่การลดตาแดงเมื่อตั้งค่าจะมีผลขณะถ่ายภาพเท่านั้น

ความสามารถและการตั้งค่ากล้องแบบ "สด" จะได้รับการปรับแต่งผ่านการแสดงตัวอย่าง MediaStreamTrack: MediaStreamTrack.getCapabilities() แสดงผลพจนานุ��รม MediaTrackCapabilities พร้อมความสามารถที่รองรับที่เป็นรูปธรรมและช่วงหรือค่าที่อนุญาต เช่น ช่วงการซูมที่รองรับหรือโหมดไวท์บาลานซ์ที่อนุญาต ที่สอดคล้องกัน MediaStreamTrack.getSettings() จะแสดงผล MediaTrackSettings พร้อมการตั้งค่าปัจจุบันที่เป็นรูปธรรม โหมดซูม ความสว่าง และไฟฉายอยู่ใน หมวดหมู่นี้ ตัวอย่างเช่น

var zoomSlider = document.querySelector('input[type=range]');
// ...
const capabilities = mediaStreamTrack.getCapabilities();
const settings = mediaStreamTrack.getSettings();
if (capabilities.zoom) {
    zoomSlider.min = capabilities.zoom.min;
    zoomSlider.max = capabilities.zoom.max;
    zoomSlider.step = capabilities.zoom.step;
    zoomSlider.value = settings.zoom;
}

ความสามารถและการตั้งค่ากล้องแบบ "ไม่ถ่ายทอดสด" ได้รับการจัดการผ่านออบเจ็กต์ ImageCapture: ImageCapture.getPhotoCapabilities() แสดงผลออบเจ็กต์ PhotoCapabilities ที่ให้สิทธิ์เข้าถึงความสามารถของกล้องที่พร้อมใช้งานแบบ "ไม่ถ่ายทอดสด" ที่สอดคล้องกัน เริ่มตั้งแต่ Chrome 61 เป็นต้นไป ImageCapture.getPhotoSettings() จะแสดงผลออบเจ็กต์ PhotoSettings พร้อมการตั้งค่าปัจจุบันที่เป็นรูปธรรม ความละเอียดของรูปภาพ การลดตาแดง และโหมดแฟลช (ยกเว้นไฟฉาย) จะอยู่ในส่วนนี้ ตัวอย่างเช่น

var widthSlider = document.querySelector('input[type=range]');
// ...
imageCapture.getPhotoCapabilities()
    .then(function(photoCapabilities) {
    widthSlider.min = photoCapabilities.imageWidth.min;
    widthSlider.max = photoCapabilities.imageWidth.max;
    widthSlider.step = photoCapabilities.imageWidth.step;
    return imageCapture.getPhotoSettings();
    })
    .then(function(photoSettings) {
    widthSlider.value = photoSettings.imageWidth;
    })
    .catch(error => console.error('Error getting camera capabilities and settings:', error));

กำลังกำหนดค่า

คุณกำหนดการตั้งค่ากล้อง "สด" ได้ผ่านข้อจำกัดapplyConstraints()ของ MediaStreamTrack ตัวอย่าง ตัวอย่างเช่น

var zoomSlider = document.querySelector('input[type=range]');

mediaStreamTrack.applyConstraints({ advanced: [{ zoom: zoomSlider.value }]})
    .catch(error => console.error('Uh, oh, applyConstraints() error:', error));

การตั้งค่ากล้อง "ไม่ได้เผยแพร่" ได้รับการกำหนดค่าด้วยพจนานุกรมPhotoSettingsที่ไม่บังคับของ takePhoto() ดังตัวอย่างต่อไปนี้

var widthSlider = document.querySelector('input[type=range]');
imageCapture.takePhoto({ imageWidth : widthSlider.value })
    .then(blob => {
    img.src = URL.createObjectURL(blob);
    img.onload = () => { URL.revokeObjectURL(this.src); }
    })
    .catch(error => console.error('Uh, oh, takePhoto() error:', error));

ความสามารถของกล้อง

หากเรียกใช้โค้ดด้านบน คุณจะเห็นความแตกต่างของมิติข้อมูลระหว่างผลลัพธ์ grabFrame() และ takePhoto()

เมธอด takePhoto() ให้สิทธิ์เข้าถึงความละเอียดสูงสุดของกล้อง

grabFrame() จะใช้ VideoFrame ถัดไปใน MediaStreamTrack ภายในกระบวนการแสดงผล ในขณะที่ takePhoto() ขัดจังหวะ MediaStream กำหนดค่ากล้องใหม่ ถ่ายภาพ (โดยปกติอยู่ในรูปแบบที่บีบอัด ดังนั้น Blob) แล้วจึงกลับสู่ MediaStreamTrack โดยพื้นฐานแล้ว นี่หมายความว่า takePhoto() ให้สิทธิ์เข้าถึงความสามารถด้านความละเอียดของภาพนิ่งเต็มรูปแบบของกล้อง ก่อนหน้านี้ คุณจะ "ถ่ายรูป" ได้โดยเรียกใช้ drawImage() ในเอลิเมนต์ canvas โดยใช้วิดีโอเป็นต้นฉบับเท่านั้น (ตามตัวอย่างที่นี่)

สามารถดูข้อมูลเพิ่มเติมได้ในส่วน README.md

ในการสาธิตนี้ มิติข้อมูล <canvas> ได้รับการตั้งค่าเป็นความละเอียดของสตรีมวิดีโอ ในขณะที่ขนาดธรรมชาติของ <img> คือความละเอียดสูงสุดของภาพนิ่งของกล้อง แน่นอนว่า CSS จะใช้ในการตั้งค่า ขนาดการแสดงผลของทั้ง 2 แบบ

คุณดูและตั้งค่าความละเอียดของกล้องทั้งหมดที่ใช้ได้สำหรับภาพนิ่งได้โดยใช้ค่า MediaSettingsRange สำหรับ PhotoCapabilities.imageHeight และ imageWidth โปรดทราบว่าข้อจำกัดต่ำสุดและสูงสุดของความกว้างและความสูงสำหรับ getUserMedia() มีไว้สำหรับวิดีโอ ซึ่ง (ตามที่กล่าวไว้) อาจแตกต่างจากความสามารถของกล้องสำหรับภาพนิ่ง กล่าวคือ คุณอาจเข้าถึงความสามารถด้านความละเอียดเต็มของอุปกรณ์ไม่ได้เมื่อบันทึกจาก getUserMedia() ไปยัง Canvas การสาธิตข้อจำกัดการแก้ปัญหาของ WebRTC จะแสดงวิธีตั้งค่าข้อจำกัด getUserMedia() สำหรับการแก้ปัญหา

มีอะไรเพิ่มเติมอีกไหม

  • Shape Detection API ทำงานได้ดีกับการจับภาพ โดยอาจมีการเรียก grabFrame() ซ้ำๆ เพื่อส่ง ImageBitmaps ไปยัง FaceDetector หรือ BarcodeDetector ดูข้อมูลเพิ่มเติมเกี่ยวกับ API จากบล็อกโพสต์ของ Paul Kinlan

  • แฟลชกล้อง (ไฟอุปกรณ์) เข้าถึงได้ผ่าน FillLightMode ใน PhotoCapabilities แต่คุณดูโหมดไฟฉาย (เปิดแฟลชอยู่ตลอดเวลา) ได้ใน MediaTrackCapabilities

การสาธิตและตัวอย่างโค้ด

การสนับสนุน

  • Chrome 59 ใน Android และเดสก์ท็อป
  • Chrome Canary บน Android และเดสก์ท็อปก่อนหน้ารุ่น 59 ที่มีการเปิดใช้ฟีเจอร์แพลตฟอร์มเว็บรุ่นทดลอง

ดูข้อมูลเพิ่มเติม