I am particularly stuck in this case
I = imread('liftingbody.png');
S = qtdecomp(I,.27);
blocks = repmat(uint8(0),size(S));
for dim = [512 256 128 64 32 16 8 4 2 1];
numblocks = length(find(S==dim));
if (numblocks > 0)
values = repmat(uint8(1),[dim dim numblocks]);
values(2:dim,2:dim,:) = 0;
blocks = qtsetblk(blocks,S,dim,values);
end
end
blocks(end,1:end) = 1;
blocks(1:end,end) = 1;
imshow(I), figure, imshow(blocks,[])
( The example above is from the MATLAB help )
If I try to write the image i.e blocks using imwrite(blocks) then the whole image appears to be black. This happens for any input images. But I want to write exactly the output that imshow shows here. Can anyone help ?
You created blocks as a uint8 matrix. By convention, MATLAB and Image Processing Toolbox treat a uint8 grayscale as having a range of values from 0 to 255. That is, 0 is black and 255 is white. So your blocks matrix, which contains only 0s and 1s, would normally be displayed as black and almost-black.
When you displayed blocks using:
imshow(blocks,[])
You used the "auto-ranging" syntax of imshow, which displays the minimum value of blocks as black and the maximum value of blocks as white.
But then when you saved blocks using imwrite, it made the normal assumption of 0 as black and 255 as white.
Try initializing blocks as a logical matrix instead, like this:
blocks = logical(size(S));
MATLAB and Image Processing Toolbox treat a logical matrix as a binary image and will display 0 as black and 1 and white. If you pass a logical matrix to imwrite, it will create a 1-bit-depth binary image file.
a generic answer is to normalize the image to be in the range for imwrite(blocks):
imwrite((blocks-min(blocks))/(max(blocks)-min(blocks)))
Related
I wanted to move the DICOM images around x-axis with the value 4.2 milimeter and have written the following code:
srcFile2=dir('C:\Users\User\Desktop\Projekt\meine B.A\Programmieren\Archiv CBCT_A_04_08\*.dcm');
for i=1:88
filename2=strcat('C:\Users\User\Desktop\Projekt\meine B.A\Programmieren\Archiv CBCT_A_04_08\',srcFile2(i).name);
CBCT(:,:,i)=dicomread(filename2);
end
info_CBCT=dicominfo('C:\Users\User\Desktop\Projekt\meine B.A\Programmieren\Archiv CBCT_A_04_08\CT.Test CatPhan.Image 1');
info_CBCT.PixelSpacing(1);
info_CBCT.PixelSpacing(2);
CBCT=double(CBCT);
cb_ref = imref2d(size(CBCT),info_CBCT.PixelSpacing(1),info_CBCT.PixelSpacing(2))
T = [1 0 0;0 1 0;4.2 0 1];%-2.5883
tform_t = affine2d(T);
for j=1:88
Axial_CBCT_Trans1(:,:,j)= imwarp(CBCT(:,:,j),tform_t);
end
It worked without any error message. Then I subtracted the image before and after the translation.
Axial_CBCT_Trans1(:,:,48)-CBCT(:,:,48);
After the subtraction the difference is zero. this has the following that the image is not shifted around x-axis.
Does anyone have this problem?
I would ask if my code is written correctly?
Can the command (affine2d) be used in DIOM images or is there another command for the DICOM data , to move the DICOM images in x axis?
By default imwarp automatically centralize the output image.
You may add 'OutputView' argument for avoiding the automatic centralization.
Replace imwarp(CBCT(:,:,j),tform_t); with:
imwarp(CBCT(:,:,j), tform_t, 'OutputView', imref2d(size(CBCT(:,:,j))));
Here is a code sample that reproduce the issue (without DCOM):
I = imread('peppers.png');
T = [1 0 0; 0 1 0; 40.2 0 1];
tform_t = affine2d(T);
J = imwarp(I, tform_t); % Automatic centralization
K = imwarp(I, tform_t, 'OutputView', imref2d(size(I)));
figure;imshow(J);title('J'); % Displayed without translation.
figure;imshow(K);title('K'); % Displayed with translation.
I have a set of pictures on which I need to perform Fan Beam projection and reconstruction by MATLAB. But for these pictures I've got weird artifacts.
Following the documentation on ifanbeam() function, I've written the following code:
ph = phantom(100);
d = 100;
fan_proj = fanbeam(ph,d);
fan_reproj = ifanbeam(fan_proj,d);
imshow(fan_reproj)
And it worked well:
But then i tried to explicitly save the phantom image on the drive (instead of loading it from MATLAB itself), load it from the drive, and perform the same operation.
ph = phantom(100);
imwrite(ph, 'phantom.png');
clear;
ph = imread('phantom.png');
d = 100;
fan_proj = fanbeam(ph,d);
fan_reproj = ifanbeam(fan_proj,d);
imshow(fan_reproj)
And the result was suffering from weird artifacts:
Why does this happen? What exactly changes in the image so the result of this function also changes so dramatically?
The issue is that imshow (by default) expects the input data to have values between 0 and 1. This is true when you first construct the phantom.
ph = phantom(100);
min(ph)
0
max(ph)
1
But when you load it back from the file it will have values between 0 and 255. This is because it was saved and loaded back in as an unsigned 8-bit integer:
ph = imread('phtnom.png');
class(ph)
uint8
min(ph)
0
max(ph)
255
And when you use imshow with the default color scaling it will still be [0,1] causing the extreme contrast that you are seeing.
You can use [] as the second input to imshow to ensure that the full dynamic range of the image is displayed.
imshow(fan_reproj, [])
I am trying to use imadjust, and in order to do that I have to normalize the values in my image (grayscale image) to 0~1. I have tried the following:
for getting min/max values:
minValue = min(I(:));
maxValue = max(I(:));
than I tried using imadjust in some ways:
Iadjusted = imadjust(I,[lowestValue/highestValue; highestValue/highestValue] ,[0 1]);
Iadjusted = imadjust(I,[lowestValue/255; highestValue/255] ,[]);
Iadjusted = imadjust(I,[double(lowestValue/highestValue); double(highestValue/highestValue)] ,[]);
but none of them worked. Each of them shows error/ shows the original image without any change. When I displayed min/max values the results were right, but when I am trying to display to normalization it always shows 0 or 1. What am I doing wrong?
In MATLAB images are stored using uint8 by default, therefore in [0 1] you can only have two integer number (i.e. 0 and 1). To do what you want between and get an image with range [0, 1] you have to use doubles.
Therefore if you want to use imadjust:
I = double(I)/255;
J = imadjust(I,[min(I(:)); max(I(:))],[0.0; 1.0]);
(Imadjust with doubles wants everything to be between 0 and 1. This is true in general for images expressed with doubles).
This function adjusts a signal (can be image) to the range [0,1]
function normsig = normalize(sig)
sig = double(sig);
normsig = (sig-min(sig(:))) / (max(sig(:))-min(sig(:))) ;
end
usage for an image signal:
img = imread('xxxx.jpg','jpg');
figure; imshow(img);
normalizedimg = normalize(img);
figure; imshow(normalizedimg);
I have a pgm image with 1251 different pixel values, ranging from 0 to 1250. I know this because I can open this image file with kate and see the values.
But when I open the same file using Matlab's imread, it also returns me 1251 different pixel values, but these values are not consecutive. The minimum value is 0 and the maximum value is 65483.
I want to iterate through these values in a for loop so I need to read the original and consecutive values as they exist in the file. How to do that in Matlab?
EDIT: That's the image if someone wants to try.
image
The values are scaled so that when you view the image it's not mostly black.
I tested that the scaling works with straight integer truncation by checking that:
[A] = imread( 'myfile.pgm', 'pgm' );
p = sort(unique(A(:));
q = uint16((0:1250) * 65535 / 1251)';
all(p == q) % returns 1
So, you can restore the image like this:
map = arrayfun( #(x) uint16(x * 1251 / 65536), 0:65535 );
B = arrayfun( #(x) map(x+1), A );
I have a proplem when dealing with images in matlab, i have a white image and when i try to print the gray level of the image and increment it by 1 , it gives me 255, it never give me 256.
and here is the code. and the count is 0.
function [ count ] = white( I )
[row,col]=size(I);
count=0;
for x=1:row
for y=1:col
g=I(x,y); %the value of the gray level on each pixel
if((g+1) == 256)
count=count+1;
256
end
end
end
Your image class is probably uint8 and 255 is the maximal value of this class . For example:
>> uint8(inf)
ans =
255
Instead try to cast to a different class, for example I=uint32(I) ...
Following #Aganders3, I'll also offer a solution to your code that doesn't use for loops:
count=sum(I(:)>threshold); % Credit to #Jonas and #Aganders3
where threshold is the gray level you want to threshold
I think nate is correct on why this is not working.
Also, consider a much simpler solution to your problem (given I is full of integers):
count = sum(vector(I == intmax(class(I))));