2014-09-04 106 views
1

我有一大組顯微鏡圖像,每個圖像有數百個點(ROI)。這些斑點固定在空間中。我想從每個圖像中提取每個點並保存到工作區,以便我可以進一步分析它們。從數千個圖像中提取許多感興趣區域ROI)

我自己寫了一個代碼,它的工作完美,但它太慢了。大約需要250秒才能從每幅圖像中完整地讀出所有斑點。

我的代碼的核心看起來如下:

for s=1:NumberImages 
    im1=imread(fn(s,1).name);  
    im=im1-medfilt2(im1,[15,15]);  
    for i=1:length(p_g_x)  
    GreenROI(i,s)=double(sum(sum(im(round(p_g_y(i))+(-2:2), round(p_g_x(i))+(-2:2))))); 
    RedROI(i,s)=double(sum(sum(im(round(p_r_y(i))+(-2:2), round(p_r_x(i))+(-2:2)))));   
    end 
end 

你可以從我解壓5x5的地區代碼中看到。 p_g_x的長度在500-700之間。

感謝您的輸入。我使用配置文件查看器來確定哪個功能需要更多時間。這是需要很多時間(〜90%)的中值濾波器。

任何建議加快它將不勝感激。

感謝

馬希普爾

+1

您正在總結5x5以上的區域,而不是4x4 ... – Unapiedra 2014-09-04 08:40:06

+0

區域是否重疊? – Shai 2014-09-04 08:42:28

+0

請用你在'p_g_x'和'p_g_y'中使用的值編輯你的問題。如果這太大,請添加一個相同的較小樣本。 – Unapiedra 2014-09-04 08:43:21

回答

0

首先,預先分配的GreenROI和RedROI結構,因爲您以前知道最終的尺寸。現在,您在每次迭代中一次又一次地調整大小。其次,我建議你使用「tic」和「toc」來調查問題出在哪裏,它會給你有用的時間。

+1

除了使用'tic'和'toc',你還可以看看Matlab的[性能分析功能](http://www.mathworks.de/de/help/matlab/matlab_prog/profiling-for-improving-performance .html) – AdrianoKF 2014-09-04 08:36:41

3

使用Matlab的分析工具!

profile on % Starts the profiler 
% Run some code now. 
profile viewer % Shows you how often each function was called, and 
       % where most time was spent. Try to start with the slowest part. 
profile off % Resets the Profiler, so you can measure again. 

預分配

預分配和輸出,因爲你知道的大小這樣它的速度要快得多。 (Matlab的告訴你,這已經!)

GreenROI = zeros(length(p_g_x), NumberImages); % And the same for RedROI. 

使用卷積

閱讀有關Matlab的conv2代碼。

for s=1:NumberImages 
    im=imread(fn(s,1).name);  
    im=im-medfilt2(im,[15,15]);  
    % Pre-compute the sums first. This will only be faster for large p_g_x 
    roi_image = conv2(im, ones(5,5)); 
    for i=1:length(p_g_x)  
    GreenROI(i,s)=roi_image(round(p_g_y(i)), round(p_g_x(i))); % You might have to offset the indices by 2, because of the convolution. Check that results are the same. 
    RedROI(i,s)=roi_image(round(p_r_y(i)), round(p_r_x(i)));   
    end 
end 

Matlab的IZE代碼

現在,您已經使用卷積拿到過5×5的窗口總和的圖像(或者你可以使用過夏嘉曦@的accumarray,同樣的事情),你可以通過不重複遍歷中的每個元素,可以進一步加快速度,但可以立即使用它作爲矢量。

我把這留給讀者作爲練習。 (作爲提示,將p_g_xp_g_y轉換爲使用sub2ind的索引)。

更新

我們的答案,包括礦山,表明過早的優化是一個多麼糟糕的事情。不知道,我認爲你的循環會佔用大部分時間,但是當你測量它時(謝謝!)事實證明,這不是問題。瓶頸是medfilt2中值過濾器,這需要90%的時間。所以你應該首先解決這個問題。(請注意,在我的電腦上,您的原始代碼足夠我的口味,但它仍然是大部分時間佔用的中值濾波器。)

看看中值濾波器操作的作用可能會幫助我們弄清楚如何使其更快。這是一張圖片。在左邊看到原始圖像。中間是中值濾波器,右邊是結果。

enter image description here

對我來說,結果看起來非常類似於邊緣檢測結果。 (在數學上,這並不奇怪。)

我建議你開始試驗各種邊緣檢測。看看Canny和Sobel。或者只是使用conv2(image, kernel_x),其中kernel_x = [1, 2, 1; 0, 0, 0; -1, -2, -1]kernel_y相同,但轉置。您可以在這裏找到各種邊緣檢測選項:edge(im, option)。我嘗試了{'sobel', 'canny', 'roberts', 'prewitt'}的所有選項。除Canny之外,它們都與中位數過濾方法大致相同。 Canny的速度慢了4倍,其餘的(包括原來的)都是7.x秒。所有這些都沒有GPU。 imgradient是9秒。

因此,從這我會說,你不能得到任何更快。如果你有一個GPU,它可以和Matlab協同工作,你可以加快速度。加載你的圖像爲gpuArray s。在medfilt2 documentation上有一個例子。你仍然可以做小幅加速,但它們只能達到10%的速度提升,所以幾乎不可能。

+0

@Shai肯定。我首先想到了積分圖像,但後來發現矩形總是相同的大小(5x5),所以他可以使用卷積代替。 – Unapiedra 2014-09-04 09:02:59

+0

感謝您的輸入。我使用配置文件查看器來確定哪個功能需要更多時間。這是需要很多時間(〜90%)的中值濾波器。 – 2014-09-04 09:53:20

+0

我剛剛做了一些時機,對於我來說,您的原始代碼需要7秒鐘,而不是250秒(100幅圖像,500個投資回報率)。如果中值濾波器確實需要所有的時間,那麼你可以做的只是增加速度。你可以問一個關於「在Matlab中加速中值濾波」的單獨問題。 – Unapiedra 2014-09-04 09:58:31

2

有幾件事情你應該做的

  1. Pre-allocate通過Didac Perez的建議。

  2. 使用profiler,看看究竟需要長在你的代碼,它是中值濾波器?是索引嗎?

  3. 假設所有圖像大小相同的,你可以使用accumarray和固定不變的面具subs快速求和值:

    subs_g = zeros(h, w); %// allocate mask for green 
    subs_r = zeros(h, w); 
    subs_g(sub2ind([h w], round(p_g_y), round(p_g_x)) = 1:numel(p_g_x); %//index each region 
    subs_g = conv2(subs_g, ones(5), 'same'); 
    subs_r(sub2ind([h w], round(p_r_y), round(p_r_x)) = 1:numel(p_r_x); %//index each region 
    subs_r = conv2(subs_r, ones(5), 'same'); 
    sel_g = subs_g > 0; 
    sel_r = subs_r > 0; 
    subs_g = subs_g(sel_g); 
    subs_r = subs_r(sel_r); 
    

    一旦這些面具是固定的,你可以處理所有圖像

    %// pre-allocation goes here - I'll leave it to you 
    for s=1:NumberImages 
        im1=imread(fn(s,1).name);  
        im=double(im1-medfilt2(im1,[15,15])); 
        accumarray(subs_g, im(sel_g)); % summing all the green ROIs 
        accumarray(subs_r, im(sel_r)); % summing all the green ROIs 
    end 
    
每個圖像上操作
0

量化代碼 -

%// Pre-compute green and red indices to be used across all the images 
r1 = round(bsxfun(@plus,permute(p_g_y,[3 2 1]),[-2:2]')); 
c1 = round(bsxfun(@plus,permute(p_g_x,[3 2 1]),[-2:2])); 
green_ind = reshape(bsxfun(@plus,(c1-1)*size(im,1),r1),[],numel(p_g_x)); 

r2 = round(bsxfun(@plus,permute(p_r_y,[3 2 1]),[-2:2]')); 
c2 = round(bsxfun(@plus,permute(p_r_x,[3 2 1]),[-2:2])); 
red_ind = reshape(bsxfun(@plus,(c2-1)*size(im,1),r2),[],numel(p_g_x)); 

for s=1:NumberImages 
    im1=imread(fn(s,1).name); 
    im=double(im1-medfilt2(im1,[15,15])); 

    GreenROI=sum(im(green_ind)); 
    RedROI =sum(im(red_ind)); 
end 
+0

您可以預先計算循環外的「r」和「c」。 – Shai 2014-09-04 12:49:40

+0

@Shai很好的呼籲,謝謝! – Divakar 2014-09-04 13:10:05

相關問題