normalize values for imadjust - matlab

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

Related

Using the affine2d command with the dicom images in matlab

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.

How to apply median filter in all images and store in a directory?

f = 'C:\Users\HP\Desktop\images';
d = ls(f);
d(1,:)=[]
d(1,:)=[]
mkdir('New_images')
for i=1:size(d)
I=imread(fullfile(f,d(i,:)));
Kmedian = I;
for i = 1:3
Kmedian(:,:,i) = medfilt2(Kmedian(:,:,i));
end
Kmedian=imresize(Kmedian,[227 227]);
imshow(Kmedian)
imwrite(Kmedian,fullfile('New_images',strcat(num2str(i),'.jpeg')));
end
How to use median filter at once.
Errors:
In resize (line 5)
Index in position 3 exceeds array bounds (must not exceed 1).
Error in resize (line 10)
Kmedian(:,:,i) = medfilt2(Kmedian(:,:,i));
The medfilt2 function only works on 1 channel at the time. If you have a color image, you will have a 3rd dimension to your pixel "matrix" for red, green, blue channels respectively.
You can still use the medfilt2 function by either converting your image to grayscale, or apply it to each channel individually.
Kmedian = I;
for i = 1:size(Kmedian,3) % Iterate over all the channels in the image
Kmedian(:,:,i) = medfilt2(Kmedian(:,:,i));
end
Updated to account for both single and multi channel images

Matlab get vector of specific pixels

I am pretty new to Matlab and encountered a problem when working with images.
I want to get a pixel that is in a specific colour (blue) in the following image:
image
My current code looks something like this:
function p = mark(image)
%// display image I in figure
imshow(image);
%// first detect all blue values higher 60
high_blue = find(image(:,:,3)>60);
%cross elements is needed as an array later on, have to initialize it with 0
cross_elements = 0;
%// in this iteration the marked values are reduced to the ones
%where the statement R+G < B+70 applies
for i = 1:length(high_blue)
%// my image has the size 1024*768, so to access the red/green/blue values
%// i have to call the i-th, i+1024*768-th or i+1024*768*2-th position of the "array"
if ((image(high_blue(i))+image(high_blue(i)+768*1024))<...
image(high_blue(i)+2*768*1024)+70)
%add it to the array
cross_elements(end+1) = high_blue(i);
end
end
%// delete the zero element, it was only needed as a filler
cross_elements = cross_elements(cross_elements~=0);
high_vector = zeros(length(cross_elements),2);
for i = 1:length(cross_elements)
high_vector(i,1) = ceil(cross_elements(i)/768);
high_vector(i,2) = mod(cross_elements(i), 768);
end
black = zeros(768 ,1024);
for i = 1:length(high_vector)
black(high_vector(i,2), high_vector(i,1)) = 1;
end
cc = bwconncomp(black);
a = regionprops(cc, 'Centroid');
p = cat(1, a.Centroid);
%// considering the detection of the crosses:
%// RGB with B>100, R+G < 100 for B<150
%// consider detection in HSV?
%// close the figure
%// find(I(:,:,3)>150)
close;
end
but it is not optimized for Matlab, obviously.
So i was wondering if there was a way to search for pixels with specific values,
where the blue value is larger than 60 (not hard with the find command,
but at the same time the values in the red and green area not too high.
Is there a command I am missing?
Since English isn't my native language, it might even help if you gave me some suitable keywords for googling ;)
Thanks in advance
Based on your question at the end of the code, you could get what you want in a single line:
NewImage = OldImage(:,:,1) < SomeValue & OldImage(:,:,2) < SomeValue & OldImage(:,:,3) > 60;
imshow(NewImage);
for example, where as you see you provide a restriction for each channel using logical operators, that you can customize of course (eg. using | as logical OR). Is this what you are looking for? According to your code you seem to be looking for specific regions in the image like crosses or coins is that the case? Please provide more details if the code I gave you is completely off the track :)
Simple example:
A = imread('peppers.png');
B = A(:,:,3)>60 & A(:,:,2)<150 & A(:,:,1) < 100;
figure;
subplot(1,2,1);
imshow(A);
subplot(1,2,2)
imshow(B);
Giving this:

Features for Image containing many objects

If I have an image that contains many objects and I want to get for example the first image moments for the entire image as result from bwlabel, which is stored in Ilabel, how would I do that?
[Ilabel num] = bwlabel(Ibw);
stats = regionprops(Ilabel,'BoundingBox');
Assuming Ibw in your example is numeric (not logical) and contains only integers 0 and 1 (or 0 and some other consistent integer value), you should be able to use it directly as a label matrix:
stats = regionprops(Ibw,'BoundingBox');
This will treat every non-zero pixel in the image as part of a single component. Alternatively , you can take the label matrix from bwlabel and change all of the labels to 1:
[Ilabel num] = bwlabel(Ibw);
Ilabel(find(Ilabel)) = 1;
stats = regionprops(Ilabel,'BoundingBox');

Manual Mean Filtering

Before I begin, I would just like to clarify that I understand how to use kernels and the conv2() function in order to mean filter an image, but I have been tasked with doing this manually by calling up each pixel.
My goal here is to call up each pixel, find its neighbors, average them out, and replace previous values with the acquired mean, without using kernels or conv2(). I have so far attempted to find the neighbors of each pixel using
for
I = 1:512;
for
J = 1:683;
A = myimage;
neighbor_offsets = [-1, A, 1, -A, A + 1, -A + 1, -A-1, A - 1];
idx = [I J];
neighbors = bsxfun(#plus,idx,neighbor_offsets);
but it does not seem to work, and I am a bit lost in trying to fix it. I think I could finish the job if I were able to get the neighbors by using something like
sum(neighbors) / 9
then replace the previous values with that answer, but please correct me if I'm. I've developed somewhat of a tendency to ask poor questions, so if anything is unclear, please let me know so I can clarify for you. Thanks
Example below treats pixels at the edge in the manner that it only considers pixels that are inside the image. For example when program is computing average with kernel dy = (-1:1) and dx = (-1:1) on top-left corner, it only considers top-left corner and its immediate 3 neighbors (right, right-bottom, right), and does average of those 4 pixels.
I would strongly advise you to test every line separately in Matlab's command window to see it's behavior!
% find image size
imsz = size( myimage );
% initialize output image
imavg = zeros( imsz );
% iterate over pixels
for yy = 1 : imsz(1)
for xx = 1 : imsz(2)
% define rectangle-kernel width
dy = (-1:1); % 1 up, to 1 down and ...
dx = (-1:1); % 1 left, to 1 right from current pixel
% get indexes of image
indy = yy + dy;
indx = xx + dx;
% [!!!] keep indexes that are inside image
indy = indy( indy>0 & indy<=imsz(1) );
indx = indx( indx>0 & indx<=imsz(2) );
% create all the pairings of chosen indexes
[ IY, IX ] = meshgrid( indy, indx );
% take all values of chosen pixels
pixs = myimage( sub2ind(imsz,IY(:),IX(:)) );
% save mean of chosen pixels to the given location
imavg(yy,xx) = mean( pixs );
end
end
You can create function from the above code with creating mean_filter.m file with this contents:
function imagv = mean_filter( myimage )
% code from above ...
You can call function from command window by positioning yourself in the directory where it's at and executing filtered = mean_filter( myimage );.
You can repeatedly filter the same image with:
filtered_3_times = myimage;
for ii = 1 : 3
filtered_3_times = mean_filter( filtered_3_times );
end