2010-09-15 30 views
8

Tôi có một ứng dụng mà tôi cần lấy cường độ trung bình của hình ảnh cho khoảng 1 triệu hình ảnh. Nó "cảm thấy" giống như một công việc cho một shader mảnh của GPU, nhưng các shader fragment là cho các tính toán cục bộ cho mỗi pixel, trong khi hình ảnh trung bình là một hoạt động toàn cục.Tổng cường độ hình ảnh trong GPU

Một cách tiếp cận tôi xem là tải hình ảnh vào kết cấu, áp dụng hiệu ứng nhòe hộp 2x2, tải kết quả trở lại vào kết cấu N/2 x N/2 và lặp lại cho đến khi đầu ra là 1x1. Tuy nhiên, điều này sẽ có các ứng dụng đăng nhập n của trình đổ bóng.

Có cách nào để thực hiện điều đó trong một lần không? Hay tôi nên chia nhỏ và sử dụng CUDA/OpenCL?

+0

Ứng dụng của tôi đang thực hiện kết hợp Chamfer của mô hình 3D được chiếu với hình ảnh đầu vào. Tôi vẽ một hình ảnh chứa các cạnh hình bóng của mô hình của tôi và đối với mọi pixel cạnh, tôi sử dụng bảng tra cứu để tìm pixel cạnh gần nhất trong hình ảnh đầu vào. Sau đó, tôi cần kết quả trung bình, cho tôi biết mô hình phù hợp với dữ liệu. Tôi đã thử đọc các điểm ảnh được hiển thị từ opengl và thực hiện kết hợp chamfer trên CPU, nhưng hoạt động đọc là một nút cổ chai lớn.Tôi đã hy vọng rằng bằng cách làm toàn bộ điều trên GPU và chỉ đọc trong một giá trị duy nhất, tôi sẽ nhận được một tốc độ lớn. –

+0

(ctd) Vì tôi có thể vượt qua bảng tra cứu dưới dạng kết cấu, tôi có thể thực hiện tra cứu trong trình đổ bóng, nhưng tôi vẫn có nút cổ chai của việc đọc dữ liệu vào bộ nhớ chính. –

+0

Không có gì buộc bạn làm mờ 2x2, - bạn có thể làm ví dụ làm mờ với hộp 16x16 và sau đó kết quả tải vào N/16 x N/16 kết cấu. Theo cách đó, bạn có thể đạt được tốc độ lớn và ít hoạt động sao chép ... –

Trả lời

4

Thao tác tổng hợp là trường hợp cụ thể của "giảm", một hoạt động chuẩn trong thư viện CUDA và OpenCL. Một ghi chú tốt đẹp trên nó có sẵn trên cuda demos page. Trong CUDA, ThrustCUDPP chỉ là hai ví dụ về thư viện cung cấp giảm. Tôi không quen thuộc với OpenCL, nhưng CLPP có vẻ là một thư viện tốt cung cấp giảm. Chỉ cần sao chép bộ đệm màu của bạn vào đối tượng bộ đệm pixel OpenGL và sử dụng cuộc gọi khả năng tương tác OpenGL thích hợp để làm cho bộ nhớ đệm của pixel đó có thể truy cập được trong CUDA/OpenCL.

Nếu nó phải được thực hiện bằng cách sử dụng API opengl (như câu hỏi ban đầu được yêu cầu), giải pháp là kết xuất với kết cấu, tạo mipmap của kết cấu và đọc trong kết cấu 1x1. Bạn phải thiết lập quyền lọc (bilinear là thích hợp, tôi nghĩ), nhưng nó sẽ nhận được gần với câu trả lời đúng, sai số chính xác modulo.

1

Đường ruột của tôi yêu cầu tôi thử triển khai của bạn trong OpenCL. Bạn có thể tối ưu hóa cho kích thước hình ảnh và phần cứng đồ họa của bạn bằng cách chia nhỏ hình ảnh thành các khối dữ liệu riêng biệt sau đó được tổng hợp song song. Có thể rất nhanh.

Trình tạo bóng phân đoạn rất tuyệt vời cho các cuộc cách mạng nhưng kết quả đó thường được ghi vào gl_FragColor để nó có ý nghĩa. Cuối cùng, bạn sẽ phải lặp qua tất cả các điểm ảnh trong kết cấu và tổng kết quả mà sau đó được đọc lại trong chương trình chính. Việc tạo ra các số liệu thống kê hình ảnh có lẽ không phải là những gì mà trình đổ bóng phân mảnh được thiết kế và không rõ rằng một hiệu năng chính có được là do nó không được bảo đảm một bộ đệm cụ thể nằm trong bộ nhớ GPU.

Có vẻ như bạn có thể áp dụng thuật toán này cho một viễn cảnh phát hiện chuyển động theo thời gian thực hoặc một số ứng dụng phát hiện tính năng tự động khác. Có thể nhanh hơn để tính toán một số thống kê từ một mẫu pixel thay vì toàn bộ hình ảnh và sau đó tạo một trình phân loại học máy.

Chúc bạn may mắn nhất trong mọi trường hợp!

+0

Cảm ơn bạn đã trả lời. Tôi sẽ xem xét OpenCL. –

1

Không cần CUDA nếu bạn muốn gắn bó với GLSL. Giống như trong giải pháp CUDA được đề cập ở đây, nó có thể được thực hiện trong một bóng mờ staight về phía trước. Tuy nhiên, bạn cần về các cuộc gọi vẽ nhật ký (độ phân giải). Chỉ cần thiết lập trình đổ bóng lấy mẫu 2x2 pixel từ hình ảnh gốc và xuất tổng số trung bình của các hình ảnh đó. Kết quả là một hình ảnh có độ phân giải một nửa ở cả hai trục. Lặp lại điều đó cho đến khi hình ảnh là 1x1 px. Một số lưu ý: Sử dụng GL_FLOAT kết cấu độ sáng nếu có, để có tổng chính xác hơn. Sử dụng glViewport để đặt khu vực hiển thị trong từng giai đoạn. Kết quả sau đó kết thúc ở pixel trên cùng bên trái của bộ đệm khung của bạn.

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