cferrier1995
cferrier1995

Reputation: 83

Matlab: trouble with taking derivative of image?

So I need to take the derivative of an image in the x-direction for this assignment, with the goal of getting some form of gradient. My thought is to use the diff(command) on each row of the image and then apply a Gaussian filter. I haven't started the second part because the first is giving me trouble. In attempting to get the x-derivative I have:

origImage = imread('TightRope.png');

for h = 1:3 %%h represents color channel
    for i = size(origImage,1)
        newImage(i,:,h) = diff(origImage(i,:,h));  %%take derivative of row and translate to new row 
    end
end

The issue is somewhere along the way I get the error 'Subscripted assignment dimension mismatch.'.

Error in Untitled2 (line 14)
    newImage(i,:,h) = diff(origImage(i,:,h));

Does anyone have any ideas on why that might be happening and if my approach is correct for getting the gradient/gaussian derivative?

Upvotes: 2

Views: 934

Answers (3)

rayryeng
rayryeng

Reputation: 104474

Given a N element vector, diff returns a N-1 length vector, so the reason why you are getting an alignment mismatch is because you are trying to assign the output of diff into an incorrect number of slots. Concretely, supposing that N is the total number of columns, you are using diff on a 1 X N vector which thus returns a 1 x (N - 1) vector and you are trying to assign this output as a single row into the output image which is expected to be 1 x N. The missing element is causing the alignment mismatch. diff works by taking pairs of elements in the vector and subtracting them to produce new elements, thus the reason why there is one element missing in the final output.

If you want to get your code working, one way is to pad each row of the image or signal vector with an additional zero (for example) as input into diff. Something like this could work. Take note that I'll be converting your image to double to allow the derivative to take on negative values:

origImage = imread('...'); %// Place path to image here and read in
origImage = im2double(origImage); %// Change - Convert to double precision
newImage = zeros(size(origImage)); %// Change - Create blank new image and populate each row per channel manually

for h = 1:3 %%h represents color channel
    for ii = 1:size(origImage,1) %// Change - fixed for loop iteration
        newImage(ii,:,h) = diff([0 origImage(ii,:,h)]); %// Change
    end
end

Take note that your for loop was incorrect since it didn't go over every row... just the last row.

When I use the onion.png image that's part of the image processing toolbox:

enter image description here

...and when I run this code, I get this image using imshow(newImage,[]);:

enter image description here

Take note that the difference filter was applied to each channel individually and I changed the intensities per channel so that the smallest value gets mapped to 0 and the largest value gets mapped to 1. How you can interpret this image is that any areasthat have a non-black colour have some non-zero differences and hence there is some activity going on in those areas and any areas that have a dark / black colour means that there is no activity going on in those areas. Take note that we applied a horizontal filter, so if you wanted to do this vertically, you'd simply repeat the behaviour but apply this column-wise instead of row-wise as you did above.

Upvotes: 1

beaker
beaker

Reputation: 16791

If your goal is to use diff to generate the derivative rather than to create a loop, you can just tell diff to give you the derivative in the x-direction (along dimension 2):

newImage = diff(double(origImage), 1, 2);

The 1 is for the first derivative and 2 is for the derivative along the second dimension. See diff.

As @rayryeng mentions in his answer, it's important to cast the image as double.

Upvotes: 1

R.Falque
R.Falque

Reputation: 944

Why not use fspecial along with imfilter instead?

figure;

I = imread('cameraman.tif');

subplot 131; imshow(I); title('original')

h = fspecial('prewitt');
derivative = imfilter(I,h','replicate'); %'

subplot 132; imshow(derivative); title('derivative')

hsize = 5;
sigma = 1;

h = fspecial('gaussian', hsize, sigma) ;
gaussian = imfilter(derivative,h','replicate'); %'

subplot 133; imshow(gaussian); title('derivative + gaussian')

The result is the following one:

enter image description here

Upvotes: 2

Related Questions