Reputation: 130
I'm trying to get into the field of computer vision, and to start I implemented a Sobel filter in MATLAB, which I read about here: http://en.wikipedia.org/wiki/Sobel_operator
Here is the code:
image = double(image);
kernelx = [ -1, 0, 1;
-2, 0, 2;
-1, 0, 1];
kernely = [ 1, 2, 1;
0, 0, 0;
-1, 0, 1];
height = size(image,1);
width = size(image,2);
channel = size(image,3);
for i = 2:height - 1
for j = 2:width - 1
for k = 1:channel
magx = 0;
magy = 0;
for a = 1:3
for b = 1:3
magx = magx + (kernelx(a, b) * image(i + a - 2, j + b - 2, k));
magy = magy + (kernely(a, b) * image(i + a - 2, j + b - 2, k));
end;
end;
edges(i,j,k) = sqrt(magx^2 + magy^2);
end;
end;
end;
Here is an image I tested it on:
This is the result:
I don't know where to go from here, I've tried looking at line thinning or thresholding, what steps should I take to make this run better?
Upvotes: 1
Views: 2318
Reputation: 16238
As Bharat Singh pointed out, your y-Kernel looks wrong. (Later analysis shows that it changes the results but that isn't the main problem.) If you want you can use your original kernel in my code below to see what the result is. (For posterity: kernely(3,:) = [-1, 0, 1];
) Basically, it looks like the input image.
Before you do anything else, just use the convolution function that is provided by Matlab.
Also, to speed things up, use conv2
. While you are experimenting, you might want to use parfor
instead of the outer for
-loop. The convolution is instantaneous on my machine and the parfor
version takes minutes.
imshow
is causing problemsThere is an alternative named imagesc
, that scales the image automatically. Or you can call imshow(image, [])
. But the problem in this case is that each channel looks right but the automated mixing of the channels by Matlab doesn't work. (Remember they are not RGB anymore but more like magnitude of the R-channel derivative |dR| etc. )
Check this by looking at each resulting channel individually (imshow(E(:,:,1), [])
) or as a euclidean average (see my code). If you run imshow(E, [])
you get the blown out highlights. The same happens if you pass it through rgb2gray
first.
image = imread('cat.jpg');
image = double(image);
kernelx = [ -1, 0, 1;
-2, 0, 2;
-1, 0, 1];
kernely = [ 1, 2, 1;
0, 0, 0;
-1, -2, -1];
height = size(image,1);
width = size(image,2);
channel = size(image,3);
edges = zeros(height, width, channel);
if exist('chooseSlow', 'var')
parfor i = 2:height - 1
for j = 2:width - 1
for k = 1:channel
magx = 0;
magy = 0;
for a = 1:3
for b = 1:3
magx = magx + (kernelx(a, b) * image(i + a - 2, j + b - 2, k));
magy = magy + (kernely(a, b) * image(i + a - 2, j + b - 2, k));
end;
end;
edges(i,j,k) = sqrt(magx^2 + magy^2);
end;
end;
end;
end
%% Convolution approach
E = zeros(height, width, channel);
for k=1:channel
Magx = conv2(image(:,:,k), kernelx, 'same');
Magy = conv2(image(:,:,k), kernely, 'same');
E(:,:,k) = sqrt(Magx .^2 + Magy .^2);
end
imshow(sqrt(E(:,:,1).^2 + E(:,:,2).^2 + E(:, :, 3) .^2 ), []);
print('result.png', '-dpng');
Upvotes: 2
Reputation: 2189
Your kernel in the y direction seems to be incorrect, it should be
[ 1, 2, 1; 0, 0, 0; -1, -2, -1];
Further, if you want to improve edge detection, you can look into Hysteresis, its an easy way to complete some obvious contours in an image which might be missed out
Upvotes: 2