How to convert a grayscale image to binary in MATLAB - matlab

I have to write a program that converts intensity images into black-and-white ones. I just figured I could take a value from the original matrix, I, and if it's above the mean value, make the corresponding cell in another array equal to 1, otherwise equal to zero:
for x=1:X
for y=1:Y
if I(x,y)>mean(I(:))
bw(x,y)=1;
elseif I(x,y)<mean(I(:))
bw(x,y)=0;
end
end
end
image(bw)
Unfortunately, the image I get is all black. Why?
I is in uint8, btw. 2-D Lena.tiff image

Use this :
bw = im2bw(I, graythresh(I));
Here the documentation for im2bw;
using imshow(I,[]);, doesn't evaluate the image between 0 and 255, but between min(I(:)) and max(I(:))
EDIT
You can change graythresh(I) by anyother level. You can still use the mean of your image. (Normalize between 0 and 1).
maxI = max(I(:));
minI = min(I(:));
bw = im2bw(I,(maxI - mean(I(:)))/(maxI - minI));

Use imagesc(bw) (instead of image(bw)). That automatically scales the image range.
Also, note that you can replace all your code by this vectorized, more efficient version:
bw = double(I>mean(I(:)));

One problem is that you are always using the mean untill then.
What you will want to do is do this before the loop:
myMean = mean(I(:));
And then replace all following occurences of mean(I(:)) by myMean.
Using the running mean as you currently will definitely slow things, but it will not be the reason why it becomes all black.

Related

how to check if pixel value is increased from 255 in matlab while increasing the brightness of the image?

i am writing the code of matlab in which i just read the image and then i add + 50 on each pixel of the image it works fine and along with it i want to check the pixel value with if statment if pixel value exceed to 255 then this pixel value set to 255. but the if statment not working
here is my code
m1 = imread('owl.pgm');
m2 = imread('mecca06.pgm');
for i=1: size(m1,1)
for j=1: size(m1,2)
m1(i,j) = m1(i,j)+270;
if m1(i,j)>=255
m1(i,j)= 255;
end
end
end
figure
imshow(m1)
In MATLAB, integer addition is saturated. That means that, if m1 is uint8 (as it usually is returned from imread), then m1+50 will never be more than 255, if the sum would surpass that value, it would be set to 255 instead.
So, MATLAB automatically does what you wanted to accomplish, you don't need anything special for that.
The code in your post can be replaced by:
m1 = imread('owl.pgm');
m2 = imread('mecca06.pgm');
m1 = m1 + 270;
figure
imshow(m1)
You don't need to loop over all pixels, you can use the image as a matrix and simply do something like:
m1 = imread('owl.pgm');
m1 = min(255,m1+50);
Edit:
Depending on what datatype im1 has you may need to convert it first to something that can handle the operation you want to do, e.g. an 8-Bit integer allows only numbers upto 255. In that case you may have to convert to a 16-Bit Integer or just a floating point number. You can convert back afterwards:
m1 = imread('owl.pgm');
m1 = double(m1);
m1 = min(255,m1+50);
m1 = uint8(m1);

Convert and indexed image to RGB and back without losing data

I am having trouble converting an indexed image to RGB and then back from RGB to an indexed image. For some reason, the result is different from the original. I am doing steganography so it can't work if the data is changed.
This is my code and this is the sample image:
[J map]=imread('expert.gif');
Jrgb=ind2rgb(J,map);
Jind=rgb2ind(Jrgb,map);
isequal(J,Jind)
Variables J and Jind are supposed to be equal. Why are they being detected as being different?
First of all, I'm certain that this is related to this question.
The issue is happening because if you actually look at the colormap of your loaded image:
map =
0 0 0
0.6275 0.3216 0.1765
0.4902 0.4902 0.4902
0.8039 0.5216 0.2471
0.7451 0.7451 0.7451
0.8627 0.8627 0.8627
0.9020 0.9020 0.9804
0 0 0
You'll see that the color black (0,0,0) actually exists in there twice so both index = 0 and index = 7 will resolve to black in the RGB image.
When you do the conversion back to an indexed image, MATLAB is going to use the same index for both of those (because they are obviously the same color) even if the colormap that you pass to rgb2ind is the same colormap.
That explains why the differences that you're seeing are where the transparent pixels are (around the periphery).
As far as dealing with this, I think it's a little tricky. Unfortunately the transparency (3rd output) output of imread is an empty array.
You could potentially change the input colormap so that the first and last rows aren't the same (set the last row to 1's) and then you should get back something comparable.
map(end,:) = 1;
rgb = ind2rgb(J, map);
ind = rgb2ind(rgb, map);
isequal(J, ind);
In general, due to MATLAB's limitations, GIFs with transparency may not be the best test case for playing with stenography.

crop an image according to what is different between 2 images

I have different images and I would like to crop them and keep only what is different between both. Here is the code I have so far.
video = VideoReader('frames.avi', 'Tag', 'my reader object');
frameFirst = read(video,1);
frameSecond = read(video, video.NumberOfFrames-1 );
imshowpair (frameSecond,frameFirst);
pause();
Well, it's tough to give you a good answer without much more detail. I think I understand what you're trying to do, and this might get you moving in the right direction. This code iterates through each pixel of the image (each pixel contains a 1x3 vector of RGB data ranging from 0 to 1), by row and column. If the difference in any of the elements of the 1x3 RGB vector exceeds some threshold (in this case, set to 0.1), we make that whole pixel black (set it to [0 0 0]). Else, we lust make it whatever the last frame was. To filter out all but those pixels that are identical, set the thresh value to 0. It goes like this:
thresh = 0.1
for ii = 1:size(frameFirst, 1)
for jj = 1:size(frameFirst, 2)
pixDiff = frameFirst{ii, jj} - frameSecond{ii, jj}
if (pixDiff(1) > thresh || pixDiff(2) > thresh || pixDiff(3) > thresh)
outputFrame = frameSecond{ii, jj};
else
outputFrame = [0 0 0];
end
end
end
I hope this does what you're looking for. Good luck!
Edit 1: Ok, I understand what you are looking for now. You need to have the indices of the bottom-right and top-left. If you already have those, just do this: frameOut = frameIn(xStart:xStop, yStart, yStop. If you need to find those points, that's harder. Let me know and I'll help you work it out.

Matlab Bug -- Matrix Elements Keep Maxing Out

There's a peculiar bug in my code that I can't seem to figure out. For context, I is an image, a matrix, consisting of scaled values from 0 to 255. GetSpatAvg is a function that is not included here. The problem I'm facing is that the elements in ngtdm always max out at 255. When this function finishes, I get the matrix ngtdm back consisting of many many values that are 255. The code is below exactly as it shows on my computer.
function ngtdm = getNGTDM(I,d)
[rowI, colI] = size(I);
ngtdm = zeros(256, 1);
for r=1+d:rowI-d
for c=1+d:colI-d
term = I(r,c)-getSpatAvg(r,c);
ngtdm(I(r,c)+1)=ngtdm(I(r,c)+1)+term;
end
end
end
I isolated a specific value in I, 254, in the code below.
function ngtdm = getNGTDM(I,d)
[rowI, colI] = size(I);
ngtdm = zeros(256, 1);
for r=1+d:rowI-d
for c=1+d:colI-d
if(I(r,c)==254)
term = I(r,c)-getSpatAvg(r,c);
disp(term);
ngtdm(I(r,c)+1)=ngtdm(I(r,c)+1)+term;
end
end
end
end
The variable 'term', in this instance was always 222. There were 369 instances of 222. Therefore the value at ngtdm(255) (254+1=255) should be larger than 255, yet the element still maxed out at 255. When I replace term with 222 as shown below:
ngtdm(I(r,c)+1)=ngtdm(I(r,c)+1)+222;
I get the correct value, a number larger than 255.
I can't seem to figure out why my element is always maxing out at 255. Could it be something to do with the fact that the values of I are scaled between 0 and 255. I'm pretty positive that getSpatAvg is not the issue because the correct value is being returned.
Thank You
It's not a bug - it sounds like you are using a uint8 datatype. If you convert to a datatype with more bits - e.g. uint16, uint32, single, double, etc - you will not run into this problem. I guess you are working with images, as images read using imread are read in as uint8 by default to save memory. Quickest fix: use I=double(I); either at the start of your function, or on the variable I before you put it into the functions.

Colormatrix from colorvector

I have a scatter3 plot in which I use a vector C to define the colors of the different points. Here the color of the colormap is linearly mapped onto the numbers which are in C. I want to somehow find the RGB-values of each value inside my C vector. So I want a x by 3 matrix out of my C vector. Anybody knows if this is possible?
Best wishes,
Achim
Edit:
Thanks to #Aabaz I was able to solve the problem. Here is my solution:
colors_current = colormap;
color = [color zeros(length(color),2)];
stepw = floor(length(color)/length(colors_current));
colorsort = sortrows(color);
color_old = 0;
counter = 1;
for i = stepw:stepw:length(JAbs)
color_indices = find(color_old < color(:,1) & color(:,1) < color_sort(i));
if counter >= length(colors_current)
break;
end
for j=1:length(color_indices)
JAbs(color_indices(j),:) = colors_current(counter,:);
end
color_old = colorsort(i);
counter = counter + 1;
end
Not the most elegant way but it seems to work.
The function colormap used with no argument, returns the current axes colormap as an m by 3 matrix storing the RGB codes for each color. From there you can get to the RGB code for every element in your vector C.
UPDATE: I am sorry, I must have misread your question because I did not understand you were looking for an explicit way to get the rgb codes, just the connexion between the colormap and the rgb code. Anyway I see you found the solution yourself, well done. Did a quick try myself which I give you here :
n=10;
C=rand(n,1);
map=colormap(jet);
Cregspaced=(min(C):(max(C)-min(C))/(size(map,1)-1):max(C))';
Cmapindex=interp1(Cregspaced,(1:size(map,1))',C,'nearest');
Crgb=map(Cmapindex,:);
This should work, depending on how Matlab interpolates the index for the colormap. You can test it against your own solution to see if the results match.