Matlab - Read and show the tif image - matlab

Please checkout the below link which directs an image (tif). It has 4 channels.
http://amarfree.com/Kannada_1_001.tif
Please help me in reading the image and convert it to b/w image using matlab.
Kindly furnish the image channels information.

The fourth channel of your image is the alpha channel. It contains the transparency value of each pixel. In this example, all the values in the 4th channel are identical to 255:
sum(sum(I(:,:,4)~=255))
ans =
0
The general solution in this specific case is to ignore the last channel(since it doesn't add information at all), and use rgb2gray function:
I = imread('<image path>');
bw = rgb2gray(I(:,:,1:3));
However, in your case you don't have rgb2gray function (probably because you don't have Matlab's Image Processing Toolbox). The general solution for this case is to implement a function which converts rgb images into bw images.
Luckily, in this particular example, the 3 channels are completely identical:
isequal(I(:,:,1),I(:,:,2))
ans =
1
isequal(I(:,:,1),I(:,:,3))
ans =
1
Therefore, you can simply write:
bw = I(:,:,1);
Notice that it will only work for this particular case.

Related

Binarization of an image with desired threshold

I am trying to make a function, that would be given a grayscale image, which it will binarize depending on the set threshold. I've been at this all day but no success.
Here is the code I implemented. With the image being a specific image; Not a variable.
function [ output_args ] = thresholdImg(X)
A=imread('car_gray.jpg');
B=zeros(size(A,1),size(A,2));
for l=1:size(A,1)
for m=1:size(A,2)
if(sum(A(l,m,:))>X)
B(l,m)=1;
end
end
end
B=logical(B);
figure,imshow(B);
I don't want to use imbinarize. I want this to be preformed manually, and the code to be as simple as possible. The output of the image looks like it is binary, but when you print the matrix, you see that the values are not only 0s and 1s or 255s
What am I doing wrong?
It'd be faster to get rid of the loop altogether:
function [] = thresholdImg(X)
A=imread('car_gray.jpg');
tmp=sum(A,3); % sum along the third dimension
B = zeros(size(tmp));
B(tmp>X) = 1; % Set all values above the threshold to be one
B=logical(B);
figure,imshow(B);
Using the following conditions: A = rand(100,100,3);X=0.6; we get this picture:
We see that this is indeed, as we expected, fully binary. Additionally, you can check this by calling whos B, which tells us B is indeed of type logical and hence has only zeros and ones.
whos B
Name Size Bytes Class Attributes
B 100x100 10000 logical
Your problem appears when you save the image. If you check the description of imwrite, you will see that if you want to save your image as binary, you are supposed to choose BMP, PNG or TIFF. These are lossless formats. JPEG on the other hand is a lossy compression format.
In addition, I made your code very compact, according to Adriaan's answer:
function [] = thresholdImg(X)
A=imread('car_gray.jpg');
B = sum(A, 3) > X
figure,imshow(B);

MATLAB loading and saving a single image from a 32 bit tiff stack

I'm using MATLAB_R2011a_student. I have some image stacks saved as 32 bit tiffs, some over 1000 frames. I would like to be able to pull out a specific frame from the stack and save it as a 32 bit tiff or some readable format where there would be no data loss from the original. Currently my code looks like this:
clear, clc;
k=163;
image=('/Users/me/Filename.tiff');
A = uint8(imread(image, k));
B=A(:,:,1);
J=imadjust(B,stretchlim(B),[]);
imwrite(J,'/Users/me/163.tif','tif');
(I'm assuming reading it as 8 bit, and the way I'm saving are not the best way to do this)
Either way this code works for a seemingly random number of frames (for example in one file.tiff the above code works for frames 1-165 but none of the frames after 165, for a different file.tiff the code works for frames 1-8 but none of the frames after 8) I'm also getting a strange horizontal line in the output image when this does work:
??? Error using ==> rtifc
Invalid TIFF image index specified.
Error in ==> readtif at 52
[X, map, details] = rtifc(args);
Error in ==> imread at 443
[X, map] = feval(fmt_s.read, filename, extraArgs{:});
Thanks!
The best way (in my opinion) to handle tiff stacks is to use the Tiff library available since a few years. I must admit that I don't know much about OOP but I managed to understand enough to load a tiff stack and manipulate it.That's the kind of simple demo I wish I had seen a year ago haha.
I the following example I load a single stack and store it all into a 3D array. I use imfinfo to fetch infos about the images, notably the number of images/stack and the actual image dimensions. If you want you can choose to load only one image using appropriate indices. Please try the code below and play around with it; you'll understand what I mean.
clear
clc
%// Get tiff files you wish to open
hFiles = dir('*.tif');
%// Here I only have 1 multi-tiff file containing 30 images. Hence hInfo is a 30x1 structure.
hInfo = imfinfo(hFiles(1).name);
%// Set parameters.
ImageHeight = hInfo(1).Height;
ImageWidth = hInfo(1).Width;
SliceNumber = numel(hInfo);
%// Open Tiff object
Stack_TiffObject = Tiff(hFiles.name,'r');
%// Initialize array containing your images.
ImageMatrix = zeros(ImageHeight,ImageWidth,SliceNumber,'uint32');
for k = 1:SliceNumber
%// Loop through each image
Stack_TiffObject.setDirectory(k)
%// Put it in the array
ImageMatrix(:,:,k) = Stack_TiffObject.read();
end
%// Close the Tiff object
Stack_TiffObject.close
Hope that helps.

Conversion to binary : Matlab

I am trying to extract veins using thinning algorithm. So far i did this much of code for image enhancement and its pretty much working. But when i computed binary thresholding i am not able to identify the veins from the back ground.Due to a vague output i am not able to do further processing for thinning. Can any one tell me whats wrong in this code? or is it because the threshold has to be done in some other way.
a=imread('vein.jpg');
cform = makecform('srgb2lab');
for ii = 1:3
a(:,:,ii) = medfilt2(a(:,:,ii),[5 5]);
end
lab = applycform(a,cform);
b=lab(:,:,1);
c=im2bw(b,0.2);
neg=1-c;
color=a;
r=color(:,:,1);
r(~c)= 0;
g = color(:,:,2);
g(~c)= 0;
b = color(:,:,3);
b(~c)= 0;
color = cat(3,r,g,b);
gray=rgb2gray(color);
i1=imresize(gray,[256 256],'bilinear');
i2=histeq(i1,256);
e=medfilt2(i2,[5 5]);
figure(1),imshow(e);
f=medfilt2(e,[5 5]);
figure(2),imshow(f);
thresh_level = graythresh(g);
BW = im2bw(g, thresh_level);
figure(10),imshow(BW);
greythresh uses Otsu's method, which is a good general method that works on the distribution of intensities. However it's not ideal for every situation, particularly if you've applied lots of nonlinear processing to the image first (e.g. clipping the channels).
You could try to generate your own threshold - look at the intensity distribution or, since you have them, the distribution in the colour channels and see if there's a plausible place to separate them. You could try to model it as a mixture of Gaussians (2 seems like a good number to start with, look up gmdistribution.fit) or do some other type of clustering. Is there any information in the colour channels that you could use?
If you end up the other way - with veins that are much darker but are continuous - then you could use morphological operators on the binarised image to get it back to the expected range. Perhaps this is what the thinning algorithm does.

eigenfaces are not showing correctly and are very dark

I need to show 1st 10 eigenfaces using PCA for a image feature vector matrix.
I am using following matlab code to create 1st eigenface but I am getting very dark and not so correct eigenfaces.
eFea is a matrix of 240x4096 where each row represents an image of 64x64
newData = eFea';
data = newData;
[M,N] = size(data);
mn = mean(data,2);
data = double(data) - repmat(mn,1,N);
% construct the matrix Y
Y = data' / sqrt(N-1);
% SVD
[u,S,PC] = svd(Y,0);
imshow(reshape(PC(1,:),64,64))
any hints regarding the error in code will be helpful.
IMSHOW does not automatically scale the image. Thus, if you only have values from, say, 0 to 0.3 in the eigenface, everything will be really dark. Try imshow(reshape(PC(1,:),64,64),[]) instead.
This is a really old topic but I want to answer something anyway.
Honestly, I think the error is somewhere else, although what Jonas said might give good-looking results.
You need to add the mean of the data again in the end. I just had the same problem with the dark principal components, that's why I found this question. But then I realized, that when you do PCA, you substract the mean first. That means that in the end, you need to add it again.

column to block using sliding window in matlab

using im2col sliding window in matlab i have converted the input image block into column and again by using col2im i do the inverse process but the output is not same as the input image. How can i recover the input image? can anyone please help me.
Here is the code
in=imread('tire.tif');
[mm nn]=size(in);
m=8;n=8;
figure,imshow(in);
i1=im2col(in,[8 8],'sliding');
i2 = reshape( sum(i1),mm-m+1,nn-n+1);
out=col2im(i2,[m n],[mm nn],'sliding');
figure,imshow(out,[]);
thanks in advance...
You didn't specify exactly what the problem is, but I see a few potential sources:
You shouldn't expect the output to be exactly the same as the input, since you're replacing each pixel value with the sum of pixels in an 8-by-8 neighborhood. Also, you will get a shrinkage of the resulting image by 7 pixels in each direction (i.e. [m-1 n-1]) since the 'sliding' option of IM2COL does not pad the array with zeroes to create neighborhoods for pixels near the edges.
These two lines are redundant:
i2 = reshape( sum(i1),mm-m+1,nn-n+1);
out=col2im(i2,[m n],[mm nn],'sliding');
You only need one or the other, not both:
%# Use this:
out = reshape(sum(i1),mm-m+1,nn-n+1);
%# OR this:
out = col2im(sum(i1),[m n],[mm nn],'sliding');
Image data in MATLAB is typically of type 'uint8', meaning each pixel is represented as an unsigned 8-bit integer spanning the range 0 to 255. Assuming this is what in is, when you perform your sum operation you will implicitly end up converting it to type 'double' (since an unsigned 8-bit integer will likely not be big enough to hold the sum totals). When image pixel values are represented with a double type, the pixel values are expected to span the range 0 to 1, so you will want to scale your resulting image by its maximum value to get it to display properly:
out = out./max(out(:));
Lastly, check what kind of input image you are using. For your code, you are essentially assuming in is 2-D (i.e. a grayscale intensity image). If it is a truecolor (i.e. RGB) image, the third dimension is going to cause you some trouble, and you will have to either process each color plane separately and recombine them or convert the RGB image to grayscale. If it is an indexed image (with an associated color map), you will not be able to do the sort of processing you describe above without first converting it to a grayscale representation.
Why are you expecting the output to be the same?
i2 is the result of performing a SUM around a pixel neighborhood (essentially a low-pass filter), which is the final blurry image that you see. i.e you are NOT doing an inverse process with the COL2IM call.
i1 obtained from 'sliding' option has the information that you would get from 'distinct' option as well, which you need to filter out. Now, this may not be the best way to code it up but it works. Assume that mm is a multiple of m and nn is a multiple of n. If this is not the case, then you'll have to zero-pad accordingly to make this the case.
in=imread('tire.tif');
[mm nn]=size(in);
m=8;n=8;
i1 = im2col(in,[m,n],'sliding');
inSel = [];
for k=0:mm/m-1
inSel = [inSel 1:n:nn+(nn-n+1)*n*k];
end
out = col2im(i1(:,inSel),[m,n],[mm,nn],'distinct');