Check the pixel values ​​in the neighborhood

I am trying to write a MATLAB script that does the following:

Data: pixel coordinates (x, y) for the image .jpg Purpose: to check, within a radius of 5 pixels from the given coordinates, if there is a pixel of a certain value.

For example, let's say I was given coordinates (100 100), then I want to check the neighborhoods (100,100) in my image for any pixels that are black (0,0,0). Possibly pixel (103, 100) and (104 100) could have value (0,0,0).

Current code :

x_coord = uint32(coord(:,1));  
y_coord = uint32(coord(:,2));
count = 0;

for i = 1:length(x_coord)
    %(img(x,y) returns pixel value at that (x,y)
    %Note 0 = black. Indicating that, at that position, the image is just 
    % black 
    if img(x_coord(i),y_coord(i)) == 0 
        count = count + 1;
    end
end

      

It currently only checks the exact location. Not in the local area. How can I renew this?

EDIT: Also notice that at least one pixel adjacent to the value, I am increasing the count. I am not trying to count how many pixels in a neighborhood have this value, just trying to find evidence of at least one pixel that matters.

EDIT:

Even though I cannot identify the error with the code, I cannot get the exact results I want. Here is the code I am using.

val = 0; %pixel value to check
N = 50; % neighbourhood radius

%2D grid of coordinates surrounding center coordinate
[R, C] = ndgrid(1 : size(img, 1), 1 : size(img, 2));

for kk = 1 : size(coord, 1)
    r = coord(kk, 1); c = coord(kk, 2); % Get pixel locations

    % mask of valid locations within the neighbourhood (avoid boundary problems)
    mask = (R - r).^2 + (C - c).^2 <= N*N;         

    pix = img(mask); % Get the valid pixels
    valid = any(pix(:) ~= val);
    % Add either 0 or 1 depending if we have found any matching pixels
    if(valid == 1)
        img = insertMarker(img, [r c], 'x', 'color', 'red', 'size', 10);
        imwrite(img, images(i).name,'tiff');
    end
    count = count + valid; 
end

      

+3


source to share


3 answers


An easier way to do this is to use indexing to capture a neighborhood, and then check if any of the pixels in the neighborhood have the value you are looking for, use any

the flattened version of that neighborhood. The trick with grabbing the right neighborhood is to first create a 2D coordinate grid that spans all the dimensions of your image, then just use the equation of a circle centered on each coordinate you are looking at and determine those locations that satisfy the following equation :

(x - a)^2 + (y - b)^2 <= N^2

      

N

is the observation window radius, (a, b)

is the coordinate of interest, and (x, y)

is the image coordinate. Use meshgrid

to create coordinates.



You would use the above equation to create a mask logical

, an index into your image to pull out the locations that are valid in the mask, and check how many pixels match the one you want. Another added benefit with the above approach is that you are not exposed to errors out of bounds. Since you are pre-listing all valid coordinates in your image, the mask generation constrains you within the image, so you don't need to check for out-of-bounds conditions ... even if you specify coordinates to find that are out of bounds.

In particular, if your image is stored in img

, you should do:

count = 0; % Remembers total count of pixels matching a value
val = 0; % Value to match
N = 50; % Radius of neighbourhood

% Generate 2D grid of coordinates
[x, y] = meshgrid(1 : size(img, 2), 1 : size(img, 1));

% For each coordinate to check...
for kk = 1 : size(coord, 1)
    a = coord(kk, 1); b = coord(kk, 2); % Get the pixel locations
    mask = (x - a).^2 + (y - b).^2 <= N*N; % Get a mask of valid locations
                                           % within the neighbourhood        
    pix = img(mask); % Get the valid pixels
    count = count + any(pix(:) == val); % Add either 0 or 1 depending if 
                                        % we have found any matching pixels
end

      

+4


source


Suggested solution:

fc = repmat(-5:5,11,1);
I = (fc.^2+fc'.^2)<=25;
fc_x = fc(I);
fc_y = fc'; fc_y = fc_y(I);

for i = 1:length(x_coord)
    x_toCheck = fc_x + x_coord(i);
    y_toCheck = fc_y + y_coord(i);
    I = x_toCheck>0 & x_toCheck<=yourImageWidth;
    I = I.*(y_toCheck>0 & y_toCheck<=yourImageHeight);
    x_toCheck = x_toCheck(logical(I));
    y_toCheck = y_toCheck(logical(I));

    count = sum(img(x_toCheck(:),y_toCheck(:)) == 0);
end

      


If your img function can only check one pixel at a time, just add for loop

:

for i = 1:length(x_coord)
    x_toCheck = fc_x + x_coord(i);
    y_toCheck = fc_y + y_coord(i);
    I = x_toCheck>0 & x_toCheck<=yourImageWidth;
    I = I.*(y_toCheck>0 & y_toCheck<=yourImageHeight);
    x_toCheck = x_toCheck(logical(I));
    y_toCheck = y_toCheck(logical(I));
    for j = 1:length(x_toCheck)
        count = count + (img(x_toCheck(j),y_toCheck(j)) == 0);
    end
end

      


Step by step:

First you need to get all coordinates within 5 pixels of the given coordinate.

Let's start by building a square 11 pixels long / wide.

fc = repmat(-5:5,11,1);
fc_x = fc;
fc_y = fc';
plot(fc_x,fc_y,'.');

      

enter image description here



Now we need to create a filter to get rid of these points outside the 5-pixel radius.

I = (fc.^2+fc'.^2)<=25;

      

Apply a filter so that we can get a circle with a 5 pixel radius.

fc_x = fc_x(I);
fc_y = fc_y(I);

      

enter image description here

Then translate the center of the circle to the given coordinate:

x_toCheck = fc_x + x_coord(i);
y_toCheck = fc_y + y_coord(i);

      

You need to check if part of the circle is outside the range of your image:

I = x_toCheck>0 & x_toCheck<=yourImageWidth;
I = I.*(y_toCheck>0 & y_toCheck<=yourImageHeight);
x_toCheck = x_toCheck(logical(I));
y_toCheck = y_toCheck(logical(I));

      

Finally, count the pixels:

count = sum(img(x_toCheck,y_toCheck) == 0);

      

+2


source


You can use the article below regarding your needs. -A new way to detect and count overlapping tracks in SSNTD using image processing techniques

https://doi.org/10.1016/j.radmeas.2016.04.009

-1


source







All Articles