bitxor operation in MATLAB - 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.

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

Quantizing Double Type Input to Double Type Output in MATLAB

I'm trying to quantize a set of double type samples with 128 level uniform quantizer and I want my output to be double type aswell. When I try to use "quantize" matlab gives an error: Inputs of class 'double' are not supported. I tried "uencode" as well but its answer was nonsense. I'm quite new to matlab and I've been working on this for hours. Any help appriciated. Thanks
uencode is supposed to give integer results. Thats the point of it. but the key point is that it assumes a symmetric range. going from -x to +x where x is the largest or smallest value in your data set. So if your data is from 0-10 your result looks like nonsense because it quantizes the values on the range -10 to 10.
In any event, you actually want the encoded value and the quantized value. I wrote a simple function to do this. It even has little help instructions (really just type "help ValueQuantizer"). I also made it very flexible so it should work with any data size (assuming you have enough memory) it can be a vector, 2d array, 3d, 4d....etc
here is an example to see how it works. Our number is a Uniform distribution from -0.5 to 3.5 this shows that unlike uencode, my function works with nonsymmetric data, and that it works with negative values
a = 4*rand(2,4,2) - .5
[encoded_vals, quant_values] = ValueQuantizer(a, 3)
produces
a(:,:,1) =
0.6041 2.1204 -0.0240 3.3390
2.2188 0.1504 1.4935 0.8615
a(:,:,2) =
1.8411 2.5051 1.5238 3.0636
0.3952 0.5204 2.2963 3.3372
encoded_vals(:,:,1) =
1 4 0 7
5 0 3 2
encoded_vals(:,:,2) =
4 5 3 6
1 1 5 7
quant_values(:,:,1) =
0.4564 1.8977 -0.0240 3.3390
2.3781 -0.0240 1.4173 0.9368
quant_values(:,:,2) =
1.8977 2.3781 1.4173 2.8585
0.4564 0.4564 2.3781 3.3390
so you can see it returns the encoded values as integers (just like uencode but without the weird symmetric assumption). Unlike uencode, this just returns everything as doubles rather than converting to uint8/16/32. The important part is it also returns the quantized values, which is what you wanted
here is the function
function [encoded_vals, quant_values] = ValueQuantizer(U, N)
% ValueQuantizer uniformly quantizes and encodes the input into N-bits
% it then returns the unsigned integer encoded values and the actual
% quantized values
%
% encoded_vals = ValueQuantizer(U,N) uniformly quantizes and encodes data
% in U. The output range is integer values in the range [0 2^N-1]
%
% [encoded_vals, quant_values] = ValueQuantizer(U, N) uniformly quantizes
% and encodes data in U. encoded_vals range is integer values [0 2^N-1]
% quant_values shows the original data U converted to the quantized level
% representing the number
if (N<2)
disp('N is out of range. N must be > 2')
return;
end
quant_values = double(U(:));
max_val = max(quant_values);
min_val = min(quant_values);
%quantizes the data
quanta_size = (max_val-min_val) / (2^N -1);
quant_values = (quant_values-min_val) ./ quanta_size;
%reshapes the data
quant_values = reshape(quant_values, size(U));
encoded_vals = round(quant_values);
%returns the original numbers in their new quantized form
quant_values = (encoded_vals .* quanta_size) + min_val;
end
As far as I can tell this should always work, but I haven't done extensive testing, good luck

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

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.

Not sure how the hist function in MATLAB works

I am not very sure how the hist function in MATLAB works. I seem to have few problems with it.
Bascially, in the code below, i am trying to run the rotation invariant Uniform Local Binary Pattern(LBP) code. I have no problem with the LBP code but the problem is with hist function(indicated in the code below).
The problem is that the range i should get is from 0:9 but when i apply the histogram function i get values greater than 9 such as 35, 27 and even values such as 178114.Not very sure how to correct it.
I2 = imread('test.png');
RIUniformHist=[];
m=size(I2,1);
n=size(I2,2);
for i=1:10:m
for j=1:10:n
for k=i+1:i+8
for l=j+1:j+8
J0=I2(k,l);
I3(k-1,l-1)=I2(k-1,l-1)>J0;
I3(k-1,l)=I2(k-1,l)>J0;
I3(k-1,l+1)=I2(k-1,l+1)>J0;
I3(k,l+1)=I2(k,l+1)>J0;
I3(k+1,l+1)=I2(k+1,l+1)>J0;
I3(k+1,l)=I2(k+1,l)>J0;
I3(k+1,l-1)=I2(k+1,l-1)>J0;
I3(k,l-1)=I2(k,l-1)>J0;
LBP=I3(k-1,l-1)*2^7+I3(k-1,l)*2^6+I3(k-1,l+1)*2^5+I3(k,l+1)*2^4+I3(k+1,l+1)*2^3+I3(k+1,l)*2^2+I3(k+1,l-1)*2^1+I3(k,l-1)*2^0;
bits = bitand(LBP, 2.^(7:-1:0))>0;
if nnz(diff(bits([1:end, 1]))) <= 2
RIULBP(k,l)=abs(I3(k-1,l-1)-I3(k-1,l))+ abs(I3(k-1,l)-I3(k-1,l+1))+ abs(I3(k-1,l+1)-I3(k,l+1))+ abs(I3(k,l+1)-I3(k+1,l+1))+abs(I3(k+1,l+1)-I3(k+1,l))+abs(I3(k+1,l)-I3(k+1,l-1))+abs(I3(k+1,l-1)-I3(k,l-1));
else
RIULBP(k,l)=9;
end
end
end
RIULBP=uint8(RIULBP);
RIULBPv=reshape(RIULBP,1,size(RIULBP,1)*size(RIULBP,2));
RIUHist=hist(RIULBPv,0:9); % problem
RIUniformHist = [RIUniformHist RIUHist];
end
end
The vector returned by
RIUHist=hist(data, bins)
is the count of how many elements of data are nearest the point identified by the bins vector. So if you have a value of 178114, that juts means that there were 178114 elements of data that were nearest to the matching index in bins.
You can use
[RIUHist, binsOut] = hist(data)
to let Matlab choose the bins (I believe it uses 20 bins) or
[RIUHist, binsOut] = hist(data, binCount)
To let Matlab choose the bins, but force a certain number of bins (I often use 100 or 200).