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

การจับภาพเป็น 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));

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

การตั้งค่ากล้อง "ถ่ายทอดสด" สามารถกําหนดค่าผ่านMediaStreamTrackข้อจํากัดapplyConstraints()ของตัวอย่างได้ ดังนี้

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

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

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

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() ไปยังภาพพิมพ์แคนวาส การสาธิตข้อจำกัดความละเอียดของ WebRTC จะแสดงวิธีตั้งค่าข้อจำกัด getUserMedia() สำหรับความละเอียด

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

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

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

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

การสนับสนุน

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

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