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

Miguel Casas-Sanchez
ฟร็องซัว โบฟอร์
François Beaufort

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

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

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

การก่อสร้าง

Image Recording 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));

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

คุณกำหนดการตั้งค่ากล้อง "Live" ผ่านข้อจำกัด 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() เพื่อฟีด ImageBitmap ไปยัง FaceDetector หรือ BarcodeDetector ได้ซ้ำๆ ดูข้อมูลเพิ่มเติมเกี่ยวกับ API จากบล็อกโพสต์ของ Paul Kinlan

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

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

การสนับสนุน

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

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