Tôi đang tạo một ứng dụng mà tôi muốn chụp ảnh từ máy ảnh mặt trước mà không cần hiển thị màn hình chụp bất kỳ loại nào. Tôi muốn chụp ảnh hoàn toàn bằng mã mà không cần bất kỳ sự tương tác nào của người dùng. Làm thế nào tôi sẽ làm điều này cho máy ảnh mặt trước?iOS: Chụp ảnh từ máy ảnh mặt trước
Trả lời
Có thể bạn cần sử dụng AVFoundation
để quay luồng/hình ảnh video mà không hiển thị. Không giống như UIImagePickerController
, nó không hoạt động 'out-of-the-box'. Hãy nhìn vào ví dụ AVCam
của Apple để giúp bạn bắt đầu.
Làm thế nào để chụp ảnh bằng cách sử dụng AVFoundation ở mặt trước máy ảnh:
Phát triển Hãy cẩn thận:
- Kiểm tra cài đặt ứng dụng và định hướng hình ảnh của bạn một cách cẩn thận
- AVFoundation và các khuôn khổ liên quan của nó là kếch xù khó chịu và rất khó hiểu/thực hiện. Tôi đã thực hiện mã của tôi như nạc càng tốt, nhưng hãy kiểm tra hướng dẫn này tuyệt vời cho một lời giải thích tốt hơn (trang web không cung cấp bất kỳ hơn, liên kết thông qua archive.org): http://www.benjaminloulier.com/posts/ios4-and-direct-access-to-the-camera
ViewController.h
// Frameworks
#import <CoreVideo/CoreVideo.h>
#import <CoreMedia/CoreMedia.h>
#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>
@interface CameraViewController : UIViewController <AVCaptureVideoDataOutputSampleBufferDelegate>
// Camera
@property (weak, nonatomic) IBOutlet UIImageView* cameraImageView;
@property (strong, nonatomic) AVCaptureDevice* device;
@property (strong, nonatomic) AVCaptureSession* captureSession;
@property (strong, nonatomic) AVCaptureVideoPreviewLayer* previewLayer;
@property (strong, nonatomic) UIImage* cameraImage;
@end
ViewController.m
#import "CameraViewController.h"
@implementation CameraViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupCamera];
[self setupTimer];
}
- (void)setupCamera
{
NSArray* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for(AVCaptureDevice *device in devices)
{
if([device position] == AVCaptureDevicePositionFront)
self.device = device;
}
AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
AVCaptureVideoDataOutput* output = [[AVCaptureVideoDataOutput alloc] init];
output.alwaysDiscardsLateVideoFrames = YES;
dispatch_queue_t queue;
queue = dispatch_queue_create("cameraQueue", NULL);
[output setSampleBufferDelegate:self queue:queue];
NSString* key = (NSString *) kCVPixelBufferPixelFormatTypeKey;
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
[output setVideoSettings:videoSettings];
self.captureSession = [[AVCaptureSession alloc] init];
[self.captureSession addInput:input];
[self.captureSession addOutput:output];
[self.captureSession setSessionPreset:AVCaptureSessionPresetPhoto];
self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
// CHECK FOR YOUR APP
self.previewLayer.frame = CGRectMake(0, 0, self.view.frame.size.height, self.view.frame.size.width);
self.previewLayer.orientation = AVCaptureVideoOrientationLandscapeRight;
// CHECK FOR YOUR APP
[self.view.layer insertSublayer:self.previewLayer atIndex:0]; // Comment-out to hide preview layer
[self.captureSession startRunning];
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer,0);
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGImageRef newImage = CGBitmapContextCreateImage(newContext);
CGContextRelease(newContext);
CGColorSpaceRelease(colorSpace);
self.cameraImage = [UIImage imageWithCGImage:newImage scale:1.0f orientation:UIImageOrientationDownMirrored];
CGImageRelease(newImage);
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
}
- (void)setupTimer
{
NSTimer* cameraTimer = [NSTimer scheduledTimerWithTimeInterval:2.0f target:self selector:@selector(snapshot) userInfo:nil repeats:YES];
}
- (void)snapshot
{
NSLog(@"SNAPSHOT");
self.cameraImageView.image = self.cameraImage; // Comment-out to hide snapshot
}
@end
Connect này lên đến một UIViewController với một UIImageView cho ảnh chụp và nó sẽ làm việc! Ảnh chụp nhanh được thực hiện theo chương trình ở khoảng thời gian 2.0 giây mà không có bất kỳ đầu vào nào của người dùng. Nhận xét các dòng được chọn để xóa lớp xem trước và phản hồi ảnh chụp nhanh.
Mọi câu hỏi/nhận xét khác, vui lòng cho tôi biết!
Rất đẹp! Tôi muốn đề nghị câu trả lời này được chấp nhận trên mỏ (giả sử nó hoạt động). – Tim
Đây có phải là Apple App Store thân thiện không? – mtmurdock
Tôi không chắc chắn, đây là lần đầu tiên tôi nghĩ về một ứng dụng như thế này. Tôi đoán bạn sẽ cần phải đào sâu vào bản in đẹp và thực sự làm cho người dùng/Apple biết rằng nó không được sử dụng cho bất kỳ mục đích nham hiểm nào (như đã đề cập trong các bài viết khác ở đây). Ứng dụng của bạn có vẻ vui nhộn và vô hại, vì vậy có thể nó sẽ ổn thôi! –
Có một phương thức gọi là takePicture trong tài liệu cho lớp UIImagePickerController. Nó nói:
Sử dụng phương pháp này cùng với chế độ xem lớp phủ tùy chỉnh để bắt đầu chụp ảnh có lập trình của hình ảnh tĩnh. Điều này hỗ trợ chụp nhiều ảnh mà không cần rời khỏi giao diện, nhưng yêu cầu bạn ẩn các điều khiển bộ chọn hình ảnh mặc định.
tôi chuyển mã trên từ ObjC để Swift 3, nếu có ai vẫn tìm kiếm một giải pháp trong 2017.
import UIKit
import AVFoundation
class CameraViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
@IBOutlet weak var cameraImageView: UIImageView!
var device: AVCaptureDevice?
var captureSession: AVCaptureSession?
var previewLayer: AVCaptureVideoPreviewLayer?
var cameraImage: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
setupCamera()
setupTimer()
}
func setupCamera() {
let discoverySession = AVCaptureDeviceDiscoverySession(deviceTypes: [.builtInWideAngleCamera],
mediaType: AVMediaTypeVideo,
position: .front)
device = discoverySession?.devices[0]
let input: AVCaptureDeviceInput
do {
input = try AVCaptureDeviceInput(device: device)
} catch {
return
}
let output = AVCaptureVideoDataOutput()
output.alwaysDiscardsLateVideoFrames = true
let queue = DispatchQueue(label: "cameraQueue")
output.setSampleBufferDelegate(self, queue: queue)
output.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable: kCVPixelFormatType_32BGRA]
captureSession = AVCaptureSession()
captureSession?.addInput(input)
captureSession?.addOutput(output)
captureSession?.sessionPreset = AVCaptureSessionPresetPhoto
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
previewLayer?.frame = CGRect(x: 0.0, y: 0.0, width: view.frame.width, height: view.frame.height)
view.layer.insertSublayer(previewLayer!, at: 0)
captureSession?.startRunning()
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: .allZeros))
let baseAddress = UnsafeMutableRawPointer(CVPixelBufferGetBaseAddress(imageBuffer!))
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)
let width = CVPixelBufferGetWidth(imageBuffer!)
let height = CVPixelBufferGetHeight(imageBuffer!)
let colorSpace = CGColorSpaceCreateDeviceRGB()
let newContext = CGContext(data: baseAddress, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo:
CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue)
let newImage = newContext!.makeImage()
cameraImage = UIImage(cgImage: newImage!)
CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: .allZeros))
}
func setupTimer() {
_ = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(snapshot), userInfo: nil, repeats: true)
}
func snapshot() {
print("SNAPSHOT")
cameraImageView.image = cameraImage
}
}
Ngoài ra, tôi tìm thấy một giải pháp ngắn hơn để nhận được hình ảnh từ CMSampleBuffer:
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
let myPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
let myCIimage = CIImage(cvPixelBuffer: myPixelBuffer!)
let videoImage = UIImage(ciImage: myCIimage)
cameraImage = videoImage
}
Cảm ơn, điều này khá hữu ích như một điểm khởi đầu. –
Không có vấn đề gì, tôi rất vui vì nó rất hữu ích, không thực sự biết nếu nó vẫn hoạt động với Swift 4 mà không xuất hiện cảnh báo .. –
Không chỉ cảnh báo, một số thứ cần phải được thay đổi, nhưng sửa chữa hầu hết là xử lý nó. –
Chuyển đổi trên mã để Swift 4
import UIKit
import AVFoundation
class CameraViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
@IBOutlet weak var cameraImageView: UIImageView!
var device: AVCaptureDevice?
var captureSession: AVCaptureSession?
var previewLayer: AVCaptureVideoPreviewLayer?
var cameraImage: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
setupCamera()
setupTimer()
}
func setupCamera() {
let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera],
mediaType: AVMediaType.video,
position: .front)
device = discoverySession.devices[0]
let input: AVCaptureDeviceInput
do {
input = try AVCaptureDeviceInput(device: device!)
} catch {
return
}
let output = AVCaptureVideoDataOutput()
output.alwaysDiscardsLateVideoFrames = true
let queue = DispatchQueue(label: "cameraQueue")
output.setSampleBufferDelegate(self, queue: queue)
output.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable as! String: kCVPixelFormatType_32BGRA]
captureSession = AVCaptureSession()
captureSession?.addInput(input)
captureSession?.addOutput(output)
captureSession?.sessionPreset = AVCaptureSession.Preset.photo
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)
previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
previewLayer?.frame = CGRect(x: 0.0, y: 0.0, width: view.frame.width, height: view.frame.height)
view.layer.insertSublayer(previewLayer!, at: 0)
captureSession?.startRunning()
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
let baseAddress = UnsafeMutableRawPointer(CVPixelBufferGetBaseAddress(imageBuffer!))
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)
let width = CVPixelBufferGetWidth(imageBuffer!)
let height = CVPixelBufferGetHeight(imageBuffer!)
let colorSpace = CGColorSpaceCreateDeviceRGB()
let newContext = CGContext(data: baseAddress, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo:
CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue)
let newImage = newContext!.makeImage()
cameraImage = UIImage(cgImage: newImage!)
CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
}
func setupTimer() {
_ = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(snapshot), userInfo: nil, repeats: true)
}
@objc func snapshot() {
print("SNAPSHOT")
cameraImageView.image = cameraImage
}
}
- 1. Máy ảnh mặt trước của Android Chụp ảnh ngược
- 2. Chụp ảnh mặt trước camera - Phonegap?
- 3. Ngăn ngừa lật máy ảnh mặt trước
- 4. Chụp ảnh từ máy ảnh thành dạng hoặc html5 canvas
- 5. Cách chụp ảnh thô từ máy ảnh android
- 6. Android tự động cắt máy ảnh chụp ảnh
- 7. Mobile Safari IOS 6 Chụp ảnh
- 8. Chụp ảnh từ webcam
- 9. Xem trước máy ảnh Android - Cách 'đóng băng' máy ảnh?
- 10. ios chụp ảnh sử dụng AVFramework
- 11. Luôn nhìn thấy hình ảnh Phản chiếu trong khi chụp từ Camera trước iOS 5.0
- 12. Chụp ảnh màn hình trên điện thoại Android khi phát video và xem trước máy ảnh
- 13. Làm cách nào để chụp nhiều ảnh trước khi loại bỏ ý định máy ảnh?
- 14. Truy cập máy ảnh trong IOS Simulator
- 15. Chất lượng hình ảnh/hình ảnh thấp khi chụp từ máy ảnh
- 16. Trì hoãn ảnh chụp màn hình iOS
- 17. C# chụp ảnh từ webcam
- 18. Android xoay ảnh 90 độ (chụp bằng máy ảnh)
- 19. Hình ảnh bề mặt máy ảnh Xem hình ảnh Trải dài
- 20. iOS: Nhận dữ liệu pixel theo pixel từ máy ảnh
- 21. Cách chụp ảnh từ máy ảnh trên Trình giả lập Android?
- 22. Nhận diện khuôn mặt bằng OpenCV cho hình ảnh không phải mặt trước
- 23. Android - Xem trước máy ảnh
- 24. Xoay khuôn mặt trong ảnh
- 25. Android - Xem trước máy ảnh nằm ngang
- 26. Cách gửi ảnh cho ứng dụng của tôi từ ứng dụng Máy ảnh iOS mặc định?
- 27. Cách chụp ảnh mà không hiển thị xem trước trong iOS
- 28. Android - Chụp ảnh
- 29. Làm thế nào để cắt hình ảnh sau khi chụp từ Máy ảnh UIImagePicker?
- 30. Ảnh chụp màn hình Circumvent cho iOS 4
Bạn có nghĩa là âm thầm chụp ảnh mà không cho người sử dụng biết anyt hing về nó? – rid
Vâng, tôi biết nó nghe có vẻ xấu nhưng hoàn toàn vô hại. Ứng dụng này sẽ khiến họ kéo mặt buồn cười và tôi muốn chụp nó để họ có thể thấy chúng trông ngớ ngẩn như thế nào. – mtmurdock
Việc bạn thực hiện một tính năng như vậy có thể vô hại, nhưng tôi có thể nghĩ đến rất nhiều trường hợp khác mà nó sẽ là bất kỳ thứ gì nhưng (đó có thể là lý do tại sao nó không thể). – inkedmn