2009-12-06 36 views
20

Tôi có một hình ảnh trong MATLAB:Làm thế nào tôi có thể tìm thấy cực đại cục bộ trong một hình ảnh trong MATLAB?

y = rgb2gray(imread('some_image_file.jpg')); 

và tôi muốn làm một số xử lý trên đó:

pic = some_processing(y); 

và tìm ra cực đại địa phương của đầu ra. Đó là, tất cả các điểm trong y lớn hơn tất cả các nước láng giềng của họ.

Tôi dường như không thể tìm thấy chức năng MATLAB để làm điều đó một cách độc đáo. Điều tốt nhất tôi có thể đưa ra là:

[dim_y,dim_x]=size(pic); 
enlarged_pic=[zeros(1,dim_x+2); 
       zeros(dim_y,1),pic,zeros(dim_y,1); 
       zeros(1,dim_x+2)]; 

% now build a 3D array 
% each plane will be the enlarged picture 
% moved up,down,left or right, 
% to all the diagonals, or not at all 

[en_dim_y,en_dim_x]=size(enlarged_pic); 

three_d(:,:,1)=enlarged_pic; 
three_d(:,:,2)=[enlarged_pic(2:end,:);zeros(1,en_dim_x)]; 
three_d(:,:,3)=[zeros(1,en_dim_x);enlarged_pic(1:end-1,:)]; 
three_d(:,:,4)=[zeros(en_dim_y,1),enlarged_pic(:,1:end-1)]; 
three_d(:,:,5)=[enlarged_pic(:,2:end),zeros(en_dim_y,1)]; 
three_d(:,:,6)=[pic,zeros(dim_y,2);zeros(2,en_dim_x)]; 
three_d(:,:,7)=[zeros(2,en_dim_x);pic,zeros(dim_y,2)]; 
three_d(:,:,8)=[zeros(dim_y,2),pic;zeros(2,en_dim_x)]; 
three_d(:,:,9)=[zeros(2,en_dim_x);zeros(dim_y,2),pic]; 

Và sau đó xem nếu tối đa dọc theo chiều thứ 3 xuất hiện trong lớp 1 (có nghĩa là: three_d(:,:,1)):

(max_val, max_i) = max(three_d, 3); 
result = find(max_i == 1); 

Có thêm thanh lịch cách để làm điều này? Điều này có vẻ như một chút của một kludge.

+0

câu hỏi liên quan: [Làm thế nào tôi có thể tìm thấy nhiều maxima địa phương trong một hình ảnh ồn ào?] (http://stackoverflow.com/questions/2706528/finding-many-local-max-in-an-image-using-matlab) –

Trả lời

37
bw = pic > imdilate(pic, [1 1 1; 1 0 1; 1 1 1]); 
+0

yep, điều này thậm chí còn nhanh hơn :) – Amro

+0

+1 Tôi đã quên cách IMDILATE sẽ làm việc với hình ảnh thang độ xám (tôi thường chỉ sử dụng nó với mặt nạ hợp lý). – gnovice

+0

Bạn có thể giải thích cách hoạt động của nó không? –

18

Nếu bạn có Image Processing Toolbox, bạn có thể sử dụng chức năng IMREGIONALMAX:

BW = imregionalmax(y); 

Biến BW sẽ là một ma trận logic kích thước giống như y với những người chỉ ra cực đại địa phương và zero khác.

LƯU Ý: Như bạn chỉ ra, IMREGIONALMAX sẽ tìm maxima mà là lớn hơn hoặc bằng hàng xóm của họ. Nếu bạn muốn loại trừ maxima lân cận có cùng giá trị (nghĩa là tìm tối đa là các pixel đơn), bạn có thể sử dụng hàm BWCONNCOMP. Sau đây nên loại bỏ điểm trong BW rằng có bất kỳ nước láng giềng, chỉ để lại pixel duy nhất:

CC = bwconncomp(BW); 
for i = 1:CC.NumObjects, 
    index = CC.PixelIdxList{i}; 
    if (numel(index) > 1), 
    BW(index) = false; 
    end 
end 
+0

Cảm ơn! Tôi thấy rằng imregionalmax tìm maxima lớn hơn hoặc bằng với hàng xóm của chúng. Bạn có biết làm thế nào tôi có thể tìm thấy những người lớn hơn và không bằng với hàng xóm của họ? –

+0

@Nathan: Vì vậy, nếu bạn tìm một tập hợp các cực đại lân cận bằng nhau, bạn có muốn chỉ chọn một trong số chúng, hoặc loại trừ tất cả chúng? – gnovice

+1

Tôi muốn loại trừ chúng. –

11

Ngoài ra, bạn có thể sử dụng nlfilter và cung cấp chức năng của riêng bạn để được áp dụng cho từng khu phố.

Chức năng "find strict max" chỉ đơn giản là kiểm tra xem trung tâm của khu phố có lớn hơn tất cả các yếu tố khác trong khu phố đó, luôn là 3x3 cho mục đích này hay không. Do đó:

I = imread('tire.tif'); 
BW = nlfilter(I, [3 3], @(x) all(x(5) > x([1:4 6:9]))); 
imshow(BW) 
+0

Cảm ơn bạn đời .. :) – G453

2

hay, chỉ cần sử dụng tuyệt vời: extrema2.m

2

Ngoài imdilate, mà là ở Image Processing Toolbox, bạn cũng có thể sử dụng ordfilt2.

ordfilt2 sắp xếp các giá trị trong vùng lân cận địa phương và chọn giá trị thứ n. (The MathWorks example chứng minh làm thế nào để thực hiện một bộ lọc max.) Bạn cũng có thể thực hiện một công cụ tìm 3x3 đỉnh với ordfilt2 với logic sau:

  1. Xác định một miền 3x3 rằng không bao gồm các điểm ảnh trung tâm (8 pixel) .

    >> mask = ones(3); mask(5) = 0 % 3x3 max 
    mask = 
        1  1  1 
        1  0  1 
        1  1  1 
    
  2. Chọn giá trị lớn nhất (8) với ordfilt2.

    >> B = ordfilt2(A,8,mask) 
    B = 
        3  3  3  3  3  4  4  4 
        3  5  5  5  4  4  4  4 
        3  5  3  5  4  4  4  4 
        3  5  5  5  4  6  6  6 
        3  3  3  3  4  6  4  6 
        1  1  1  1  4  6  6  6 
    
  3. Hãy so sánh sản lượng này với giá trị trung tâm của mỗi khu vực (chỉ A):

    >> peaks = A > B 
    peaks = 
        0  0  0  0  0  0  0  0 
        0  0  0  0  0  0  0  0 
        0  0  1  0  0  0  0  0 
        0  0  0  0  0  0  0  0 
        0  0  0  0  0  0  1  0 
        0  0  0  0  0  0  0  0 
    
+1

Đây là giải pháp chính xác nhất ở đây. Nó là nguyên bản trong Matlab và mất rất nhiều thời gian để tính toán hơn nfilter nào. – iamseiko

+0

@ Franzd'Anconia Nhưng tôi đã trả lời 5 năm muộn, vì vậy ở đây nó là ở phía dưới. :) – chappjc

+0

Câu trả lời hay. Có thể bao gồm ma trận gốc 'A' không? Dường như nó bị thiếu trong chuỗi xử lý của bạn. Tôi có thể dễ dàng đảo ngược kỹ sư nó nhưng nó sẽ là tốt đẹp để bao gồm những gì nó đã cho tự ngăn chặn :). Cảm ơn! – rayryeng

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