Edge detection using Convolution

I am trying to detect the edges in an image using convolution. Tried this but get error " final_lena does not look like it has the correct dimensions."
smooth_image = conv2(single(lena), F, 'same');
vert_ = conv2(single(smooth_image), gx, 'same');
hor_ = conv2(single(smooth_image), gy, 'same');
final_lena = sqrt(vert_.^2 + hor_.^2);

Réponses (2)

DGM
DGM le 20 Avr 2022
Modifié(e) : DGM le 20 Avr 2022
What exactly is throwing that error? That's not an error from conv2(). Is this a part of something that's being auto-graded?
I don't know what sort of filters you chose or which variation of the lena image you're working with. It may simply be that the grader presumes a different source image geometry or something. The one I'm using is 512x512 RGB.
How you choose to reduce the RGB image to grayscale will change the resultant pixel values, so if the grader expects you to convert to a particular brightness measure, you'd need to use that. The rgb2gray() uses BT601 luma (Y). Otherwise, see:
Similarly, if the grader expects you to use a particular filter kernel(s), then your result values will differ if you don't. Since it's left up to me, I'm just going to use a prenormalized Scharr filter so that the gradient magnitude stays within the unit interval. You can use a regular Sobel or whatever you want, but bear in mind that your resulting gradient magnitude image will be on the interval [0 4.5] instead of [0 1]. There may be some expectation that you clamp or rescale the result.
Lastly, use im2single() instead of single(). Many tools (e.g. imshow(), imwrite()) presume a nominal data range based on the class of the array. For floating point images, the nominal data range is [0 1]. When you do single() on a uint8 array, it only casts the data, but its data range is still [0 255], and so it'll be interpreted as being out of range (whiter than white). Using im2double(), im2single(), im2uint8(), etc handles both casting and rescaling.
% note that i had to spoof the file extension to upload a TIFF
% you shouldn't have to do that on desktop
lena = imread('lena.tif.txt'); % RGB
lena = rgb2gray(lena); % convert to BT601 luma
% prenormalized scharr filter
% this is prenormalized for 2-pass gradient estimation
a = 0.155140;
b = 0.534738;
fk = [a b a; 0 0 0; -a -b -a];
% 3x3 gaussian
a = 0.003744;
b = 0.970049;
fkg = [a a a; a b a; a a a];
% use im2double()/im2single() instead of double()/single()
smooth_image = conv2(im2single(lena), fkg, 'same');
% smooth_image is already class 'single'
vert_ = conv2(smooth_image, fk.', 'same'); % d/dx
hor_ = conv2(smooth_image, fk, 'same'); % d/dy
final_lena = sqrt(vert_.^2 + hor_.^2); % gradient magnitude
imshow(final_lena)
There's also the possibility that the grader doesn't expect you to use the 'same' flags with conv2(), though that seems kind of odd that you wouldn't.

2 commentaires

Compiles OK but get same error. The following are the given conditions given by the grader:
% read image and convert it to a double
lena=imread('https://courses.edx.org/c4x/ETHx/AMRx/asset/lena.jpg');
lena = double(lena);
% ---- Filters ----------------------
% filter to detect horizontal edges
gx = [1;0;-1]./sqrt(2);
% filter to detect vertical edges
gy = [1 0 -1]./sqrt(2);
% smoothing filter
F = [1 4 6 4 1; 4 16 24 16 4; 6 24 36 24 6; 4 16 24 16 4; 1 4 6 4 1];
F = F./norm(F);
DGM
DGM le 20 Avr 2022
Modifié(e) : DGM le 20 Avr 2022
I don't know what to say. I almost wonder if the error message is being incorrectly given (i.e. that the actual error has nothing to do with the dimensions). The image is already grayscale, so it's not a question of gray conversion. You have filter kernels specified. It only makes sense that you'd use the 'same' flag with conv2(), and certainly the result is the same size. You need to make sure the output is rescaled correct for its class before you display or save it, but other than that, I don't know what it's complaining about.
You might want to ask your TA or whoever is administering this for some sort of clarification, because otherwise I think we'd both be guessing from this point forward.
% read image and convert it to a double
lena = imread('https://courses.edx.org/c4x/ETHx/AMRx/asset/lena.jpg');
% you can cast without rescaling, but be careful what you do
% while the image is in this improperly-scaled state
lena = double(lena);
% ---- Filters ----------------------
% filter to detect horizontal edges
gx = [1;0;-1]./sqrt(2);
% filter to detect vertical edges
gy = [1 0 -1]./sqrt(2);
% smoothing filter
F = [1 4 6 4 1; 4 16 24 16 4; 6 24 36 24 6; 4 16 24 16 4; 1 4 6 4 1];
F = F./norm(F);
smooth_image = conv2(lena, F, 'same');
vert_ = conv2(smooth_image, gx, 'same');
hor_ = conv2(smooth_image, gy, 'same');
final_lena = sqrt(vert_.^2 + hor_.^2);
final_lena = uint8(final_lena);
imshow(final_lena)

Connectez-vous pour commenter.

Image Analyst
Image Analyst le 20 Avr 2022
Try this. There are no errors.
%============================================================================================================================================
% Initialization Steps.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 15;
markerSize = 40;
% read image and convert it to a double
rgbImage = imread('lenaColor.png');
subplot(3, 3, 1);
imshow(rgbImage, 'Border', 'tight')
impixelinfo;
axis('on', 'image');
title('Original Image', 'fontSize', fontSize, 'Interpreter','none');
[rows, columns, numberOfColorChannels] = size(rgbImage);
% Get the gray scale image.
if numberOfColorChannels == 3
grayImage = rgb2gray(rgbImage);
else
grayImage = rgbImage;
end
grayImage = double(grayImage);
subplot(3, 3, 2);
imshow(grayImage, [], 'Border', 'tight')
impixelinfo;
axis('on', 'image');
title('Gray Scale Image', 'fontSize', fontSize, 'Interpreter','none');
% ---- Filters ----------------------
% filter to detect horizontal edges
gx = [1;0;-1]./sqrt(2);
% filter to detect vertical edges
gy = [1 0 -1]./sqrt(2);
% smoothing filter
F = [1 4 6 4 1; 4 16 24 16 4; 6 24 36 24 6; 4 16 24 16 4; 1 4 6 4 1];
F = F./norm(F)
subplot(3, 3, 3);
imshow(F, [], 'Border', 'tight')
impixelinfo;
axis('on', 'image');
title('Smoothing Filter Image', 'fontSize', fontSize, 'Interpreter','none');
% Convolve with filter F to blur the image.
smooth_image = conv2(single(grayImage), F, 'same');
subplot(3, 3, 4);
imshow(smooth_image, [], 'Border', 'tight')
impixelinfo;
axis('on', 'image');
title('Blurred smooth_image Image', 'fontSize', fontSize, 'Interpreter','none');
verticalEdgeImage = conv2(single(smooth_image), gx, 'same');
subplot(3, 3, 5);
imshow(verticalEdgeImage, [], 'Border', 'tight')
impixelinfo;
axis('on', 'image');
title('verticalEdgeImage', 'fontSize', fontSize, 'Interpreter','none');
horizontalEdgeImage = conv2(single(smooth_image), gy, 'same');
subplot(3, 3, 6);
imshow(horizontalEdgeImage, [], 'Border', 'tight')
impixelinfo;
axis('on', 'image');
title('horizontalEdgeImage', 'fontSize', fontSize, 'Interpreter','none');
% Magnitude of images, like you could get directly from imgradient().
final_lena = sqrt(verticalEdgeImage.^2 + horizontalEdgeImage.^2);
subplot(3, 3, 7);
imshow(final_lena, [], 'Border', 'tight')
impixelinfo;
axis('on', 'image');
title('final_lena Image', 'fontSize', fontSize, 'Interpreter','none');
g = gcf;
g.WindowState = 'maximized';

19 commentaires

Ken
Ken le 20 Avr 2022
Got error:
Error using imread>get_full_filename
File "lenaColor.png " does not exist.
Error in imread (line 371)
fullname = get_full_filename(filename);
Error in solution (line 2)
rgbImage = imread('lenaColor.png ');
Image Analyst
Image Analyst le 20 Avr 2022
Well you either have to use the one I attached (and you forgot to download) or you have to change the name to the filename of yours.
Ken
Ken le 21 Avr 2022
This is a comment I received on the code I originally posted. Cannot understand what it means.
"You are not following the correct way to compute filter values which are to be applied on the image. Just go through the output which is required (appears once you submit your answer) and you'll know what you are doing wrong."
Image Analyst
Image Analyst le 21 Avr 2022
I don't know who or what generated that comment. Perhaps a TA is telling you that you're not supposed to use the built in conv2 function or something.
Or it could be that the filter F is supposed to be the Sobel filter kernel which will do an edge detection instead of the filter you used which is used to slightly blur the image, not enhance/find edges in it.
Here is the original problem statement:
The task in this problem is to detect the edges in this image of Lena:
Some code and some filters to apply to this image are already given to you below. Using the 'conv2' MATLAB built-in function for 2D convolution, add all missing expressions to arrive at the edge image of lena (detecting edged in both the horizontal and the vertical direction). Quoting the description in the MATLAB documentation:'C = conv2(A,B) computes the two-dimensional convolution of matrices A and B'.
Read through the code below and using 'conv2' write out all expressions that will lead to the generation of 'final_lena'.
% read image and convert it to a double
lena=imread('https://courses.edx.org/c4x/ETHx/AMRx/asset/lena.jpg');
lena = double(lena);
% ---- Filters ----------------------
% filter to detect horizontal edges
gx = [1;0;-1]./sqrt(2);
% filter to detect vertical edges
gy = [1 0 -1]./sqrt(2);
% smoothing filter
F = [1 4 6 4 1; 4 16 24 16 4; 6 24 36 24 6; 4 16 24 16 4; 1 4 6 4 1];
F = F./norm(F);
% use 'conv2' and the filters given above to detect the edges in lena
final_lena =
plotFilteredLenaQuiz(lena, gx, gy, F);
Image Analyst
Image Analyst le 21 Avr 2022
OK, that's what I thought. You don't even need the F matrix or the convolution using it. You computed it wrong anyway.
DGM
DGM le 21 Avr 2022
The way I read it, the problem statement is specifying to use to use those filter kernels. F doesn't make sense to me either, but why would it be given that way unless the purpose is to mislead the student?
Image Analyst
Image Analyst le 21 Avr 2022
Oh, maybe. I thought the code was code @Ken wrote, not code that was part of the problem. If it's part of the problem, then so be it, but that F kernel is a blurring kernel, not an edge finding kernel.
Or maybe they want you to use the 'full' convolution option instead of 'same'. Perhaps that will get the message to go away. Was the message something somebody, like your professor manually wrote? Or was it automatically generated by some grading program when you submitted your code?
Ken
Ken le 21 Avr 2022
The msg from the grader is: " final_lena does not look like it has the correct dimensions."
Ken
Ken le 21 Avr 2022
Tried with 'full' instead of 'same'. Got error 'Arrays have incompatible sizes for this operation'.
Oh, I forgot your derivative filters aren't 3x3. You could make them symmetric and it would run, but I still have no idea if that's right. I have to wonder about the normalization of the filters. F isn't sum-normalized, and expanding gx,gy to make them symmetric will increase the range of the gradient estimate unless they're scaled accordingly.
% read image and convert it to a double
lena = imread('https://courses.edx.org/c4x/ETHx/AMRx/asset/lena.jpg');
% you can cast without rescaling, but be careful what you do
% while the image is in this improperly-scaled state
lena = double(lena);
% ---- Filters ----------------------
% filter to detect horizontal edges
gx = [1;0;-1]./sqrt(2);
% filter to detect vertical edges
gy = [1 0 -1]./sqrt(2);
% smoothing filter
F = [1 4 6 4 1; 4 16 24 16 4; 6 24 36 24 6; 4 16 24 16 4; 1 4 6 4 1];
F = F./norm(F);
smooth_image = conv2(lena, F, 'full');
vert_ = conv2(smooth_image, [gx gx gx], 'full');
hor_ = conv2(smooth_image, [gy;gy;gy], 'full');
final_lena = sqrt(vert_.^2 + hor_.^2);
final_lena = uint8(final_lena);
imshow(final_lena)
I figured the blur was just an attempt to suppress noise.
Ken
Ken le 22 Avr 2022
Tried this - compiled OK but grader says wrong
Image Analyst
Image Analyst le 22 Avr 2022
Who is this mysterious "grader" ? A real live person or an automated computer grader? Like I said, I ran the code (my code) and it ran fine with no error whatsoever.
Ken
Ken le 22 Avr 2022
Modifié(e) : Ken le 22 Avr 2022
Yes, I also am getting my doubts about the grader. This is the link to the quiz:
Ken
Ken le 26 Avr 2022
Comment received from the lectureer:
"Your solution looks fine, but to get the solution requested by the automatic grader you need to have a slightly different approach: Try to first convolve the two filters gx,gy to a single filter, then convolve this result with the filter F to get the final filter, that you can apply to the original image. (Note that you don't need to use the 'same' option)"
Based on the above comment I tried below but got into an endless loop!
F = conv2(lena, F);
vert_ = conv2(F, [gx gx gx]);
hor_ = conv2(F, [gy;gy;gy]);
comb=conv2(vert_,hor_);
F = conv2(comb,F);
F = uint8(F);
DGM
DGM le 27 Avr 2022
Modifié(e) : DGM le 27 Avr 2022
That still sounds like so much baloney. Even if you did exactly what they're telling you to do, your output image would still be 518x518, which is the same size as it would have been before if you simply omitted the 'same' flags, which (if I recall) has already been tried without success. If you replicate the derivative filters so that they're square, the output would be 520x520, but there's no suggestion that that was ever intended (well it was never suggested that the filters be combined either)...
I guess you could convolve them together? I don't really know whether you're still trying to calculate gradient magnitude or what you're supposed to do with this combined filter. For sake of demonstration, consider the results with an image full of circular edges. Note the behavior
lena = imread('circlesBrightDark.png');
lena = double(lena);
% ---- Filters ----------------------
% filter to detect horizontal edges
gx = [1;0;-1]./sqrt(2);
% filter to detect vertical edges
gy = [1 0 -1]./sqrt(2);
% smoothing filter
F = [1 4 6 4 1; 4 16 24 16 4; 6 24 36 24 6; 4 16 24 16 4; 1 4 6 4 1];
F = F./norm(F);
% 518x518 using old way without 'same'
%fk = conv2(gx, gy); % makes result 518x518
fk = conv2([gx gx gx], [gy; gy; gy]); % makes result 520x520
fk = conv2(fk, F);
% single pass?
final_lena = conv2(lena, fk);
final_lena = uint8(final_lena);
imshow(final_lena)
% grad magnitude estimate?
pass = conv2(lena, fk);
final_lena2 = sqrt(pass.^2 + pass.^2);
final_lena2 = uint8(final_lena2);
imshow(final_lena2)
% compare the symmetry to prior methods
smooth_image = conv2(lena, F);
vert_ = conv2(smooth_image, [gx gx gx]);
hor_ = conv2(smooth_image, [gy;gy;gy]);
final_lena0 = sqrt(vert_.^2 + hor_.^2);
final_lena0 = uint8(final_lena0);
imshow(final_lena0)
Note that the first two attempts have grossly asymmetric response. They both have suppressed response to vertical and horizontal edges. I don't know how that combined filter is supposed to be applied, so I'm just guessing here. It's sort of a half-scale Kayyali filter combined with a gaussian. I don't know what that's even for, so maybe I'm using it wrong.
Ken
Ken le 27 Avr 2022
Thanks. Still stuck! Funny that someone has already solved this without any issue (as per prior comment).
DGM
DGM le 27 Avr 2022
Modifié(e) : DGM le 27 Avr 2022
Hah. I guess accidents do happen.
Is there any other sort of contextual information that came with this dumb assignment? Any rumors among classmates? Maybe a clue about the intended size... or whether the size is actually the problem or not?
Maybe Image Analyst might have ideas as to how to appropriately apply a combined filter of that sort.

Connectez-vous pour commenter.

Question posée :

Ken
le 19 Avr 2022

Modifié(e) :

DGM
le 27 Avr 2022

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by