Question

I'm working on image de-noising, trying to keep continuous lines (with some leniency) in my matrix and removing random non-zero elements which are not really connected to the lines I'm after. The problem I have is detailed below:

I have tried to write a sliding window function that will search through row r of my 2-D matrix and look for non-zero digits.
For each non-zero digit, the function should look for the presence of a non-zero element within the 2x2 neighbourhood (2 numbers either side of the non-zero element) of row r and of row r+1 (and r-1 if it exists).
If the neighbourhood is empty, that original element in row r should be zeroed, otherwise all non-zero elements within the window should be kept.
To complicate things, I am also trying to make the sliding window circular, so that when it reaches the end of the row, it doesn't get compressed, but rather includes numbers from the start of the row in the neighbourhood.

For all rows, I can also only keep a "connected" element, if it is in some way connected to row 1, so continuous lines down my matrix cannot start in row 2.

I've written this with for-loops in Matlab, and ran into problems when trying to manipulate values within the window. Aside from that, my function is really slow. Is there a way to do this in Matlab or Python without using for-loops, and without any pre-installed toolboxes?

Sample Matlab Code: "test" is a binary matrix (but not all matrices I'll look at will be binary). It contains 5 rows. This is dummy code I wrote for row 1. The window manipulation (line 4 of the code) doesn't work, but hopefully this will give you some idea of what I'm trying to do. This code also omits the edges of the matrix as I wasn't sure the best way to make this circular.

n=2 % size of neighborhood to look at
p=size(test,2) % length of row

for ii=1+n:p-n;
    if test(1,ii)==1;
        if sum(test(2,(ii-2:ii+2))+test(1,(ii-2:ii+2)))>=2;
           test(2,(ii-2:ii+2))=test(2,(ii-2:ii+2))*2;
        else;
           test(1,ii)=0;
        end;
    end;
end

var=test(2,:);
var(var==1)=0;
var(var>=2)=1;
test(2,:)=var;

Example matrix ("test"): (zeros replaced with '.' for better visualization)

. . . 1 . . 1 . . . . 1 1 1 . . . . . . . 
1 . . . 1 . 1 . . . 1 . . . . . . . . 1 .
. . . . . 1 1 1 . . . 1 . . . . . . 1 . .
. . 1 . . . . . 1 . . . . . . . . . . 1 .
. . . . . . . . . 1 . . . . . 1 . . . . .

Desired output: (zeros replaced with '.' for better visualization)

. . . 1 . . 1 . . . . 1 1 1 . . . . . . .
. . . . 1 . 1 . . . 1 . . . . . . . . . .
. . . . . 1 1 1 . . . 1 . . . . . . . . .
. . . . . . . . 1 . . . . . . . . . . . .
. . . . . . . . . 1 . . . . . . . . . . .
Was it helpful?

Solution

Here's an outline to do what I think you're trying to do:

Step 1:

Find all of the matrix positions that have non-zero elements in their 3x5 neighborhood by summing the values of the neighbors. We don't want to include the current element just yet, hence the zero in the middle. Input matrix is test.

fil = [1 1 1 1 1; 1 1 0 1 1; 1 1 1 1 1];
A = conv2(test, fil, 'same');

Step 2:

A now contains values > 1, so change them all to 1, leaving the zero values alone.

A(A > 0) = 1;

Step 3:

Now that you've identified all of elements with valid neighborhoods, combine test with A by element-wise multiplication leaving only those elements that are both non-zero in test and have non-zero neighbors.

result = test .* A;

Step 0:

Padding - The above should work as is, but pads both rows and columns with zeros. As I understand them, your padding requirements are that you want circular rows and the columns padded with zeros.

nCols = size(test, 2);
paddedTest = [zeros(1,nCols);...
              test(:, nCols-1:nCols), test, test(:,1:2);...
              zeros(1,nCols)];

This obviously changes the size of the matrix you're working on by doing your own padding, so you need to change the convolution parameters in order to return a matrix the same size as test.

A = conv2(paddedTest, fil, 'valid');

I don't have Matlab available right now to test this, but hopefully others will correct any egregious errors I've made.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top