2012-05-27 44 views
17

Tôi muốn xử lý hình ảnh bằng hình ảnh thô mà không hiển thị hình ảnh trên màn hình, điều này làm giảm hiệu suất rõ ràng.Android SDK: Xem hình ảnh máy ảnh xem trước thô mà không hiển thị hình ảnh

Theo câu trả lời cho chủ đề này Taking picture from camera without preview thì không thể thực hiện được trong Android 1.5, nhưng có ai biết nếu có thể trong Android 4 (API cấp 15) không?

+0

Chỉ cần thử giải pháp SurfaceTexture giả (phương pháp 2) trên Samsung Galaxy s5. Nó không thành công sau một vài khung hình. Cách giải quyết của tôi là thực sự gọi updateTexImage, nhưng sử dụng tên kết cấu không hợp lệ với ngữ cảnh GL hợp lệ. Sau khi ngắt kết quả ngoại lệ, mọi thứ hoạt động suôn sẻ. – user3693576

Trả lời

41

Trong Android 4, tùy chọn đơn giản nhất để nhận dữ liệu hình ảnh thô mà không hiển thị trên màn hình là sử dụng cuộc gọi Camera.setPreviewTexture() để định tuyến khung xem trước cho GPU.

Bạn có thể sử dụng theo hai cách:

  1. Do chế biến thực tế của bạn trên GPU: Thiết lập một bối cảnh OpenGL (OpenGL ES 2 tutorial), và tạo ra một đối tượng SurfaceTexture trong bối cảnh đó. Sau đó chuyển đối tượng đó tới setPreviewTexture và bắt đầu xem trước. Sau đó, trong mã OpenGL, bạn có thể gọi SurfaceTexture.updateTexImage và ID kết cấu được liên kết với SurfaceTexture sẽ được cập nhật lên khung xem trước mới nhất từ ​​máy ảnh. Bạn cũng có thể đọc lại dữ liệu kết cấu RGB tới CPU để xử lý thêm bằng cách sử dụng các glReadPixels, nếu muốn.
  2. Làm việc xử lý của bạn trên CPU: Bạn chỉ cần tạo một đối tượng SurfaceTexture giả mà không có bất kỳ bối cảnh OpenGL nào được thiết lập. Vượt qua bất kỳ số nguyên nào bạn muốn làm ID kết cấu và kết nối SurfaceTexture với máy ảnh bằng cách sử dụng setPreviewTexture. Miễn là bạn không gọi updateTexImage, SurfaceTexture sẽ đơn giản loại bỏ tất cả dữ liệu được truyền vào máy ảnh. Sau đó, thiết lập gọi lại xem trước bằng cách sử dụng setPreviewCallback và sử dụng dữ liệu đó (thường ở định dạng YUV) để xử lý CPU. Điều này có lẽ kém hiệu quả hơn # 1, nhưng không yêu cầu phải biết OpenGL.
+0

Có ai đi qua một ví dụ đơn giản của việc sử dụng glReadPixels sau khi SurfaceTexture.updateTexImage trả về? – wobbals

+0

Phương pháp 2 không hoạt động đối với Nexus 4. – user1914692

+0

@wobbals: Bạn không thể trực tiếp 'glReadPixels()' đầu ra Camera (cùng một vấn đề với http: // stackoverflow.com/questions/19366660/how-to-save-surfacetexture-as-bitmap/19370209 # 19370209). Làm cho nó vào một pbuffer đầu tiên. Một số gợi ý cho các ví dụ ở đây: http://stackoverflow.com/questions/20710204/android-camera-preview-on-surfacetexture/21104769#21104769 – fadden

1

Vì tôi không được phép nhận xét. Về câu trả lời của Eddy. Bạn cần phải làm việc với điều này trong NDK khi sử dụng giao diện Java sẽ phủ nhận bất kỳ lợi ích hiệu suất nào. Phải làm việc với PixelBuffer là hoàn toàn điên rồ từ quan điểm hiệu suất. Chuyển đổi của bạn từ RGBA888 sang YUV cũng cần được thực hiện trong C.

Đừng thử sử dụng TextureView vì sẽ còn tệ hơn nữa. Bạn sẽ phải sao chép các Pixels vào một Bitmap sau đó từ một Bitmap vào một mảng tất cả trước khi chuyển đổi sang YUV. Điều này, một mình, chiếm gần 30% mức sử dụng CPU trên một Nexus 7 mới của thương hiệu 2013.

Cách hiệu quả nhất là nói chuyện trực tiếp với Camera.h và bỏ qua tất cả các API Android. Bạn có thể tạo bộ đệm của riêng bạn và chặn dữ liệu YUV trước khi nó đi bất cứ nơi nào khác.

+1

Trong khi các cuộc gọi lại xem trước không hiệu quả như tôi muốn, chúng không kinh khủng. Bạn nhận được một byte [] dữ liệu YUV trên mỗi khung, có thể được gửi qua JNI tới mã xử lý gốc với 0 bản sao. Không chuyển đổi sang Bitmap hoặc bất kỳ thứ gì khác được yêu cầu. Sử dụng Camera.h trực tiếp là một ý tưởng tồi, bởi vì giao diện đó là riêng tư và có thể thay đổi bất cứ lúc nào. –

+0

Lệnh gọi lại xem trước chỉ hoạt động với Bề mặt. Câu hỏi đặt ra là làm thế nào để làm điều đó mà không hiển thị nó cả. Cách duy nhất để làm điều đó mà không có Surface là sử dụng PixelBuffer. Gọi lại tiêu chuẩn w/Bề mặt tốt hơn từ quan điểm hiệu suất. Mỗi cuộc gọi lại có hai chu kỳ. Camera sao chép vào bộ đệm trong; sau đó vào bộ đệm bề mặt RGBA. Chu kỳ thứ hai sao chép bộ đệm bên trong vào bộ đệm gọi lại. – bond

+0

Tôi thực sự không chắc chắn ý của bạn là gì bởi PixelBuffer - không có API nào theo tên mà tôi biết trong Android (ý bạn là Bitmap?). Các callbacks preview làm việc tốt với setPreviewTexture() ngoài setPreviewDisplay(), và trước đây không yêu cầu bản vẽ xem trước cho bất kỳ phần tử UI nào. Các bản sao trong các lớp bản địa và JNI là một hiệu suất kéo, tôi đồng ý, đó là lý do tại sao tôi cũng đề xuất phương pháp xử lý GPU, mà không có phí. –

1

Hiển thị xem trước trên màn hình không có hậu quả về hiệu suất. Trên tất cả các thiết bị tôi gặp, đầu ra của máy ảnh là "có dây" với bề mặt hoặc kết cấu không có CPU liên quan, tất cả chuyển đổi màu và chia tỷ lệ được xử lý bằng phần cứng chuyên dụng.

Có thể có các lý do khác để "ẩn" bản xem trước, nhưng hãy nhớ rằng mục đích của API ban đầu là đảm bảo rằng người dùng cuối thấy mọi thứ đến từ máy ảnh đến ứng dụng, vì lý do riêng tư và bảo mật .

Các vấn đề liên quan