2010-02-17 17 views
7

Tôi đang cố gắng sử dụng Python và Numpy/Scipy để triển khai thuật toán xử lý hình ảnh. Các hồ sơ nói với tôi rất nhiều thời gian đang được chi tiêu trong hàm sau (gọi là thường xuyên), mà nói với tôi tổng chênh lệch vuông giữa hai hình ảnhTổng số khác biệt về hình vuông (SSD) ở dạng khối/scipy

def ssd(A,B): 
    s = 0 
    for i in range(3): 
     s += sum(pow(A[:,:,i] - B[:,:,i],2)) 
    return s 

Làm thế nào tôi có thể tăng tốc độ này lên? Cảm ơn.

Trả lời

27

Chỉ

s = numpy.sum((A[:,:,0:3]-B[:,:,0:3])**2) 

(mà tôi mong đợi là khả năng chỉ sum((A-B)**2) nếu hình dạng luôn là (,, 3))

Bạn cũng có thể sử dụng phương pháp tổng hợp: ((A-B)**2).sum()

Đúng?

+2

Bàng. Tôi đang có một ngày chậm chạp. Giảm một nửa thời gian chạy của tôi. –

+0

Cần lưu ý rằng, bạn sẽ phải sử dụng 'numpy.sum', không phải' tổng hợp ', mà sẽ tìm tổng trên kích thước thứ nhất và trả về một mảng mới có kích thước một chiều. –

+0

((A-B) ** 2) .sum (-1) Nếu bạn chỉ muốn thêm trên trục cuối cùng, thì đối số trục cần được chỉ định. Chỉ cần sử dụng sum() cho biết thêm tất cả các mục của mảng (raveled đầu tiên) – user333700

1

Tôi không biết liệu hàm pow() với nguồn 2 có nhanh không. Hãy thử:

def ssd(A,B): 
    s = 0 
    for i in range(3): 
     s += sum((A[:,:,i] - B[:,:,i])*A[:,:,i] - B[:,:,i]) 
    return s 
1

Tôi nhầm lẫn lý do bạn đang dùng i in range(3). Đó có phải là toàn bộ mảng, hay chỉ là một phần?

Nhìn chung, bạn có thể thay thế hầu hết những điều này với các hoạt động quy định tại NumPy:

def ssd(A,B): 
    squares = (A[:,:,:3] - B[:,:,:3]) ** 2 
    return numpy.sum(squares) 

Bằng cách này bạn có thể thực hiện một hoạt động thay vì ba và sử dụng numpy.sum có thể tối ưu hóa việc bổ sung tốt hơn so với xây dựng trong sum .

+2

+1 Đây là cách 'scipy.stats.stats.ss' (tổng của hình vuông) hiện nó. – unutbu

1

Thêm vào câu trả lời của Ritsaert Hornstra có 2 dấu âm (phải thừa nhận là tôi không thấy nó ở dạng ban đầu ...)

Điều này thực sự đúng.

Đối với một số lượng lớn các lần lặp lại, có thể mất gấp đôi thời gian để sử dụng toán tử '**' hoặc phương thức (x, y) để ghép các cặp lại với nhau theo cách thủ công. Nếu cần thiết sử dụng phương thức math.fabs() nếu nó ném ra NaN (mà đôi khi nó đặc biệt là khi sử dụng int16s vv), và nó vẫn chỉ mất khoảng một nửa thời gian của hai hàm được đưa ra.

Điều đó không quan trọng đối với câu hỏi ban đầu mà tôi biết, nhưng chắc chắn đáng biết.

-3

Trong ngôn ngữ Ruby bạn có thể đạt được điều này bằng cách này

def diff_btw_sum_of_squars_and_squar_of_sum(from=1,to=100) # use default values from 1..100. 
((1..100).inject(:+)**2) -(1..100).map {|num| num ** 2}.inject(:+) 
end 

diff_btw_sum_of_squars_and_squar_of_sum #call for above method 
Các vấn đề liên quan