필터 지우기
필터 지우기

Introduction to MATLAB programming - image blur problem

조회 수: 5 (최근 30일)
ey21
ey21 2020년 4월 8일
댓글: Summer K.Rock 2022년 1월 24일
Hello all,
I am trying to work through one of the problems for the 'introduction to matlab programming' course by coursera, known as the 'image blur' problem (lesson 8 - final problems, week 9). The system keeps telling me that my values are incorrect, but I am struggling to understand why? I have attached my code below. I would be very grateful if anyone could give me a helping hand.
%The code to call the function:
img = imread('vandy.png')
output = blur(img,2) % I have specified the function 'blur' below
imshow(output);
% The function:
function[output] = blur(img,w)
here = 2*w + 1;
change = w;
%setting an epmpty matrix
emptymatrix = zeros(length(img(:,1)),length(img(1,:)));
%working out the output pixel value for each corner
added = img((1):(1+change),(1):(1+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(1,1) = answer;
i = length(img(:,1));
z = 1;
added = img((i-change):(i),(z):(z+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(i,z) = answer;
i = 1;
z = length(img(1,:));
added = img((i):(i+change),(z-change):(z));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(i,z) = answer;
i = length(img(:,1));
z = length(img(1,:));
added = img((i-change):(i),(z-change):(z));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(i,z) = answer;
output = uint8(emptymatrix);
% working out the pixel values for the inner square
for i = 1:length(img(:,1))
for z = 1:length(img(1,:))
if ((i + change) <= length(img(:,1))) && ((i-change) > 0) && ((z+change) <= length(img(1,:))) && ((z-change) > 0)
added = img((i-change):(i+change),(z-change):(z+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/(here*here);
answer = uint8(mean);
emptymatrix(i,z) = answer;
output = uint8(emptymatrix);
end
end
end
% working out the output pixel values for the outer rows and columns (excluding the corners)
for i = 2:(length(img(:,1))-1)
if (i-change) > 0 && (i+change) < length(img(:,1))
z = 1;
added = img((i-change):(i+change),(z):(z+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(i,z) = answer;
output = uint8(emptymatrix);
end
end
for i = 2:(length(img(:,1))-1)
if (i-change) > 0 && (i+change) < length(img(:,1))
z = length(img(1,:));
added = img((i-change):(i+change),(z-change):(z));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(i,z) = answer;
output = uint8(emptymatrix);
end
end
for i = 2:(length(img(1,:))-1)
if (i-change) > 0 && (i+change) < length(img(1,:))
z = 1;
added = img((z):(z+change),(i-change):(i+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(z,i) = answer;
output = uint8(emptymatrix);
end
end
for i = 2:(length(img(1,:))-1)
if (i-change) > 0 && (i+change) < length(img(1,:))
z = length(img(:,1));
added = img((z-change):(z),(i-change):(i+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(z,i) = answer;
output = uint8(emptymatrix);
end
end
end
  댓글 수: 5
ey21
ey21 2020년 4월 9일
편집: ey21 2020년 4월 9일
@Geoff Hayes
I have attached a screenshot below for what the code is supposed to be doing.
This code here is working out the averaged pixel value for each of the corners of the n-by-n matrix:
%working out the output pixel value for each corner
added = img((1):(1+change),(1):(1+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(1,1) = answer;
i = length(img(:,1));
z = 1;
added = img((i-change):(i),(z):(z+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(i,z) = answer;
i = 1;
z = length(img(1,:));
added = img((i):(i+change),(z-change):(z));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(i,z) = answer;
i = length(img(:,1));
z = length(img(1,:));
added = img((i-change):(i),(z-change):(z));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(i,z) = answer;
output = uint8(emptymatrix);
This code below works out the average pixel values for the indices (pixels) in the centre of the matrix. If the matrix is a 5-by-5 by matrix, the inner 3-by-3 square of pixel values would be calculated using the formula below:
% working out the pixel values for the inner square
for i = 1:length(img(:,1))
for z = 1:length(img(1,:))
if ((i + change) <= length(img(:,1))) && ((i-change) > 0) && ((z+change) <= length(img(1,:))) && ((z-change) > 0)
added = img((i-change):(i+change),(z-change):(z+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/(here*here);
answer = uint8(mean);
emptymatrix(i,z) = answer;
output = uint8(emptymatrix);
end
end
end
The code below is trying to work out the average value for each pixel on the outer edges of the matrix. For example, if the matrix is a 5-by-5 matrix, the code below would work out the average value for each pixel (indice) in the first and last column and row of the matrix, excluding the values of the four corners (as these have already been calculated above).
for i = 2:(length(img(:,1))-1)
if (i-change) > 0 && (i+change) < length(img(:,1))
z = 1;
added = img((i-change):(i+change),(z):(z+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(i,z) = answer;
output = uint8(emptymatrix);
end
end
for i = 2:(length(img(:,1))-1)
if (i-change) > 0 && (i+change) < length(img(:,1))
z = length(img(1,:));
added = img((i-change):(i+change),(z-change):(z));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(i,z) = answer;
output = uint8(emptymatrix);
end
end
for i = 2:(length(img(1,:))-1)
if (i-change) > 0 && (i+change) < length(img(1,:))
z = 1;
added = img((z):(z+change),(i-change):(i+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(z,i) = answer;
output = uint8(emptymatrix);
end
end
for i = 2:(length(img(1,:))-1)
if (i-change) > 0 && (i+change) < length(img(1,:))
z = length(img(:,1));
added = img((z-change):(z),(i-change):(i+change));
addition = sum(added);
additionally = sum(addition);
mean = additionally/numel(added);
answer = uint8(mean);
emptymatrix(z,i) = answer;
output = uint8(emptymatrix);
end
end
end
Image Analyst
Image Analyst 2020년 4월 9일
Can you use imfilter() or conv2()? It would be a lot shorter.

댓글을 달려면 로그인하십시오.

채택된 답변

Geoff Hayes
Geoff Hayes 2020년 4월 9일
편집: Geoff Hayes 2020년 4월 9일
ey21 - I think that you need to simplify your code. For the block that is concerned with the inner rows and columns, I've reduced it to
for i = 1:length(img(:,1))
for z = 1:length(img(1,:))
if ((i + w) <= length(img(:,1))) && ((i-w) > 0) && ((z+w) <= length(img(1,:))) && ((z-w) > 0)
submatrix = img((i-w):(i+w),(z-w):(z+w));
output(z,i) = uint8(sum(submatrix(:))/numel(submatrix));
end
end
end
There is only one sum since submatris(:) will return a column of all elements in the submatrix, and then we can just sum those elements. numel is used to return the number of elements in the submatrix so that we can do the appropriate average. I've eliminated the emptymatrix since it is redundant. (I've replaced the change with w since they are identical.)
You still have two other blocks of code, so can all of this be simplified further? I think so...so long as you choose the correct submatrix for each element in the input matrix. In fact, I think that you can do all of this work in one loop regardless as to the pixel if you choose the correct minimum and maximum row and column to create the submatrix from. The example in your assignment tells you what to do if your code is considering the pixel at (1,1) so you could use that information to determine what to do.Your code to get the submatrix of an inner pixel is
submatrix = img((i-w):(i+w),(z-w):(z+w));
because you know that i-w is valid, i+w is valid, z-w is valid, and z+w is valid. This could be made more general if you do
minValidRowIndex = max(1,i-w);
maxValidRowIndex = min(numRows,i+w);
minValidColIndex = max(1,z-w);
maxValidColIndex = min(numCols,z-w);
The above four variables can now be used to get your submatrix for any (I think) pixel. We use max and min to ensure that we never use row or column indices that are outside of the matrix.
  댓글 수: 2
ey21
ey21 2020년 4월 13일
@geoff hayes,
the code below seems to be more successful but not perfect yet...
function[output] = blur(img,w)
here = 2*w + 1;
change = w;
emptymatrix = zeros(length(img(:,1)),length(img(1,:)));
for z = 1:length(img(1,:))
for i = 1:length(img(:,1))
if (i + change) <= length(img(:,1)) && (i - change) >= 1 && (z + change) <= length(img(1,:)) && (z - change) >= 1
submatrix = img((i-change):(i+change),(z-change):(z+change));
emptymatrix(i,z) = uint8(sum(submatrix(:))/numel(submatrix));
output = uint8(emptymatrix);
elseif i == 1 && z == 1
submatrix = img((i):(i+change),(z):(z+change));
emptymatrix(i,z) = uint8(sum(submatrix(:))/numel(submatrix));
output = uint8(emptymatrix);
elseif i == length(img(:,1)) && z == length(img(1,:))
submatrix = img((i-change):(i),(z-change):(z));
emptymatrix(i,z) = uint8(sum(submatrix(:))/numel(submatrix));
output = uint8(emptymatrix);
elseif i == 1 && z == length(img(1,:))
submatrix = img((i):(i+change),(z-change):(z));
emptymatrix(i,z) = uint8(sum(submatrix(:))/numel(submatrix));
output = uint8(emptymatrix);
elseif i == length(img(:,1)) && z == 1
submatrix = img((i-change):(i),(z):(z+change));
emptymatrix(i,z) = uint8(sum(submatrix(:))/numel(submatrix));
output = uint8(emptymatrix);
elseif i == 1 && z-change >= 1 && z+change <= length(img(1,:))
submatrix = img((i):(i+change),(z-change):(z+change));
emptymatrix(i,z) = uint8(sum(submatrix(:))/numel(submatrix));
output = uint8(emptymatrix);
elseif i == length(img(:,1)) && z-change >= 1 && z+change <= length(img(1,:))
submatrix = img((i-change):(i),(z-change):(z+change));
emptymatrix(i,z) = uint8(sum(submatrix(:))/numel(submatrix));
output = uint8(emptymatrix);
elseif z == 1 && i-change >= 1 && i+change <= length(img(:,1))
submatrix = img((i-change):(i+change),(z):(z+change));
emptymatrix(i,z) = uint8(sum(submatrix(:))/numel(submatrix));
output = uint8(emptymatrix);
elseif z == length(img(1,:)) && i-change >= 1 && i+change <= length(img(:,1))
submatrix = img((i-change):(i+change),(z-change):(z));
emptymatrix(i,z) = uint8(sum(submatrix(:))/numel(submatrix));
output = uint8(emptymatrix);
end
end
end
end
Geoff Hayes
Geoff Hayes 2020년 4월 14일
Do you really need to consider all of those cases? I really don't think that you need any if/elseif statements and so could perhaps reduce the code to simply
for z = 1:length(img(1,:)) % iterating over columns
for i = 1:length(img(:,1)) % iterating over rows
minValidRowIndex = max(1,i-w);
maxValidRowIndex = min(numRows,i+w);
minValidColIndex = max(1,z-w);
maxValidColIndex = min(numCols,z-w);
submatrix = img(minValidRowIndex:maxValidRowIndex, minValidColIndex:maxValidColIndex);
output(z,i) = uint8(sum(submatrix(:))/numel(submatrix));
end
end

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Swapnil Yadav
Swapnil Yadav 2020년 6월 22일
function out = blur(img,w) % convert to double for doing calculations imgD = double(img); [row, col] = size(img); out = zeros(row, col); for ii = 1:row for jj = 1:col % Get the indices for a submatrix r1 = ii-w; r2 = ii+w; c1 = jj-w; c2 = jj+w; % Test that indices are valid % If not, set to min/max that is valid if r1 < 1 r1 = 1; end if r2 > row r2 = row; end if c1 < 1 c1 = 1; end if c2 > col c2 = col; end % Get the submatrix and assign the mean to the output pixel m = imgD(r1:r2, c1:c2); out(ii,jj) = mean(m(:)); end end % convert back to uint8 out = uint8(out); end
  댓글 수: 2
Aindrila Bose
Aindrila Bose 2020년 8월 23일
Thanks a lot. Code was easy to understand.
Summer K.Rock
Summer K.Rock 2022년 1월 24일
this answer is super easy and simple !! very good !!

댓글을 달려면 로그인하십시오.

Community Treasure Hunt

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

Start Hunting!

Translated by