Tôi đã làm việc khá nhiều với Android và tối ưu hóa (tôi đã viết một ứng dụng xử lý video xử lý khung trong 4ms) vì vậy tôi hy vọng tôi sẽ cung cấp cho bạn một số câu trả lời thích hợp.
Không có nhiều khác biệt giữa giao diện C và C++ trong OpenCV. Một số mã được viết bằng C, và có một trình bao bọc C++ và một số phó từ. Bất kỳ sự khác biệt đáng kể nào giữa hai (được đo bằng Shervin Emami) là hồi quy, sửa lỗi hoặc cải thiện chất lượng. Bạn nên gắn bó với phiên bản OpenCV mới nhất.
Tại sao không viết lại?
Bạn sẽ dành nhiều thời gian để sử dụng tốt hơn. Giao diện C là cồng kềnh, và cơ hội để giới thiệu lỗi hoặc rò rỉ bộ nhớ là cao. Bạn nên tránh nó, theo ý kiến của tôi.
Lời khuyên dành cho tối ưu hóa
A. Bật tối ưu hóa.
Cả tối ưu hóa trình biên dịch và thiếu xác nhận gỡ lỗi có thể tạo sự khác biệt lớn trong thời gian chạy của bạn.
B. Hồ sơ ứng dụng của bạn.
Làm điều đó trước trên máy tính của bạn, vì nó dễ dàng hơn nhiều. Sử dụng profiler studio trực quan, để xác định các phần chậm. Tối ưu hóa chúng. Không bao giờ tối ưu hóa vì bạn nghĩ là chậm, nhưng vì bạn đo lường nó. Bắt đầu với chức năng chậm nhất, tối ưu hóa nó càng nhiều càng tốt, sau đó đi chậm thứ hai. Đo lường các thay đổi của bạn để đảm bảo rằng các thay đổi đó thực sự nhanh hơn.
C. Tập trung vào thuật toán.
Thuật toán nhanh hơn có thể cải thiện hiệu suất với các đơn đặt hàng có độ lớn (100x). Một thủ thuật C++ sẽ giúp bạn tăng hiệu năng gấp 2 lần.
kỹ thuật cổ điển:
Resize bạn khung hình video phải nhỏ hơn. Thông thường, bạn có thể trích xuất thông tin từ hình ảnh 200x300px thay vì 1024x768. Diện tích đầu tiên nhỏ hơn 10 lần.
Sử dụng các thao tác đơn giản hơn thay vì thao tác phức tạp. Sử dụng số nguyên thay vì phao. Và không bao giờ sử dụng double
trong ma trận hoặc vòng lặp for
thực thi hàng nghìn lần.
Làm càng ít phép tính càng tốt. Bạn có thể theo dõi một đối tượng chỉ trong một khu vực cụ thể của hình ảnh, thay vì xử lý tất cả đối tượng đó cho tất cả các khung hình không? Bạn có thể phát hiện thô/gần đúng trên một hình ảnh rất nhỏ và sau đó tinh chỉnh nó trên ROI trong toàn bộ khung hình không?
D. Sử dụng C mà nó quan trọng
Trong vòng, nó có thể làm cho tinh thần để sử dụng C phong cách thay vì C++. Một con trỏ tới một ma trận dữ liệu hoặc một mảng float nhanh hơn nhiều so với mat.at hoặc std :: vector <>. Thường thì nút cổ chai là một vòng lặp lồng nhau. Tập trung vào nó.Nó không có ý nghĩa để thay thế vector <> trên tất cả các nơi và spaghettify mã của bạn.
E. Tránh ẩn chi phí
Một số chức năng OpenCV chuyển đổi dữ liệu tăng gấp đôi, quá trình đó, sau đó chuyển đổi lại định dạng đầu vào. Cẩn thận với họ, họ giết hiệu suất trên các thiết bị di động. Ví dụ: cong vênh, mở rộng quy mô, nhập chuyển đổi. Ngoài ra, chuyển đổi không gian màu được biết là lười. Ưu tiên thang độ xám thu được trực tiếp từ YUV gốc.
F. Sử dụng vector hóa
vi xử lý ARM thực hiện vector hóa với một công nghệ gọi là NEON. Học cách sử dụng nó. Nó mạnh mẽ!
Một ví dụ nhỏ:
float* a, *b, *c;
// init a and b to 1000001 elements
for(int i=0;i<1000001;i++)
c[i] = a[i]*b[i];
thể được viết lại như sau. Đó là tiết, nhưng nhanh hơn nhiều.
float* a, *b, *c;
// init a and b to 1000001 elements
float32x4_t _a, _b, _c;
int i;
for(i=0;i<1000001;i+=4)
{
a_ = vld1q_f32(&a[i]); // load 4 floats from a in a NEON register
b_ = vld1q_f32(&b[i]);
c_ = vmulq_f32(a_, b_); // perform 4 float multiplies in parrallel
vst1q_f32(&c[i], c_); // store the four results in c
}
// the vector size is not always multiple of 4 or 8 or 16.
// Process the remaining elements
for(;i<1000001;i++)
c[i] = a[i]*b[i];
Purists say bạn phải viết trong trình biên dịch, nhưng đối với một lập trình viên thông thường thì hơi khó khăn. Tôi đã có kết quả tốt bằng cách sử dụng gcc intrinsics, như trong ví dụ trên.
Cách khác để bắt đầu là chuyển mã mã được tối ưu hóa SSE được mã hóa bằng tay trong OpenCV sang NEON. SSE tương đương với NEON trong bộ vi xử lý Intel và nhiều chức năng OpenCV sử dụng nó, như here. Đây là mã lọc hình ảnh cho ma trận uchar (định dạng hình ảnh thông thường). Bạn không nên chuyển đổi một cách mù quáng từng người một, nhưng lấy nó làm ví dụ để bắt đầu.
Bạn có thể đọc thêm về NEON trong this blog và các bài đăng sau.
G. Chú ý đến chụp ảnh
Nó có thể là đáng ngạc nhiên chậm trên một thiết bị di động. Tối ưu hóa nó là thiết bị và hệ điều hành cụ thể.
Tôi không quen với Android nói riêng, nhưng việc sử dụng giao diện C của OpenCV không mang lại cho bạn hiệu suất đáng kể nào vì nó vẫn sử dụng cùng một mã cơ sở. – Mohammad
Tôi đã thêm một số thông tin khác vào câu trả lời của tôi, hy vọng bạn sẽ thấy nó hữu ích. – Sam