Pi camera v2 - chế độ chụp cảm biến nhanh, đầy đủ với chế độ lấy mẫu xuống


7

Tôi có một máy ảnh Pi v2 mà tôi dự định sử dụng với RPi3 cho dự án thị giác máy tính.

Tôi cần chụp ảnh cảm biến đầy đủ từ máy ảnh - không cắt xén. Độ phân giải thực sự được sử dụng bởi phần mềm rất thấp, khoảng 120 x 90 hoặc hơn (cộng hoặc trừ vài chục). Phần mềm sẽ có được một khung, xử lý nó, có được khung tiếp theo, v.v. - nhanh nhất có thể. Phần mềm sẽ được viết bằng Python, với Tensorflow thực hiện nhận dạng hình ảnh.

Có cách nào để thực hiện binning sâu trên máy ảnh trực tiếp không? Tôi đang cố gắng tránh xử lý hình ảnh trong phần mềm càng nhiều càng tốt, vì cả 4 lõi CPU sẽ bận rộn làm những việc khác. Vì vậy, tôi cần phải giảm mẫu từ hình ảnh cảm biến đầy đủ xuống độ phân giải 120 x 90 thấp với nỗ lực CPU tối thiểu. Sẽ thật tuyệt nếu máy ảnh có thể thực hiện một số thao tác thực sự sâu, như 20 x 20 hoặc hơn thế.

Nếu không, điều gì sẽ là một lựa chọn tốt trong điều kiện của các thư viện Python để thực hiện lấy mẫu nhanh, sâu? BTW, tôi không thể thả pixel, tôi cần tất cả thông tin ban đầu, vì vậy một số loại pha trộn sẽ phải được thực hiện.

Phần mềm chỉ xử lý hình ảnh đen trắng. Tôi có thể đặt máy ảnh để xuất hình ảnh b / w không? Một lần nữa, nếu không, cách nhanh nhất để làm điều đó trong Python trên nền tảng RPi3 là gì? Bất kỳ thủ thuật tăng tốc phần cứng đều rất được hoan nghênh.

Mục tiêu tổng thể ở đây là đưa ra các thói quen thu nhận hình ảnh sử dụng toàn bộ cảm biến, mẫu xuống và cung cấp khoảng 120 x 90 px hình ảnh, đen và trắng, 8 bit cho mỗi pixel, có thể là một mảng khó chịu, cho phần thị giác của máy tính phần mềm, trong khi sử dụng số lượng chu kỳ CPU tối thiểu, để tối đa hóa tốc độ chung.


1
Có, bạn có thể truy cập trực tiếp vào lớp máy ảnh bằng mã MMAL nhưng điều đó hơi khó. Nhưng nếu bạn sử dụng UV4L, có sẵn API để thực hiện công việc với luồng video thông qua v4l2-ctl để đặt mọi thứ trên máy ảnh mà sau đó bạn có thể sử dụng /dev/videothiết bị trực tiếp. Tôi sẽ thử điều đó và xem làm thế nào bạn nhận được trên. Nếu bạn gặp khó khăn liên hệ với tác giả về bất kỳ vấn đề hoặc câu hỏi thực sự. Anh ấy là một chàng trai rất tốt, thích giúp đỡ với những vấn đề thực sự. Chúc may mắn và hãy trả lời với cách bạn giải quyết vấn đề của bạn.
Piotr Kula

Câu trả lời:


13

Hãy bắt đầu bằng cách nhìn vào các mô-đun máy ảnh. Mô-đun máy ảnh v1 có khả năng tạo khung 2x2 và 4x4 (xem bảng chế độ máy ảnh ); Tôi cũng đã nghe nói có chế độ tạo thùng 8 x 8 nhưng các nhà phát triển phần sụn không thể làm cho nó hoạt động. Đây là lý do tại sao mô-đun v1 có thể đạt được trường quan sát (foV) đầy đủ trong hầu hết các chế độ.

Thật không may, mô-đun máy ảnh v2 được so sánh, chỉ có khả năng tạo khung 2x2, điều này giải thích tại sao nhiều chế độ của nó có một phần foV (Tôi nghĩ rằng mô-đun v2 cũng có thể bỏ qua dòng, nhưng tôi không nghĩ rằng đó là máy ảnh của Pi sử dụng phần sụn). Tuy nhiên, đây không phải là toàn bộ câu chuyện. Đây chỉ là sự khởi đầu của đường ống xử lý hình ảnh. Nói cách khác, đây chỉ là những gì cảm biến tự chuyển đến khối ISP trong GPU xử lý phần còn lại của quá trình xử lý, bao gồm mọi thay đổi kích thước. Trong khi máy ảnh có một số chế độ riêng biệt (được liệt kê trong bảng đó), nó có thể hoạt động hiệu quả trong mọi chế độđộ phân giải lên đến mức tối đa được liệt kê. Nếu bạn đọc thêm một chút từ các bảng đó trong tài liệu, bạn sẽ tìm thấy mô tả về heuristic được sử dụng để chọn chế độ cảm biến theo độ phân giải và tốc độ khung hình được yêu cầu.

Miễn là bạn kết nối hoặc buộc sử dụng chế độ cảm biến toàn khung hình, bạn sẽ chụp từ tất cả các pixel trên cảm biến. Đối với những lo ngại về việc sử dụng CPU: đừng lo lắng. CPU không được sử dụng cho bất kỳ phần nào trong đường dẫn hình ảnh của máy ảnh, nó gần như hoàn toàn dựa trên GPU (ngoại trừ bước tạo thùng đầu tiên được thực hiện bởi ISP cảm biến). Lần duy nhất CPU tham gia là khi nó nhận được đầu ra cuối cùng và phải làm gì đó với nó.

Nếu bạn đang tìm kiếm mức sử dụng CPU tối thiểu, đây là điểm cộng lớn của mô-đun máy ảnh so với webcam USB, vì bus USB được CPU thăm dò, hãy sử dụng thời gian CPU đáng kể (USB3 sử dụng ngắt thay vì bỏ phiếu nhưng chúng tôi nói về Pis ở đây chỉ có USB2 và bên cạnh đó: hầu hết các webcam USB không sử dụng USB3 tại thời điểm viết).

Lên các yêu cầu cụ thể của bạn. Bạn muốn:

  • để tạo ra hình ảnh 120x90
  • với góc nhìn đầy đủ
  • màu đen và trắng (tôi sẽ hiểu điều này chỉ có nghĩa là luma là tốt)
  • đến một mảng numpy Python
  • nhanh nhất có thể

Vừa đủ dễ. Chúng tôi sẽ sử dụng chế độ cảm biến 4 cung cấp trường quan sát đầy đủ và sử dụng cảm biến để thực hiện chế độ tạo 2x2 ban đầu. Chúng tôi sẽ đặt độ phân giải đầu ra của máy ảnh thành 120x90 (điều này đơn giản có nghĩa là khối thay đổi kích thước của GPU sẽ lấy dữ liệu cảm biến có khung hình 2x2 toàn khung hình và giảm kích thước xuống 120x90). Cuối cùng, chúng ta sẽ chụp thẳng vào một mảng gọn gàng nhưng chúng ta sẽ chỉ làm cho nó đủ lớn cho mặt phẳng Y (độ chói) của dữ liệu; nó sẽ gây ra lỗi vì mảng không đủ lớn cho tất cả dữ liệu, nhưng không sao - chúng ta có thể bỏ qua điều đó và nó vẫn sẽ ghi dữ liệu Y ra:

import time
import picamera
import numpy as np

with picamera.PiCamera(
         sensor_mode=4,
         resolution='120x90',
         framerate=40) as camera:
    time.sleep(2) # let the camera warm up and set gain/white balance
    y_data = np.empty((96, 128), dtype=np.uint8)
    try:
        camera.capture(y_data, 'yuv')
    except IOError:
        pass
    y_data = y_data[:120, :90]
    # y_data now contains the Y-plane only
    print(y_data.max())

Điều này ít nhiều được sao chép trực tiếp từ công thức chụp ảnh chưa được mã hóa (YUV) cũng giải thích lý do tại sao chúng tôi thực sự chụp 128x96 ở đây (máy ảnh hoạt động trong các khối 32x16).

Điều gì về chụp liên tục nhanh chóng? Tôi cho rằng bạn quan tâm đến điều này đơn giản chỉ vì bạn muốn điều này càng nhanh càng tốt (điều này thường có nghĩa là bạn muốn càng nhiều càng tốt). Trong trường hợp này, tốt nhất là sử dụng đầu ra tùy chỉnh với bản ghi YUV (sẽ nhận một cuộc gọi write () trên mỗi khung hình), sau đó sử dụng frombufferphương pháp rất tiện dụng của numpy để xếp một mảng numpy lên trên mặt trước của dữ liệu đã chụp (lưu ý: việc này cực kỳ nhanh vì chúng tôi không phân bổ mảng numpy hoặc sao chép dữ liệu, chúng tôi chỉ nói "tạo một mảng gọn gàng trên khối bộ nhớ hiện có này "):

import time
import picamera
import numpy as np

class MyOutput(object):
    def write(self, buf):
        # write will be called once for each frame of output. buf is a bytes
        # object containing the frame data in YUV420 format; we can construct a
        # numpy array on top of the Y plane of this data quite easily:
        y_data = np.frombuffer(
            buf, dtype=np.uint8, count=128*96).reshape((96, 128))
        # do whatever you want with the frame data here... I'm just going to
        # print the maximum pixel brightness:
        print(y_data[:90, :120].max())

    def flush(self):
        # this will be called at the end of the recording; do whatever you want
        # here
        pass

with picamera.PiCamera(
        sensor_mode=4,
        resolution='120x90',
        framerate=40) as camera:
    time.sleep(2) # let the camera warm up and set gain/white balance
    output = MyOutput()
    camera.start_recording(output, 'yuv')
    camera.wait_recording(10) # record 10 seconds worth of data
    camera.stop_recording()

Mặc dù tạo ra 40 khung hình mỗi giây của dữ liệu hình ảnh trong các mảng khó hiểu, việc sử dụng CPU của tập lệnh này là tối thiểu. Nhận xét câu lệnh in, thực sự khá nặng về CPU, để xem mức độ sử dụng CPU tổng thể: đó là khoảng 2% trên Pi3 của tôi vì vậy còn dư lại cho bất kỳ xử lý hình ảnh nào bạn muốn làm.


1
Câu trả lời và phân tích tốt đẹp! +1 cũng xứng đáng.
Dmitry Grigoryev

Cảm ơn bạn rất nhiều Dave, câu trả lời của bạn luôn luôn tuyệt vời! Đây là chính xác những gì tôi cần. Kích thước hình ảnh không được đặt trong đá, tôi sẽ cố gắng tìm kích thước tối đa cho phép phần còn lại của mã .py (Tensorflow) thực hiện nhận dạng hình ảnh với tốc độ đủ tốt trên Pi3; Tôi chỉ cần dữ liệu cảm biến đầy đủ cho một góc nhìn phong nha. Tôi vẫn đang tự tranh luận liệu toàn bộ sự việc sẽ là một vòng lặp (chụp / phản hồi hình ảnh / phản ứng) hay tôi nên có hai đơn vị riêng biệt (chụp như trong ví dụ thứ 2 của bạn trong một quy trình và chia sẻ numpys async với quy trình Tensorflow) . # 1 thì dễ hơn, # 2 thì nhanh hơn. Cần phải suy nghĩ về nó.
Florin Andrei

BTW, thông tin trong câu trả lời này rất hữu ích, nó nên được thêm vào tài liệu mô-đun picamera ở đâu đó. Ít nhất là nửa đầu của câu trả lời. Tôi không biết làm thế nào tất cả quá trình xử lý đó được thực hiện trên GPU, v.v. Có lẽ chính tài liệu máy ảnh nên đề cập đến công cụ này trong một chi tiết công nghệ xuất hiện ở đâu đó. Cách máy ảnh hoạt động và tích hợp với nền tảng RPi và phần mềm tốt hơn tôi nghĩ rất nhiều.
Florin Andrei

1
Tôi đã tìm hiểu chương phần cứng máy ảnh cho lần phát hành tiếp theo nhưng có lẽ tôi nên nói thêm một chút về tất cả được triển khai trong GPU - Tôi chỉ coi kiến ​​thức đó là hiển nhiên nhưng đọc tài liệu thì không rõ ràng.
Dave Jones

@DaveJones ví dụ đầu tiên của bạn ném một số lỗi. Đây là mã cố định: gist.github.com/FlorinAndrei/281662a59dec0d3cbb902cb3be6d79f6
Florin Andrei

3

Pi camera v2 là một lựa chọn đặc biệt tồi cho những gì bạn đang cố gắng thực hiện. Hãy xem danh sách các nghị quyết được hỗ trợ của nó :

nhập mô tả hình ảnh ở đây

Như bạn có thể thấy, độ phân giải được hỗ trợ nhỏ nhất là 640 × 480 và nó đã bị cắt so với khu vực cảm biến đầy đủ.

máy ảnh Orange Pi mà bạn có thể xem xét, có kích thước tương tự và hỗ trợ độ phân giải xuống tới 320 × 240. Không chính xác những gì bạn cần (mặc dù gần hơn), nhưng tôi không biết liệu bạn có thể chuyển đổi dự án của bạn sang SBC khác một cách dễ dàng không.

Tuy nhiên, lời khuyên của tôi là mua một webcam USB giá rẻ hỗ trợ độ phân giải CIF , đặc biệt là SQCIF (128 × 96). Bạn có thể tìm ra độ phân giải mà webcam hỗ trợ bằng cách chạy v4l2-ctl --list-formats-ext.

Cuối cùng, nếu bạn cần FOV lớn, hãy xem xét việc mua webcam với ống kính 180 ° (được gọi là Fisheye). Nếu bạn không quan tâm đến Full HD, có những webcam mắt cá ngoài kia với giá chỉ $ 30. Chụp ảnh 640 × 480 với FOV 180 ° và cắt vùng 120 × 90 sẽ cho kết quả FOV hiệu quả khoảng 33 °.


1
Đó là các chế độ cảm biến riêng của máy ảnh, nhưng bạn có thể chụp ở mọi độ phân giải; GPU sẽ xử lý lấy mẫu hình ảnh xuống bất kỳ độ phân giải được yêu cầu. Tôi sẽ viết lên một câu trả lời đầy đủ hơn trong một mo, nhưng tôi sợ cách giải thích này hoàn toàn sai.
Dave Jones

@DaveJones Tôi sai là thực sự rất có thể. Tuy nhiên, tôi thấy hơi lãng phí khi mua máy ảnh 5MP để chụp ảnh 120 × 90, vì vậy tôi vẫn đề nghị mua một webcam giá rẻ. Ngoài ra, cần phải trả giá cho việc xử lý GPU này (bộ nhớ video? Bộ nhớ bộ đệm khung?)
Dmitry Grigoryev

1
Không có giá CPU cho lớp phủ video (nó hoàn toàn không sử dụng bộ đệm khung - chỉ cần rút thẳng ra HDMI / composite để Linux thậm chí không biết về bản xem trước của máy ảnh - đó là một trong những lý do bạn không thể dễ dàng "Dán nó trong một cửa sổ"). Rõ ràng là nó sử dụng một lượng năng lượng GPU nhất định nhưng nhìn chung đó không phải là vấn đề đáng lo ngại (ngoại trừ điều hiển nhiên nếu bạn đang chạy Pi trên pin :)
Dave Jones

1
Tôi cũng nên giải thích lý do tại sao tôi gọi cách giải thích của bạn là "sai": các chế độ được liệt kê không phải là "độ phân giải được hỗ trợ". Trên thực tế, nếu bạn thử v4l2-ctl --list-formats-extvới trình điều khiển V4L2 của mô-đun máy ảnh pi được tải ( sudo modprobe bcm2835-v4l2), bạn sẽ thấy nó liệt kê tải các chế độ với "Kích thước: Stepwise 32x32 - 2592x1944 với bước 2/2" (đó là từ mô-đun v1). Điều đó có nghĩa là nó hỗ trợ bất kỳ độ phân giải nào từ 32x32 đến 2592x1944 theo các bước của 2x2; phần sụn sẽ làm hết sức mình để tối đa hóa foV cho độ phân giải đã chọn, nhưng tự nhiên có giới hạn cho điều đó.
Dave Jones
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.