2013-09-23 123 views
6

Tôi đã cố gắng tối ưu hóa mã của mình và nhận thấy rằng một trong các mã của tôi là một nút cổ chai. Mã của tôi là:Tính toán nhanh độ dốc của hình ảnh trong MATLAB

function [] = one(x) 
I = imread('coins.png'); 
I = double(I); 
I = imresize(I,[x x]); 
sig=.8; % scale parameter in Gaussian kernel 
G=fspecial('gaussian',15,sig); % Caussian kernel 
Img_smooth=conv2(I,G,'same'); % smooth image by Gaussiin convolution 
[Ix,Iy]=gradient(Img_smooth); 
f=Ix.^2+Iy.^2; 
g=1./(1+f); % edge indicator function. 
end 

Tôi đã cố gắng chạy như sau: xóa tất cả;

x=4000;N=1; 
tic 
for i=1:N 
    one(x); 
end 
toc 

tôi thấy rằng số lượng lớn nhất của thời gian đã được tiêu thụ bởi các nhà điều hành dốc statement (khoảng 60%) trong tổng số thời gian. Vì vậy, nó đã cho tôi suy nghĩ làm thế nào tôi có thể tối ưu hóa mã của tôi hơn nữa ....

tôi tham khảo ý kiến ​​vài trang web thích: Dgradienthttp://regularize.wordpress.com/2013/06/19/how-fast-can-you-calculate-the-gradient-of-an-image-in-matlab/

Tuy nhiên Dgradient là một tập tin MEX và tôi không muốn sử dụng nó. Tôi muốn viết chức năng gradient của riêng tôi. Tôi đọc trong các blog rằng toán tử gradient trong MATLAB chậm hơn đáng kể và được tăng tốc bằng cách sử dụng shift & ma trận trừ và thưa thớt.

Tôi không có kiến ​​thức về ma trận thưa thớt. Tuy nhiên tôi đã thử làm điều đó bằng cách sử dụng phương thức shift và substract. Tuy nhiên Tôi chắc chắn rằng mã của tôi là sai. Xin vui lòng bất cứ ai có thể làm rõ những loại khác biệt MATLAB sử dụng để tính toán gradient của nó? Và chỉ cho tôi cách làm điều đó trong mã của tôi?

clc;clear all;close all; 
I = imread('coins.png'); 
I = double(I(:,:,1)); 
I = imresize(I,[4 4]); 

tic 
[dx dy] = gradient(I); 
toc 

tic 
%//Doing forward difference on both directions 
dx1 = [I(:,2:end) I(:,end)] - I; 
dy1 = [I(2:end,:);I(end,:)] - I; 
toc 

Các bạn có thể xem mã và đề xuất cho tôi cách áp dụng chính xác không? Hoặc hướng dẫn tôi làm thế nào để làm như vậy bằng cách sử dụng ma trận thưa thớt?

+1

bạn đã thử sử dụng 'diff' chưa? http://www.mathworks.com/help/matlab/ref/diff.html – Dan

+0

diff hoạt động với mảng 1D và tôi đang làm việc trên Hình ảnh 2D hoặc 3D. Vui lòng giải thích cách khác biệt được áp dụng trong trường hợp của tôi? – roni

+1

'khác biệt (I, 1,2)' khác biệt giữa các cột, tức là giống như 'dx1' của bạn. Xin vui lòng đọc liên kết doc tôi đăng, diff không chỉ áp dụng cho mảng 1D. – Dan

Trả lời

3

Nhờ tất cả các câu trả lời và đề xuất hữu ích của bạn. Tôi mất những gợi ý của pseudoDust, Hugues, DimaHigh Performance Đánh dấu và viết mã của riêng tôi. Mã của tôi được đưa ra dưới đây:

clc;clear all;close all; 
x=32; 
I = imread('coins.png'); 
I = imresize(I,[x x]); 
I = double(I(:,:,1)); 

tic 
[dx dy] = gradient(I); 
toc 

tic 
[m,n]=size(I); 
A = [I(:,2:end) zeros(m,1)]; 
B = [zeros(m,1) I(:,1:end-1)]; 
dx1 = [I(:,2)-I(:,1) (A(:,2:end-1)-B(:,2:end-1))./2 I(:,end)-I(:,end-1)]; 
A = [I(2:end,:) ; zeros(1,n)]; 
B = [zeros(1,n) ; I(1:end-1,:)]; 
dy1 = [I(2,:)-I(1,:) ; (A(2:end-1,:)-B(2:end-1,:))./2 ; I(end,:)-I(end-1,:)]; 
toc 

nnz(dx-dx1) 
nnz(dy-dy1) 

ý tưởng cơ bản của tôi là: trung bình Gradient 2 vị trí liền kề (trái và phải hoặc trên và dưới), trừ các cạnh nơi nó mất phần chênh lệch giữa giá trị và vị trí liền kề. Sau đó tôi đã kiểm tra ma trận do tôi tạo ra (dx1, dy1) với ma trận được tạo bởi hàm gradient matlab (dx, dy).

Elapsed time is 0.010232 seconds. 
Elapsed time is 0.000066 seconds. 
ans = 
    0 
ans = 
    0 

Vì vậy, tôi tin rằng mã của tôi là chính xác. Ngoài ra các kết quả thời gian là đáng ngạc nhiên để nói rằng ít nhất. Sau đó, tôi đã định thời gian mã của mình bằng mã MATLAB cho các kích thước khác nhau của hình ảnh.

tôi nhận kết quả này:


%x=16 
Elapsed time is 0.010790 seconds. 
Elapsed time is 0.000057 seconds. 
%x=32 
Elapsed time is 0.010564 seconds. 
Elapsed time is 0.000069 seconds. 
%x=64 
Elapsed time is 0.010627 seconds. 
Elapsed time is 0.000152 seconds. 
%x=128 
Elapsed time is 0.011346 seconds. 
Elapsed time is 0.000669 seconds. 
%x=256 
Elapsed time is 0.017311 seconds. 
Elapsed time is 0.004468 seconds. 
%x=512 
Elapsed time is 0.044148 seconds. 
Elapsed time is 0.030435 seconds. 
%x=1024 
Elapsed time is 0.093386 seconds. 
Elapsed time is 0.093029 seconds. 
%x=2048 
Elapsed time is 0.345423 seconds. 
Elapsed time is 0.387762 seconds. 

Vì vậy, kết luận của tôi là thế này: Đối với kích thước hình ảnh tối đa 1024x1024 mã của tôi là nhanh hơn so với inbuilt lệnh gradient trong matlab.

Edit: Tôi cập nhật câu trả lời của tôi và thêm vào biểu đồ này:

Nó cho thấy rõ ràng rằng cho kích thước mảng nhỏ hơn mã của tôi là nhanh hơn so với chức năng matlab dốc đáng kể.

enter image description here

là mã của tôi có đúng không? Các bạn hãy xem qua và kiểm tra. Làm phản hồi của bạn. Tôi thực sự là một người mới trong MATLAB và rất ngạc nhiên bởi kết quả này. Vui lòng kiểm tra xem những gì tôi đang làm là đúng hay không?

2
dx1 = (I(:,[1:end end]) - I(:,[1 1:end])); 
dx1(:,2:(end-1))=dx1(:,2:(end-1))*0.5; 
dy1 = (I([1:end end],:) - I([1 1:end],:)); 
dy1(2:(end-1),:)=dy1(2:(end-1),:)*0.5; 

Nên làm việc, gradient trung bình 2 vị trí liền kề (trái và phải hoặc trên và dưới), trừ các cạnh cần chênh lệch giữa giá trị và vị trí liền kề.

+0

Tôi đang cố gắng viết một hàm gradient thực hiện chính xác như lệnh gradient trong MATLAB thực hiện nhưng nhanh hơn đáng kể. Đó là lý do tại sao tôi đang thử nó. Lệnh của bạn cung cấp một số giá trị khác. – roni

+0

Xin chào một lần nữa, bạn có thể xem lại mã của mình không. Tôi đã thử nó nhưng câu trả lời là không đúng. Vui lòng kiểm tra và cho tôi biết – roni

+0

Vui lòng kiểm tra câu trả lời của tôi và cho tôi biết – roni

1

Thật tuyệt khi bạn muốn viết chức năng gradient của riêng mình và như đã đề cập trong blog, một số phương pháp tốt hơn các phương pháp khác. Tuy nhiên, mục nhập blog so sánh các vòng lặp lồng nhau để dịch chuyển và trừ và ma trận thưa thớt; không nơi nào nó nói rằng gradient là chậm hoặc không được tối ưu hóa. Các hàm Matlab Usualy được thực hiện trong C++ và sử dụng các thư viện BLAS và LAPACK. Họ nên đánh bại bất kỳ kỹ thuật nào bạn đề xuất, nhưng hãy tiếp tục và vui lòng kiểm tra điều đó cho chúng tôi :-)

Về mã của bạn, tôi nghi ngờ rằng bạn muốn thay đổi kích thước hình ảnh của mình thành [4 4]! Nếu không, mã của bạn là chính xác.

Bạn đã mặc nhiên sử dụng một nhà điều hành Robert cho gradient (dI/dx = I(x+1) - I(x))

Chức năng gradient sử dụng sự khác biệt trung ương, [- 1 0 1] trong x-hướng.

Kết quả bằng số cho mỗi toán tử sẽ khác đôi chút.

Lưu ý rằng trong Matlab R2013a, hàm imgradient sử dụng toán tử Sobel, [1 0 -1; 2 0 -2;1 0 -1] theo hướng x.

Nên lấy một cái nhìn tại imgradient

+0

Xin chào. Cảm ơn vì đã trả lời. Bạn có thể cho tôi biết sự khác biệt giữa lệnh gradient bình thường và lệnh imgradient là gì? – roni

+1

http: //www.mathworks.se/help/matlab/ref/gradient.html và http://www.mathworks.se/help/images/ref/imgradient.html. Về cơ bản bạn không có bất kỳ tùy chọn trong một cơ bản. Phiên bản im cho phép bạn chọn hạt nhân, cho dù sử dụng GPU, v.v. –

+0

Cảm ơn bạn. Có, tôi đã đọc tài liệu. Thật không may nó chỉ có sẵn trong R2013 và tôi đang sử dụng R2012. Nhưng bạn có thể cho tôi biết cả hai đều đưa ra cùng một câu trả lời nếu tôi sử dụng trường hợp mặc định trong lệnh imgradient? Như tôi không có Matlab 2013A tôi không thể kiểm tra. – roni

0

Nếu bạn có một phiên bản gần đây của Matlab (R2012b trở lên, IIRC) và Image Processing Toolbox, sau đó bạn có thể sử dụng chức năng imgradient.

+0

imgradient không có sẵn trong 2012a – roni

+0

True. Nhưng năm 2013a mới xuất hiện. – Dima

+0

không công bằng :(:(thực sự là – roni