Pixel subtraction - matlab

I am working on code that select set of pixels randomly from gray images, then comparing the intensity of each 2 pixels by subtracting the intensity of pixel in one location from another one in different location.
I have code do random selection, but I am not sure of this code and I do not know how to do pixels subtraction?
thank you in advance..
{
N = 100; % number of random pixels
im = imread('image.bmp');
[nRow,nCol,c] = size(im);
randRow = randi(nRow,[N,1]);
randCol = randi(nCol,[N,1]);
subplot(2,1,1)
imagesc(im(randRow,randCol,:))
subplot(2,1,2)
imagesc(im)
}

Parag basically gave you the answer. In order to achieve this vectorized, you need to use sub2ind. However, what I would do is generate two sets of rows and columns. The reason why is because you need one set for the first set of pixels and another set for the next set of pixels so you can subtract the two sets of intensities. Therefore, do something like this:
N = 100; % number of random pixels
im = imread('image.bmp');
[nRow,nCol,c] = size(im);
%// Generate two sets of locations
randRow1 = randi(nRow,[N,1]);
randCol1 = randi(nCol,[N,1]);
randRow2 = randi(nRow,[N,1]);
randCol2 = randi(nCol,[N,1]);
%// Convert each 2D location into a single linear index
%// for vectorization, then subtract
locs1 = sub2ind([nRow, nCol], randRow1, randCol1);
locs2 = sub2ind([nRow, nCol], randRow2, randCol2);
im_subtract = im(locs1) - im(locs2);
subplot(2,1,1)
imagesc(im_subtract);
subplot(2,1,2)
imagesc(im);
However, the above code only assumes that your image is grayscale. If you want to do this for colour, you'll have to do a bit more work. You need to access each channel and subtract on a channel basis. The linear indices that were defined above are just for a single channel. As such, you'll need to offset by nRow*nCol for each channel if you want to access the same corresponding locations in the next channels. As such, I would use sub2ind in combination with bsxfun to properly generate the right values for vectorizing the subtraction. This requires just a slight modification to the above code. Therefore:
N = 100; % number of random pixels
im = imread('image.bmp');
[nRow,nCol,c] = size(im);
%// Generate two sets of locations
randRow1 = randi(nRow,[N,1]);
randCol1 = randi(nCol,[N,1]);
randRow2 = randi(nRow,[N,1]);
randCol2 = randi(nCol,[N,1]);
%// Convert each 2D location into a single linear index
%// for vectorization
locs1 = sub2ind([nRow, nCol], randRow1, randCol1);
locs2 = sub2ind([nRow, nCol], randRow2, randCol2);
%// Extend to as many channels as we have
skip_ind = permute(0:nRow*nCol:(c-1)*nRow*nCol, [1 3 2]);
%// Create 3D linear indices
locs1 = bsxfun(#plus, locs1, skip_ind);
locs2 = bsxfun(#plus, locs2, skip_ind);
%// Now subtract the locations
im_subtract = im(locs1) - im(locs2);
subplot(2,1,1)
imagesc(im_subtract);
subplot(2,1,2)
imagesc(im);

Related

Enlarging models in MATLAB

Im trying to create a project in MATLAB where i project a heat map matrix on to a cylinder in MATLAB but i'm bumping in to all kinds of issues.
Im using MATLAB version R2019b(Latest version).
Now my first issue id like to adress is is the modells being absolutely tiny even when i zoom in to the max.
Is there any way to make these models larger or to display them in a separate window ??
Also my second question is the regarding the scaling. As you can see the scale on the Z-axis of the cylinder goes to 512. any way to get a larger more detailed image where i can see each point on that scale?
clear vars
filename =
['/Users/gomer/Documents/Datavisualisering/Projekt/data/day/filenames.txt'];
%This line simply gives us a table of all filenames in this file.
T = readtable(filename);
tsize = size(T);
%extracts the content of the table as a categorical array.
%%
%
% {rownumber,variablenumber}. {100,1} = row 100, variable 1.
%converts the categorical array into a string array.
%joins the string array across the column.
%string(T{100:105,1}); implies from row 100 to row 105 and use variable 1.
%This line simply adds the name of the file at row 100 to the path of the
%file. Hnece we get a full filepath.
filename = strcat('/Users/gomer/Documents/Datavisualisering/Projekt/data/day/', string(T{100,1}));
map100 = getHeatMap(filename);
%%
%
filename = strcat('/Users/gomer/Documents/Datavisualisering/Projekt/data/day/', string(T{1000,1}));
map1000 = getHeatMap(filename);
%creates a image
k=imshow(map100);
%creates a colormap.
%gca returns the current axes (or standalone visualization) in the current figure.
%hence the command just works top down and affects last image displayed.
colormap(gca, 'jet');
k=imshow(map1000);
colormap(gca, "jet");
function heat = getHeatMap(filename)
%Returns a struct with info about the file.
s = dir(filename);
%Opens a file for reading, hence the 'r'.
fin=fopen(filename,'r');
%A = fread(fileID,sizeA,precision)
%reads file data into an array, A, with dimensions, sizeA, and positions the file pointer after the last value read.
%fread populates A in column order.
I=fread(fin,s.bytes,'uint8=>uint8');
%The uint16 function converts a Input array, specified as a scalar, vector, matrix, or multidimensional array.
%Converts the values in to type uint16 and creates a Matrix with the values.
%Looks more like we are just calculating the size of values to be
%deducted from matrix size (no idea why).
w = uint16(I(1))+256*uint16(I(2));
h = uint16(I(3))+256*uint16(I(4));
skip = s.bytes - w*h + 1;
IN = I(skip:1:s.bytes);
%reshape(A,sz) reshapes A using the size vector, sz, to define size(B). For example, reshape(A,[2,3]) reshapes A into a 2-by-3 matrix.
%sz must contain at least 2 elements, and prod(sz) must be the same as numel(A).
%single(X) converts the values in X to single precision.
Z=single(reshape(IN,w,h));
%Interpolate the values.
%telling the system which points to interpolate in between.
Z=griddedInterpolant(Z');
y_range = linspace(1.0,single(h),360);
x_range = linspace(1.0,single(w),512);
%Used to apecify the query points (points in between which we want
%interpolation) as vectors (this is to get a more continues image).
%specifies the query points as grid vectors.
%Use this syntax to conserve memory when you want to query a large grid of points.
heat = uint8(Z({y_range, x_range}));
end
Thank you
Resizing Figure Window
Copying your script to a .m and running it instead of a live .mlx file will automatically create all the figures in a separate window by default. To adjust the size of the figures the following the position property can be modified. To adjust the scale functions xticks(), yticks() and zticks() can be used. These three scale functions take in an array representing all the line markers along the respective axis/scale.
Test Plot Script:
X_Position = 10;
Y_Position = 10;
Width = 1000;
Height = 500;
%Configuring the figure settings%
figure('Position', [X_Position Y_Position Width Height])
%Test plot (replace with your plot)%
Data = [1 2 3 4 5 6];
plot(Data);
Plotting Heatmaps on a Cylindrical Surfaces
Method 1: Using warp() Function
Haven't delved into which orientation the data should be set as but this is an option to use the warp() function to wrap the heatmap around a cylinder. They're most likely other 3D plotting options if specific points are of interest. The points of the cylinder to be plotted are generated using the cylinder() function which returns the xyz-coordinates of the cylinder's wireframe. The fourth input argument into the warp() function serves and a colormap in this case it is proportional to the heatmap values.
load('HeatMapMatrix.mat');
%Setting up the figure%
clf;
close all;
figure('Position', [10 10 1000 500])
%Creating the cylinder%
Cylinder_Radius = 360;
Cylinder_Height = 512;
[X,Y,Z] = cylinder(Cylinder_Radius,Cylinder_Height-1);
%Warping the heatmap along the cylinder%
subplot(1,2,1); warp(X,Y,Cylinder_Height.*Z,map100');
colormap(gca,'jet');
subplot(1,2,2); warp(X,Y,Cylinder_Height.*Z,map100);
colormap(gca,'jet');
Method 2: Plotting All Points and Using surf() Function:
In this case, the coordinates for a cylinder are generated by first finding the coordinates of the circumference of the cylinder. This is done by using the sin() and cos() relationships:
X-Points = Radius × cos(𝜃)
Y-Points = Radius × sin(𝜃)
This results in the xy-coordinates of the cylinder's circle. These xy-coordinates need to be duplicated using repmat() to be later used for the varying heights. The process can be described best with a diagram as follows:
Four matrices above are created to plot each Heat Data point corresponding to an xyz-coordinate. The x and y coordinates are repeated in every row of matrices X-Points and Y_Points since those are constant for the repeating circles. The columns of the matrix Z-Points are also duplicates of each other since the heights should be constant for each row corresponding to each circle.
load('HeatMapMatrix.mat');
Radius = 20;
Number_Of_Data_Points = 360;
Theta = linspace(0,2*pi,Number_Of_Data_Points);
%The xy values according to radius and number of points%
X_Points = Radius*cos(Theta);
Y_Points = Radius*sin(Theta);
map100 = rot90(map100);
Sample_Range = 255 - 0;
Temperature_Range = 450 - 50;
Multiplier = Temperature_Range/Sample_Range;
map100 = map100.*Multiplier + 50;
Height = 512;
X_Points = repmat(X_Points,Height,1);
Y_Points = repmat(Y_Points,Height,1);
Z_Points = (1:512)';
Z_Points = repmat(Z_Points,1,Number_Of_Data_Points);
clf;
close;
figure('Position', [10 10 800 500])
Offset = 200;
subplot(1,3,1:2); Surface = surf(Y_Points,X_Points,Z_Points,'Cdata',map100);
title("3D Heatmap Plot");
zlabel("Height");
shading interp
colorbar
% direction = [0 1 0];
% rotate(Surface,direction,90)
Maximum_Value = 450;
Minimum_Value = 50;
caxis([Minimum_Value Maximum_Value]);
subplot(1,3,3); imshow(rot90(rot90(map100)));
colormap(gca, 'default');
title("Flat Heatmap Plot");
caxis([Minimum_Value Maximum_Value]);
colorbar;
Ran using MATLAB R2019b

Matlab - Plotting Specific Pixels (image treatment)

I'm currently struggling with an image treatment\ data plotting issue and was hoping to get some feedback from people with more experience than myself on this matter.
I'll try and breakdown the problem as to make it more understandable:
I have an original image (figureB - which is the blue chanel of the original image) of size NxM, from this image I select a specific area to study (NewfigureB), size 120x170;
I then divide this area into what I called macropixels which are 10x10 arrays of data points (pixels);
I then apply a mask to the selected area to select only the points meeting certain luminescence conditions;
So far so good. My problem comes when I try to plot a histogram of each of these macropixels when applying the luminescence mask. The final objective is to then find the peaks in these histograms.
so far this is what I've come up with. Any help would be greatly appreciated.
Many thanks
%Make the number of pixels in the matrix divisible
Macropixel = 10; %determine the size of the macropixel
[rows,columns] = size(figureB); %determine dimentions of the matrix used in the calculations
MacropixRows = floor(rows/Macropixel); %determine how many macropixels are in a row of the original matrix
MacropixColumn = floor(columns/Macropixel); %determine how many macropixels are in a column of the original matrix
%define new dim for the matrix
rows = MacropixRows * Macropixel;
columns = MacropixColumn * Macropixel;
NewfigureB = figureB(1:rows,1:columns); %divisible by the size of the macropixels created
%select area
NewfigureB = NewfigureB(1230:1349,2100:2269);
%create luminescence mask
Lmin=50;
hmax=80;
mask=false(size(NewfigureB));
mask(NewfigureB <Lmin)=true;
mask=mask & (NewfigureB<hmax);
%Apply mask
NewfigureB=NewfigureB(mask);
for jj = 1:Macropixel:120
for ii =1:Macropixel:170
histogram( NewfigureB(jj:jj+Macropixel-1, ii:ii+Macropixel-1))
end
end'''
The code you have posted has too many issues.
I tried to correct it the best I could.
I modified some parameters to feat the sample image I used.
I couldn't find your sample image, so I used the following
Here is a corrected code (please read the comments):
I = imread('Nikon-D810-Image-Sample-7.jpg');
figureB = I(:,:,3);
%Make the number of pixels in the matrix divisible
Macropixel = 10; %determine the size of the macropixel
[rows,columns] = size(figureB); %determine dimentions of the matrix used in the calculations
MacropixRows = floor(rows/Macropixel); %determine how many macropixels are in a row of the original matrix
MacropixColumn = floor(columns/Macropixel); %determine how many macropixels are in a column of the original matrix
%define new dim for the matrix
rows = MacropixRows * Macropixel;
columns = MacropixColumn * Macropixel;
NewfigureB = figureB(1:rows,1:columns); %divisible by the size of the macropixels created
%select area
NewfigureB = NewfigureB(1230:1349,2100:2269);
%create luminescence mask
Lmin=90;%50; %Change to 90 for testing
hmax=200;%80; %Change to 200 for testing
mask=false(size(NewfigureB));
mask(NewfigureB > Lmin)=true; %I think it should be > Lmin. %mask(NewfigureB <Lmin)=true;
mask=mask & (NewfigureB<hmax);
%This is not the right way to apply a mask, because the result is a vector (not a matrix).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Apply mask
%NewfigureB=NewfigureB(mask);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Assuming there are no zeros in the image, you can set masked elements to zero:
NewfigureB(~mask) = 0;
for jj = 1:Macropixel:120
for ii =1:Macropixel:170
%Copy NewfigureB(jj:jj+Macropixel-1, ii:ii+Macropixel-1) into temporary matrix MB:
MB = NewfigureB(jj:jj+Macropixel-1, ii:ii+Macropixel-1);
%Remove the zeros from MB (zeros are masked elements).
%The result is a vector (not a matrix).
MB = MB(MB ~= 0);
%histogram( NewfigureB(jj:jj+Macropixel-1, ii:ii+Macropixel-1))
figure; %Open new figure for each histogram. (I don't know if it's a good idea).
histogram(MB); %Plot the histogram of vector MB.
end
end
It's probably not exactly matches intentions.
I hope it gives you a lead...

Find the real time co-ordinates of the four points marked in red in the image

To be exact I need the four end points of the road in the image below.
I used find[x y]. It does not provide satisfying result in real time.
I'm assuming the images are already annotated. In this case we just find the marked points and extract coordinates (if you need to find the red points dynamically through code, this won't work at all)
The first thing you have to do is find a good feature to use for segmentation. See my SO answer here what-should-i-use-hsv-hsb-or-rgb-and-why for code and details. That produces the following image:
we can see that saturation (and a few others) are good candidate colors spaces. So now you must transfer your image to the new color space and do thresholding to find your points.
Points are obtained using matlab's region properties looking specifically for the centroid. At that point you are done.
Here is complete code and results
im = imread('http://i.stack.imgur.com/eajRb.jpg');
HUE = 1;
SATURATION = 2;
BRIGHTNESS = 3;
%see https://stackoverflow.com/questions/30022377/what-should-i-use-hsv-hsb-or-rgb-and-why/30036455#30036455
ViewColoredSpaces(im)
%convert image to hsv
him = rgb2hsv(im);
%threshold, all rows, all columns,
my_threshold = 0.8; %determined empirically
thresh_sat = him(:,:,SATURATION) > my_threshold;
%remove small blobs using a 3 pixel disk
se = strel('disk',3');
cleaned_sat = imopen(thresh_sat, se);% imopen = imdilate(imerode(im,se),se)
%find the centroids of the remaining blobs
s = regionprops(cleaned_sat, 'centroid');
centroids = cat(1, s.Centroid);
%plot the results
figure();
subplot(2,2,1) ;imshow(thresh_sat) ;title('Thresholded saturation channel')
subplot(2,2,2) ;imshow(cleaned_sat);title('After morpphological opening')
subplot(2,2,3:4);imshow(im) ;title('Annotated img')
hold on
for (curr_centroid = 1:1:size(centroids,1))
%prints coordinate
x = round(centroids(curr_centroid,1));
y = round(centroids(curr_centroid,2));
text(x,y,sprintf('[%d,%d]',x,y),'Color','y');
end
%plots centroids
scatter(centroids(:,1),centroids(:,2),[],'y')
hold off
%prints out centroids
centroids
centroids =
7.4593 143.0000
383.0000 87.9911
435.3106 355.9255
494.6491 91.1491
Some sample code would make it much easier to tailor a specific solution to your problem.
One solution to this general problem is using impoint.
Something like
h = figure();
ax = gca;
% ... drawing your image
points = {};
points = [points; impoint(ax,initialX,initialY)];
% ... generate more points
indx = 1 % or whatever point you care about
[currentX,currentY] = getPosition(points{indx});
should do the trick.
Edit: First argument of impoint is an axis object, not a figure object.

How can I make 3d plots of planes by using spreadsheet in matlab

pointA=[9.62579 15.7309 3.3291];
pointB=[13.546 25.6869 3.3291];
pointC=[23.502 21.7667 -3.3291];
pointD=[19.5818 11.8107 -3.3291];
points=[pointA' pointB' pointC' pointD'];
fill3(points(1,:),points(2,:),points(3,:),'r')
grid on
alpha(0.3)
This code will show a filled plane(Cant add images yet T.T)
Now here is my problem. On a spreadsheet, I have x,y,z coordinates of thousands of points. The 4 consecutive points form a plane like the one shown. How do I make a code such that for every 4 consecutive points, it makes a filled plane.
Basically, if I have 400 points, I want the code to plot 100 planes.
Assuming your data are a matrix, m = (400,3)
m = rand(400,3);
for i = 1:length(m);
m2 = m'; % Transpose
end
Create a 3-D matrix in which 'j' represents each set of points:
m3=[];
%Not the most elegant way to cycle through every four points but it works!
z = 0:(length(m2)/4); z1 = (z*4)+1; z1 = z1(:,1:length(z)-1);
for j = 1:length(z1);
m3(:,:,j) = m2(:,z1(j):(z1(j)+3));
end
'j' now has a total length = 100 - representing the amount planes;
fill3(m3(1,:,1),m3(2,:,1),m3(3,:,1),'r');
% Cycle through planes- make a new figure for each plane;
for j = 1:length(z1);
fill3(m3(1,:,j),m3(2,:,j),m3(3,:,j),'r');
end
clear all, close all, clc
pointA=rand(99,1);
pointB=rand(99,1);
pointC=rand(99,1);
pointD=rand(99,1);
pointAmat = reshape(pointA,3,1,[]);
pointBmat = reshape(pointB,3,1,[]);
pointCmat = reshape(pointC,3,1,[]);
pointDmat = reshape(pointD,3,1,[]);
points=[pointAmat pointBmat pointCmat pointDmat];
for i = 1:size(points,3)
fill3(points(1,:,i),points(2,:,i),points(3,:,i),'r')
hold all
end
grid on
alpha(0.3)
Hope this helps.

Measuring weighted mean length from an electrophoresis gel image

Background:
My question relates to extracting feature from an electrophoresis gel (see below). In this gel, DNA is loaded from the top and allowed to migrate under a voltage gradient. The gel has sieves so smaller molecules migrate further than longer molecules resulting in the separation of DNA by length. So higher up the molecule, the longer it is.
Question:
In this image there are 9 lanes each with separate source of DNA. I am interested in measuring the mean location (value on the y axis) of each lane.
I am really new to image processing, but I do know MATLAB and I can get by with R with some difficulty. I would really appreciate it if someone can show me how to go about finding the mean of each lane.
Here's my try. It requires that the gels are nice (i.e. straight lanes and the gel should not be rotated), but should otherwise work fairly generically. Note that there are two image-size-dependent parameters that will need to be adjusted to make this work on images of different size.
%# first size-dependent parameter: should be about 1/4th-1/5th
%# of the lane width in pixels.
minFilterWidth = 10;
%# second size-dependent parameter for filtering the
%# lane profiles
gaussWidth = 5;
%# read the image, normalize to 0...1
img = imread('http://img823.imageshack.us/img823/588/gele.png');
img = rgb2gray(img);
img = double(img)/255;
%# Otsu thresholding to (roughly) find lanes
thMsk = img < graythresh(img);
%# count the mask-pixels in each columns. Due to
%# lane separation, there will be fewer pixels
%# between lanes
cts = sum(thMsk,1);
%# widen the local minima, so that we get a nice
%# separation between lanes
ctsEroded = imerode(cts,ones(1,minFilterWidth));
%# use imregionalmin to identify the separation
%# between lanes. Invert to get a positive mask
laneMsk = ~repmat(imregionalmin(ctsEroded),size(img,1),1);
Image with lanes that will be used for analysis
%# for each lane, create an averaged profile
lblMsk = bwlabel(laneMsk);
nLanes = max(lblMsk(:));
profiles = zeros(size(img,1),nLanes);
midLane = zeros(1,nLanes);
for i = 1:nLanes
profiles(:,i) = mean(img.*(lblMsk==i),2);
midLane(:,i) = mean(find(lblMsk(1,:)==i));
end
%# Gauss-filter the profiles (each column is an
%# averaged intensity profile
G = exp(-(-gaussWidth*5:gaussWidth*5).^2/(2*gaussWidth^2));
G=G./sum(G);
profiles = imfilter(profiles,G','replicate'); %'
%# find the minima
[~,idx] = min(profiles,[],1);
%# plot
figure,imshow(img,[])
hold on, plot(midLane,idx,'.r')
Here's my stab at a simple template for an interactive way to do this:
% Load image
img = imread('gel.png');
img = rgb2gray(img);
% Identify lanes
imshow(img)
[x,y] = ginput;
% Invert image
img = max(img(:)) - img;
% Subtract background
[xn,yn] = ginput(1);
noise = img((yn-2):(yn+2), (xn-2):(xn+2));
noise = mean(noise(:));
img = img - noise;
% Calculate means
means = (1:size(img,1)) * double(img(:,round(x))) ./ sum(double(img(:,round(x))), 1);
% Plot
hold on
plot(x, means, 'r.')
The first thing to do to is convert your RGB image to grayscale:
gr = rgb2gray(imread('gelk.png'));
Then, take a look at the image intensity histogram using imhist. Notice anything funny about it? Use imcontrast(imshow(gr)) to pull up the contrast adjustment tool. I found that eliminating the weird stuff after the major intensity peak was beneficial.
The image processing task itself can be divided into several steps.
Separate each lane
Identify ('segment') the band in each lane
Calculate the location of the bands
Step 1 can be done "by hand," if the lane widths are guaranteed. If not, the line detection offered by the Hough transform is probably the way to go. The documentation on the Image Processing Toolbox has a really nice tutorial on this topic. My code recapitulates that tutorial with better parameters for your image. I only spent a few minutes with them, I'm sure you can improve the results by tuning the parameters further.
Step 2 can be done in a few ways. The easiest technique to use is Otsu's method for thresholding grayscale images. This method works by determining a threshold that minimizes the intra-class variance, or, equivalently, maximizes the inter-class variance. Otsu's method is present in MATLAB as the graythresh function. If Otsu's method isn't working well you can try multi-level Otsu or a number of other histogram based threshold determination methods.
Step 3 can be done as you suggest, by calculating the mean y value of the segmented band pixels. This is what my code does, though I've restricted the check to just the center column of each lane, in case the separation was off. I'm worried that the result may not be as good as calculating the band centroid and using its location.
Here is my solution:
function [locations, lanesBW, lanes, cols] = segmentGel(gr)
%%# Detect lane boundaries
unsharp = fspecial('unsharp'); %# Sharpening filter
I = imfilter(gr,unsharp); %# Apply filter
bw = edge(I,'canny',[0.01 0.3],0.5); %# Canny edges with parameters
[H,T,R] = hough(bw); %# Hough transform of edges
P = houghpeaks(H,20,'threshold',ceil(0.5*max(H(:)))); %# Find peaks of Hough transform
lines = houghlines(bw,T,R,P,'FillGap',30,'MinLength',20); %# Use peaks to identify lines
%%# Plot detected lines above image, for quality control
max_len = 0;
imshow(I);
hold on;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
%# Plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
%# Determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if ( len > max_len)
max_len = len;
end
end
hold off;
%%# Use first endpoint of each line to separate lanes
cols = zeros(length(lines),1);
for k = 1:length(lines)
cols(k) = lines(k).point1(1);
end
cols = sort(cols); %# The lines are in no particular order
lanes = cell(length(cols)-1,1);
for k = 2:length(cols)
lanes{k-1} = im2double( gr(:,cols(k-1):cols(k)) ); %# im2double for compatibility with greythresh
end
otsu = cellfun(#graythresh,lanes); %# Calculate threshold for each lane
lanesBW = cell(size(lanes));
for k = 1:length(lanes)
lanesBW{k} = lanes{k} < otsu(k); %# Apply thresholds
end
%%# Use segmented bands to determine migration distance
locations = zeros(size(lanesBW));
for k = 1:length(lanesBW)
width = size(lanesBW{k},2);
[y,~] = find(lanesBW{k}(:,round(width/2))); %# Only use center of lane
locations(k) = mean(y);
end
I suggest you carefully examine not only each output value, but the results from each step of the function, before using it for actual research purposes. In order to get really good results, you will have to read a bit about Hough transforms, Canny edge detection and Otsu's method, and then tune the parameters. You may also have to alter how the lanes are split; this code assumes that there will be lines detected on either side of the image.
Let me add another implementation similar in concept to that of #JohnColby's, only without the manual user-interaction:
%# read image
I = rgb2gray(imread('gele.png'));
%# middle position of each lane
%# (assuming lanes are somewhat evenly spread and of similar width)
x = linspace(1,size(I,2),10);
x = round( (x(1:end-1)+x(2:end))./2 );
%# compute the mean value across those columns
m = mean(I(:,x));
%# find the y-indices of the mean values
[~,idx] = min( bsxfun(#minus, double(I(:,x)), m) );
%# show the result
figure(1)
imshow(I, 'InitialMagnification',100, 'Border','tight')
hold on, plot(x, idx, ...
'Color','r', 'LineStyle','none', 'Marker','.', 'MarkerSize',10)
and applied on the smaller image: