Image registration in imageJ or matlab - matlab

I am looking for advice on how to automatically register image stacks acquired at different magnifications. Specially we need to align a small z-stack (~100um) taken of several brain cells in the live brain to a large z stack(~2mm) taken of the fixed brain. We want to be able to find back the cells that were previously imaged and take high resolution images of the staining to identify pre-synaptic inputs. Both the difference in magnification and rotation need to be taken into account as well as possible shrinkage or swelling. We would like an advice on the best way to do this using ImageJ or matlab.

With ImageJ you might want to download the plugin StackReg:
http://bigwww.epfl.ch/thevenaz/stackreg/
or this nice macro code freely available:
http://www.plosone.org/article/info%3Adoi%2F10.1371%2Fjournal.pone.0053942
With matlab you are looking for imregister, imregtform and/or imwarp. Also look at the optimizer, which is used to define the type of transformation you wish to apply, for example translation, rigid body, etc. Examples on the matlab website are quite helpful. Please ask for more details if it's not clear.
EDIT:
Here is a simple code to register images stored in a sequence in a cell array with Matlab and the functions I mentionned:
clear
clc
dialog_title = 'Select the directory containing the images to be processed'; % select images
folder_name = uigetdir('',dialog_title);
addpath(folder_name);
% select current folder
cd(folder_name);
ImagesToRead = dir('*.tif');
%preallocation
ImageCell = cell(1,length(ImagesToRead));
for i=1 : length(ImagesToRead)
ImageCell{i} = imread(ImagesToRead(i).name);
end
optimizer = registration.optimizer.RegularStepGradientDescent; % here you can modify the default properties of the optimizer to suit your need/to adjust the parameters of registration.
[optimizer, metric] = imregconfig('monomodal'); % for optical microscopy you need the 'monomodal' configuration.
RegisteredCell = cell(1,length(ImagesToRead));
for p = 2:length(ImagesToRead)
moving = ImageCell{p}; % the image you want to register
fixed = ImageCell{p-1}; % the image you are registering with
movingONE = rgb2gray(moving(:,:,:)); % imregtform needs grayscale images
fixedONE = rgb2gray(fixed(:,:,:));
tform = imregtform(movingONE,fixedONE,'translation',optimizer,metric,'DisplayOptimization',true,'PyramidLevels',5);
tform = affine2d(tform.T);
RegisteredCell{p} = imwarp(moving,tform,'OutputView',imref2d(size(fixedONE))); %
end
Now all your images are stored in the cell array 'RegisteredCell' and you can access each of them individually using RegisteredCell{YouImage} for example. Hope that helps!

Related

Filling the gaps in a binary image

I have found a couple areas referring to filling of gaps in binary images in matlab, however I am still struggling. I have written the following code but I cannot get it to work. Here is my binary image:
.
However, what I'm trying to achieve is the following
.
Does anyone know how to do this? I have been trying using imfill but I know I think I need to define boundaries also with the bwlabel function but I dont know how. Any help would be greatly appreciated.
%%Blade_Image_Processing
clc;
clear;
%%Video file information
obj = VideoReader('T9_720p;60p_60mm_f4.MOV');
% Sampling rate - Frames per second
fps = get(obj, 'FrameRate');
dt = 1/fps;
% ----- find image info -----
file_info = get(obj);
image_width = file_info.Width;
image_height = file_info.Height;
% Desired image size
x_range = 1:image_height;
y_range = 1:image_width;
szx = length(x_range);
szy = length(y_range);
%%Get grayscale image
grayscaleimg1 = rgb2gray(read(obj,36));
grayscaleimg = imadjust(grayscaleimg1);
diff_im = medfilt2(grayscaleimg, [3 3]);
t1=60;
t2=170;
range=(diff_im > t1 & diff_im <= t2);
diff_im (range)=255;
diff_im (~range)=0;
% Remove all those pixels less than 300px
diff_im = bwareaopen(diff_im,2000);
%imshow(diff_im)
%imhist(grayscaleimg)
%Fill gaps in binary image
BW2 = imfill(diff_im,'holes');
There are two main problems: desired object has no readily usable distinguishing features, and it touches other object. Second problem could be perhaps cleared with morphological opening/closing (touching object is thin, desired object not, is this always the case?), but first problem remains. If your object touched edge but others didn't or vice versa, you could do something with imfill and subtractions. As it is now, MAYBE something like this would work:
With opening/closing remove connection, so your object is disjoint.
With imfill, remove what is left of this thin horizontal thing.
Then, you can bwlabel and remove everything that touches sides or bottom of the image - in shown case that would leave only your object.
Exact solution depends heavily on what additional constrains are there for your pictures. I believe it is not a one-shot, rather you have more of those pictures and want to correctly find objects on all? You have to check what holds for all pictures, such as if object always touches only something thin or if it always touches only upper edge etc.

Identification of only a part of an image

I want to identify only this marked part in my image. (marked in red)
It should be a scale and translation invariant matching algorithm. Which is the best method I can use?
Will the SIFT method be useful here? As I have observed, it outputs many points. I want only this predefined part to be identified always. Maybe as a blob, or the centroid of this part.
Edit: I am trying to use SIFT from VLFeat. This is the code I am using:
Ia = imread ('Img_1.bmp') ; % Img_1 is the entire wheel's image
Ib = imread ('Img_2.png') ; % Img_2 is a small image containing only the part I want to identify in all images.
Ia = im2single(rgb2gray(Ia)) ;
Ib = im2single(rgb2gray(Ib)) ;
[fa, da] = vl_sift(Ia) ;
[fb, db] = vl_sift(Ib) ;
[matches, scores] = vl_ubcmatch(da, db) ;
After this, how can I view the matched images? As it is shown on the website?
Also, will this method serve my purpose of identifying only the small notch?
How should I proceed after this?

Lock image size on Matlab GUI

I'm making a GUI in MatLab that asks the user to upload a video file.
Next I want to play it in axes with a fixed window size . However, if the uploaded file is large, Matlab will expand the axes and take over most of my GUI. Is there a way to shrink the image to make it fit the axes?
Does anyone know how to solve this?
Usually Matlab axes are not supposed to change their position if the image is too big.
I can think of two possible problems:
The axes were large from the beginning, but showed small image with margins if the image is small enough
The command of showing the image that you are using is custom and it changes the axes size.
This question is old, but I stumbled across this (looking for something else) so perhaps it will help someone to see what I did.
I wanted to resize pretty large images (1024x 100k-200k pixels) so that my GUI can quickly demonstrate various color operations on a view of these large data sets. I just manually sub-sampled my data as follows (functions below).
Note that this example is an image. To spatially sub-sample a video, I have looped through the video and done something similar in the past on each frame.
[plotWidthPixels, plotHeightPixels] = getPlotAreaPixels(handles.figure1, handles.axes1);
[nSamplesPerLine nLines] = size(iqData);
colInds = decimateToNumber(nLines,plotWidthPixels);
rowInds = decimateToNumber(nSamplesPerLine,plotHeightPixels);
iqDataToPlot = iqData(rowInds,colInds);
First, I got the axis size in pixels:
function [plotWidthPixels, plotHeightPixels] = getPlotAreaPixels(figHandle, axisHandle)
set(figHandle,'Units','pixels')
figSizePix = get(figHandle,'Position');
set(axisHandle,'Units','normalized')
axSizeNorm = get(axisHandle,'Position');
axisSizePix = figSizePix.*axSizeNorm;
plotWidthPixels = ceil(axisSizePix(3)-axisSizePix(1));
plotHeightPixels = ceil(axisSizePix(4)-axisSizePix(2));
Then I used that to decimate the width and height of my image by getting sub-sets of indices that are (crudely approximately) evenly spaced:
function inds = decimateToNumber(lengthOfInitialVector, desiredVectorLength, initialIndex)
if nargin < 3
initialIndex = 1;
end
if (lengthOfInitialVector-initialIndex+1) > desiredVectorLength*2
inds = round(linspace(initialIndex,lengthOfInitialVector,desiredVectorLength));
else
inds = initialIndex:lengthOfInitialVector;
end

How do I detect an instance of an object in an image?

I have an image containing several specific objects. I would like to detect the positions of those objects in this image. To do that I have some model images containing the objects I would like to detect. These images are well cropped around the object instance I want to detect.
Here is an example:
In this big image,
I would like to detect the object represented in this model image:
Since you originally posted this as a 'gimme-da-codez' question, showing absolutely no effort, I'm not going to give you the code. I will describe the approach in general terms, with hints along the way and it's up to you to figure out the exact code to do it.
Firstly, if you have a template, a larger image, and you want to find instances of that template in the image, always think of cross-correlation. The theory is the same whether you're processing 1D signals (called a matched filter in signal processing) or 2D images.
Cross-correlating an image with a known template gives you a peak wherever the template is an exact match. Look up the function normxcorr2 and understand the example in the documentation.
Once you find the peak, you'll have to account for the offset from the actual location in the original image. The offset is related to the fact that cross-correlating an N point signal with an M point signal results in an N + M -1 point output. This should be clear once you read up on cross-correlation, but you should also look at the example in the doc I mentioned above to get an idea.
Once you do these two, then the rest is trivial and just involves cosmetic dressing up of your result. Here's my result after detecting the object following the above.
Here's a few code hints to get you going. Fill in the rest wherever I have ...
%#read & convert the image
imgCol = imread('http://i.stack.imgur.com/tbnV9.jpg');
imgGray = rgb2gray(img);
obj = rgb2gray(imread('http://i.stack.imgur.com/GkYii.jpg'));
%# cross-correlate and find the offset
corr = normxcorr2(...);
[~,indx] = max(abs(corr(:))); %# Modify for multiple instances (generalize)
[yPeak, xPeak] = ind2sub(...);
corrOffset = [yPeak - ..., xPeak - ...];
%# create a mask
mask = zeros(size(...));
mask(...) = 1;
mask = imdilate(mask,ones(size(...)));
%# plot the above result
h1 = imshow(imgGray);
set(h1,'AlphaData',0.4)
hold on
h2 = imshow(imgCol);
set(h2,'AlphaData',mask)
Here is the answer that I was about to post when the question was closed. I guess it's similar to yoda's answer.
You can try to use normalized cross corelation:
im=rgb2gray(imread('di-5Y01.jpg'));
imObj=rgb2gray(imread('di-FNMJ.jpg'));
score = normxcorr2(imObj,im);
imagesc(score)
The result is: (As you can see, the whitest point corresponds to the position of your object.)
The Mathworks has a classic demo of image registration using the same technique as in #yoda's answer:
Registering an Image Using Normalized Cross-Correlation

MATLAB - Restore central sub-section of an image

So, I have a 512x512 distorted image, but what I'm trying to do is restore only a 400x400 centrally-positioned subsection of the image while it is still distorted outside of it. How do I go about implementing something like that?
I was thinking to have a for loop within a for loop like
for row = 57:457
for col = 57:457
%some filter in here
end
end
But I'm not quite sure what to do next...
As a general rule, you can do a lot of things in MATLAB without loops using vectorization instead. As discussed in the comments below your question, there are filtering functions included with MATLAB such as medfilt2, wiener2 or imfilter which all work on two-dimensional images directly without the need for any loops.
To restore only the center part of your image, you apply the filter to the full image, store the result in a temporary variable and then copy over the part that you want into your distored image:
tmpimage = medfilt2(distortedimage);
finalimage = distortedimage;
finalimage(57:456,57:456)=tmpimage(57:456,57:456);
Of course if you don't care about edge effects during the reconstruction, you can just call the reconstruction for the part that interests you and avoid the tmpimage:
finalimage = distortedimage;
finalimage(57:456,57:456)=medfilt2(distortedimage(57:456,57:456));
Note how the sizes in an assignment need to match: you can't assign finalimage(57:456,57:456)=medfilt2(distortedimage) since the right-hand-size produces a 512-by-512 matrix which doesn't fit into the 400-by-400 center of finalimage.