2012-06-13 32 views
13

Tôi mới dùng opencv và tôi có một nghi ngờ với một trong các thao tác đơn giản nhất trong mã hóa: Truyền các giá trị cho các hàm.Vượt qua các ma trận đơn giản tức là. cv :: Mat cho các hàm trong OpenCV2.4

Heres những gì tôi muốn làm,

  1. Khởi tạo một cv:Mat trong hàm chính với tiếng nói, các giá trị từ 0 đến 50.
  2. Vượt qua ma trận này như một tham số để một hàm foo() do đó đơn giản in ra các giá trị của mỗi phần tử trong ma trận. Đó là nó.

Bây giờ tôi đã đọc ở nhiều nơi khi các ma trận này được thông qua, nó chỉ là tiêu đề được chuyển, chứ không phải là dữ liệu thực tế. Sau đó, làm thế nào tôi vẫn có thể đọc ra các giá trị của ma trận này trong chức năng được gọi là nếu toàn bộ ma trận đã được thông qua?

+0

Các địa điểm này ở đâu? Bạn có thể chia sẻ tài liệu tham khảo cho họ không? – karlphillip

+0

http://opencv.willowgarage.com/documentation/cpp/memory_management.html –

Trả lời

31

Để hiểu những gì đang xảy ra bạn cần phải có một cái nhìn tại C++ constructors, cụ thể các copy constructor hơn.

Khi bạn tạo một cv::Mat từ cv::Mat khác, như trong:

cv::Mat a = cv::imread("huge.png", 1); 
cv::Mat b = a; 

các copy constructor (mà là một chức năng) của cv::Mat được gọi để thực hiện các bản sao của đối tượng. Trước khi tôi nói về những gì xảy ra trong quy trình sao chép, bạn phải nhận ra rằng vì cv::Mat được sử dụng để lưu trữ hình ảnh, hình ảnh lớn hơn có thể chiếm hàng trăm MB trong bộ nhớ. Vì vậy, công cụ sao chép sao chép của cv::Mat trong ví dụ trên là sao chép toàn bộ tiêu đề (chiều cao, chiều rộng, thông tin chiều sâu và các phần khác) của a vào b, nhưng thay vì sao chép toàn bộ dữ liệu/pixel của a (có thể là hàng trăm của MB), nó chỉ trỏ (sử dụng một con trỏ) đến dữ liệu gốc của a.

Nói cách khác, không sao chép toàn bộ dữ liệu hình ảnh là quyết định tối ưu hóa/hiệu suất.

Bây giờ, hãy xem xét mã này mà các cuộc gọi một chức năng và vượt qua cv::Mat như một tham số:

void do_something(cv::Mat src) 
{ 
    // changing src pixels will be the same as changing orig pixels 
} 

int main() 
{ 
    cv::Mat orig = cv::imread("huge.png", 1); 
    do_something(orig); 
    return 0; 
} 

Nếu bạn đã nghiên cứu làm thế nào để vượt qua các thông số chức năng, bạn biết rằng gọi do_something(a); sẽ pass the parameter by value. Điều này có nghĩa là nó sẽ cố gắng sao chép nội dung của orig vào src, tuy nhiên, quy trình này kích hoạt trình tạo bản sao của cv::Mat mà sẽ không tạo bản sao dữ liệu cứng như tôi vừa giải thích.

Giải pháp cho vấn đề này? Nếu bạn đang viết do_something() và bạn chỉ muốn tạo một bản sao thực sự của orig, chỉ cần tạo một mới cv::Mat và gọi phương thức copyTo():

void do_something(cv::Mat src) 
{ 
    cv::Mat real_copy = src.copyTo(); 
    // operating on the data of real_copy will not affect orig 
} 

Nhưng hãy nhớ, nếu src là ~ 100MB gọi copyTo() để làm cho bản sao thực sẽ chiếm một ~ 100MB bộ nhớ khác, điều đó có nghĩa là trong một hàm duy nhất gọi chương trình của bạn chỉ cần đi từ 100MB đến 200MB.Hãy ghi nhớ điều này khi thiết kế hệ thống của bạn. Chúc may mắn.

+4

Tuyệt vời. Nó giống như bạn đọc được suy nghĩ của tôi và trả lời chính xác câu hỏi mà tôi có. Cảm ơn ngài rất nhiều. Nhiều đánh giá cao. –

+1

Tuyệt vời, chỉ cần nhấp vào hộp kiểm gần đó để chọn nó làm câu trả lời chính thức. – karlphillip

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