How to create 2D Gray image from 3D colored image?

12 views (last 30 days)
I've been trying to create a 2D matrix using the Average of RGB values from each pixel in a 3D matrix.
for i = 1:m
for j = 1:n
gray(i,j) = double((A(i,j,1) + A(i,j,2) + A(i,j,3))/3);
%%gray(i,j) = round(gray(i,j)/255);
end
end
imshow(gray, []);
This only shows a red image with some greens in it. It is possible that it still is trying to print using RGB values maybe?
IF I uncomment this: "gray(i,j) = round(gray(i,j)/255);" , I get a black image.
All I need is a simple direction. What am I doing wrong? The image should be grayscale form the averages of RGB values.

Accepted Answer

Bjorn Gustavsson
Bjorn Gustavsson on 20 Apr 2020
When you add data of non-double type you'll run into all sorts of wrap-around problems. When I work with images I typically cast the data to double ASAP - that is instantly after reading the image-file:
A = imread('peppers.png');
A = double(A);
Then I don't have to worry about issues like overflow and wraparound.
subplot(2,2,1)
imagesc(A/max(A(:)))
disp([min(A(:)),max(A(:))])
subplot(2,2,2)
imagesc(A/max(A(:)))
Then a couple of unrelated advices:
When you have to loop, try to pre-allocate your variables, otherwise matlab will have to re-allocate space on every step, that becomes slow. If you cannot figure-out how big matrices you have but can run the loop in any direction you might run it from the largest indices and down towards 1:
for i = m:-1:1
for j = n:-1:1
gray(i,j) = (A(i,j,1) + A(i,j,2) + A(i,j,3))/3;
end
end
That way you'll allocate gray to its full size first time around the loops.
You very often do not need to loop. matlab is short for MATrix LABoratory after all. You can do something like this:
gray = (A(:,:,1)+A(:,:,2)+A(:,:,3))/3;
...or even better there are loads of functions doing what you need or 60-90 % of what you need. You could do:
gray = mean(A,3);
HTH
  4 Comments
Bjorn Gustavsson
Bjorn Gustavsson on 20 Apr 2020
Well, it's not for some reason - it is for the reason that your uint8 variable is limited to integer values between 0 and 255, and when matlab adds two uint8 variables and the sum saturates at 255. That's most likely what happens in your case. That's why it might be preferable to cast to double asap - unless you have some explicit reason to keep it in uint8-format.
Yup, it should, matlab removes trailing singleton dimensions - if you generate a variable that gets the size [n1 x n2 x n3 x 1] it will become an [n1 x n2 x n3] variable, but other singleton-dimensions will not be removed, that is [1 x n1 x n2 x n3] will have that size unless you explicitly squeeze it out.
You should also make it a habit to check the size and type of variables when you start, use whos and size...
HTH
Image Analyst
Image Analyst on 20 Apr 2020
Since gray() is a built-in function, you might use:
grayImage = (A(:,:,1) + A(:,:,2) + A(:,:,3)) / 3;
Where A was already made double of course.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!