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

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);

Related

Convolution Kernel using a user defined function. How to deal with negative pixel values?

I've declared a function that will be used to calculate the convolution of an image using an arbitrary 3x3 kernel. I also created a script that will prompt the user to select both an image as well as enter the convolution kernel of their choice. However, I do not know how to go about dealing with negative pixel values that will arise for various kernels. How would I implement a condition into my script that will deal with these negative values?
This is my function:
function y = convul(x,m,H,W)
y=zeros(H,W);
for i=2:(H-1)
for j=2:(W-1)
Z1=(x(i-1,j-1))*(m(1,1));
Z2=(x(i-1,j))*(m(1,2));
Z3=(x(i-1,j+1))*(m(1,3));
Z4=(x(i,j-1))*(m(2,1));
Z5=(x(i,j))*(m(2,2));
Z6=(x(i,j+1))*(m(2,3));
Z7=(x(i+1,j-1))*(m(3,1));
Z8=(x(i+1,j))*(m(3,2));
Z9=(x(i+1,j+1))*(m(3,3));
y(i,j)=Z1+Z2+Z3+Z4+Z5+Z6+Z7+Z8+Z9;
end
end
And this is the script that I've written that prompts the user to enter an image and select a kernel of their choice:
[file,path]=uigetfile('*.bmp');
x = imread(fullfile(path,file));
x_info=imfinfo(fullfile(path,file));
W=x_info.Width;
H=x_info.Height;
L=x_info.NumColormapEntries;
prompt='Enter a convulation kernel m: ';
m=input(prompt)/9;
y=convul(x,m,H,W);
imshow(y,[0,(L-1)]);
I've tried to use the absolute value of the convolution, as well as attempting to locate negatives in the output image, but nothing worked.
This is the original image:
This is the image I get when I use the kernel [-1 -1 -1;-1 9 -1; -1 -1 -1]:
I don't know what I'm doing wrong.
MATLAB is rather unique in how it handles operations between different data types. If x is uint8 (as it likely is in this case), and m is double (as it likely is in this case), then this operation:
Z1=(x(i-1,j-1))*(m(1,1));
returns a uint8 value, not a double. Arithmetic in MATLAB always takes the type of the non-double argument. (And you cannot do arithmetic between two different types unless one of them is double.)
MATLAB does integer arithmetic with saturation. That means that uint8(5) * -1 gives 0, not -5, because uint8 cannot represent a negative value.
So all your Z1..Z9 are uint8 values, negative results have been set to 0. Now you add all of these, again with saturation, leading to a value of at most 255. This value is assigned to the output (a double). So it looks like you are doing your computations correctly and outputting a double array, but you are still clamping your result in an odd way.
A Correct implementation would cast each of the values of x to double before multiplying by a potentially negative number. For example:
for i = 2:H-1
for j = 2:W-1
s = 0;
s = s + double(x(i-1,j-1))*m(1,1);
s = s + double(x(i-1,j))*m(1,2);
s = s + double(x(i-1,j+1))*m(1,3);
s = s + double(x(i,j-1))*m(2,1);
s = s + double(x(i,j))*m(2,2);
s = s + double(x(i,j+1))*m(2,3);
s = s + double(x(i+1,j-1))*m(3,1);
s = s + double(x(i+1,j))*m(3,2);
s = s + double(x(i+1,j+1))*m(3,3);
y(i,j) = s;
end
end
(Note that I removed your use of 9 different variables, I think this is cleaner, and I also removed a lot of your unnecessary brackets!)
A simpler implementation would be:
for i = 2:H-1
for j = 2:W-1
s = double(x(i-1:i+1,j-1:j+1)) .* m;
y(i,j) = sum(s(:));
end
end

calculating mean gray level

I have a lot of images in IM{}. I want to calculate mean graylevel of non-black pixels. When I run my code sum has 255 as a maximum value. I don't understand the reason. Why doesn't sum get higher values?
for i=1: length(IM)
[L,W,z]=size( IM{i});
k=1;
sum=0;
for L=1:L
for W=1: W
if IM{i}(L,W)~=0;
sum=IM{i}(L,W)+sum;
k=k+1;
end
end
end
Mean(i)=sum/k
end
That's probably because IM is of type uint8. This data type can't hold values larger than 255. Example:
>> uint8(200) + uint8(200)
ans =
255
To avoid this, you should convert IM to double:
IM = double(IM);
Anyway, your code could be reduced to a single line (including the conversion):
result = mean(double(IM(IM>0)));
With this approach, you could even dispense with double, because mean (actually sum, which is called by mean) converts to double automatically:
result = mean(IM(IM>0));

How to convert a grayscale image to binary in 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.

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.

bitxor operation in MATLAB

I am trying to understand why the original image is not coming with this code. The resulting image receive is yellowish in color, instead of being similar to the image Img_new.
Img=imread(‘lena_color.tif’);
Img_new=rgb2gray(img);
Send=zeroes(size(Img_new);
Receive= zeroes(size(Img_new);
Mask= rand(size(Img_new);
for i=1 :256
for j=1:256
Send(i,j)=xor( Img_new(i,j),mask(i,j));
End
End
image(send);
imshow(send);
for i=1 :256
for j=1:256
receive(i,j)=xor( send(i,j),mask(i,j));
End
End
image(receive);
imshow(receive);
What am I doing wrong?
There are several problems in your code.
MATLAB is case sensitive so end and End is not the same. Same goes for receive, and send.
MATLAB has a lot of matrix-based operations so please use for loops as a last resort since most of these operations can be executed by MATLAB's optimized routines for matrices.
MATLAB's xor returns the logical xor so when it sees two values (or matrices of values) it doesn't matter if it's 234 xor 123 or 12 xor 23 since it is equivalent to 1 xor 1 and 1 xor 1. You're looking for bitxor which does the bitwise xor on each element of the matrix and I've used it in my code below. This is the only way you can retrieve the information with the pixel == xor(xor(pixel,key),key) operation (assuming that's what you want to do).
rand returns a real value from 0 - 1 ; therefore, to do a successful bitwise xor, you need numbers from 0 - 255. Hence, in my code, you'll see that mask has random values from 0-255.
Note: I've used peppers.png since it's available in MATLAB. Replace it with lena_color.tif.
%%# Load and convert the image to gray
img = imread('peppers.png');
img_new = rgb2gray(img);
%%# Get the mask matrix
mask = uint8(rand(size(img_new))*256);
%%# Get the send and receive matrix
send = bitxor(img_new,mask);
receive = bitxor(send,mask);
%%# Check and display
figure;imshow(send,[0 255]);
figure;imshow(receive,[0 255]);
Update:
%%# Get mask and img somehow (imread, etc.)
img = double(img);
mask_rgb = double(repmat(mask,[1 1 3]));
bitxor(img,mask);
If instead, you choose to make everything uint8 instead of double, then I urge you to check if you are losing data anywhere. img is uint8 so there is no loss, but if any of the values of mask is greater than 255 then making it double will lead to a loss in data.