Difference between revisions of "Assignment 4 part 1: Make a fake image"

From Course Wiki
Jump to: navigation, search
Line 38: Line 38:
 
Play around with the arguments. It's fun. You can make a giant microsphere or a tiny one.
 
Play around with the arguments. It's fun. You can make a giant microsphere or a tiny one.
  
 +
==Draw multiple particles in one image==
 
The next step is to write a function that can draw more than one particle. The function should take two arguments. The first argument is an N x 4 matrix. Each row of the matrix specifies a single microsphere. The first two columns contain the ''Y'' and ''X'' coordinates of the particle. The third column is the radius in pixels, and the fourth column is the intensity. Hint: use a <tt>for</tt> loop to iterate through each row of the matrix. Here is a framework for the function:
 
The next step is to write a function that can draw more than one particle. The function should take two arguments. The first argument is an N x 4 matrix. Each row of the matrix specifies a single microsphere. The first two columns contain the ''Y'' and ''X'' coordinates of the particle. The third column is the radius in pixels, and the fourth column is the intensity. Hint: use a <tt>for</tt> loop to iterate through each row of the matrix. Here is a framework for the function:
  

Revision as of 13:20, 1 October 2017

20.309: Biological Instrumentation and Measurement

ImageBar 774.jpg


This is part 1 of Assignment 4.

Overview

All software has to be tested. The code you will develop for this part of the lab measures the size and position of fluorescent microspheres in images. To test the code you are developing, you will need images of fluorescent microspheres. One way to get some images is to go to the lab, snap a few pictures with your microscope, and use those for testing. This is a fine idea, and you ought to do just that. But there is a drawback to this approach: the microspheres are scattered randomly so you don't know the ground truth of where the microspheres are. How will you know if you got it right? Another good approach is to generate synthetic images of microspheres whose positions you know exactly. The drawback of synthetic images is that they may differ in some important way from the actual images that come out of your microscope. It's a good idea to test your code both ways.

Before you start working on your resolution and particle tracking code, let's get started by generating synthetic images.

A useful function: draw a particle

You are going to make synthetic images of fluorescent microspheres. The function below is a useful building block. It draws a single microsphere on a dark background. To make an image of multiple particles, you can add up the images of several individual particles. (You will get funny results if the particles overlap — a physical impossibility IRL.)

The function takes arguments that specify the location of the particle, its radius, and its intensity as well as the size of the image. It returns a two-dimensional array of doubles. The function does not include any noise sources or blurring due to the optical system. We'll add those in a minute.

function OutputImage = DrawOneFluorescentMicrosphere( ...
        YCenter, XCenter, Radius, TotalIntensity, ImageSizeY, ImageSizeX )
    
    upsamplingFactor = ceil( 4 / Radius );
    [ x, y ] = meshgrid( 1:(1/upsamplingFactor):ImageSizeX, 1:(1/upsamplingFactor):ImageSizeY );

    distanceFromParticleCenterPixels = hypot(x - XCenter, y - YCenter);
    distanceFromParticleCenterRadiuses = distanceFromParticleCenterPixels ./ Radius;
    mask = ( distanceFromParticleCenterRadiuses < 1 );
    
    OutputImage = mask .* cos( distanceFromParticleCenterRadiuses .* pi ./ 2 );
    OutputImage = max( 0, imresize( OutputImage, [ ImageSizeY, ImageSizeX ] ) );
    OutputImage = TotalIntensity * OutputImage / sum( OutputImage(:) );

end

Remember that MATLAB functions have to be stored in a file that has the same name as the function, appended by ".m" Save the function in a file and give it a try ... type something like:

imshow( DrawOneFluorescentMicrosphere( 100, 100, 30, sqrt(2) * 30^2, 200, 200 ) );

Play around with the arguments. It's fun. You can make a giant microsphere or a tiny one.

Draw multiple particles in one image

The next step is to write a function that can draw more than one particle. The function should take two arguments. The first argument is an N x 4 matrix. Each row of the matrix specifies a single microsphere. The first two columns contain the Y and X coordinates of the particle. The third column is the radius in pixels, and the fourth column is the intensity. Hint: use a for loop to iterate through each row of the matrix. Here is a framework for the function:

function OutputImage = SyntheticFluorescentMicrosphereImage( Particles, ImageSize )
    OutputImage = zeros( ImageSize );

    for ii = 1:size( Particles, 1 )
        position = Particles(ii, 1:2);
        radius = Particles(ii, 3);
        intensity = Particles(ii, 4);
        % PUT YOUR CODE HERE
    end
end


Pencil.png

Complete the function SyntheticFLuorescentMicrosphereImage that renders a simulated image of multiple particles specified in an N x 4 matrix.


Modeling optical blurring and noise

For your next trick, you are going to add software models of optical blurring and imaging noise. This section introduces a few functions that will help you out.

Blurring

A decent model for the blurring that occurs in optical systems is to convolve your synthetic image with an Airy disk. To model this in software, you need two things: an Airy disk and a function that convolves things.

Here's
Thing 1: the function below generates an Airy disk. The parameters are: NA, magnification, pixel size, and image size. The Airy function has a bright central blob with rings that extend out to infinity, but it falls off.

function OutputImage = SimulatedAiryDisk( ...
        NumericalAperture, Magnification, Wavelength, PixelSize, ImageSize )

    airyDiskRadiusInPixels = 0.61 * Wavelength / NumericalAperture * Magnification / PixelSize;
    airyDiskCenter = ImageSize / 2;

    yAxis = (1:ImageSize(1)) - airyDiskCenter(1);
    xAxis = (1:ImageSize(2)) - airyDiskCenter(2);

    [ xCoordinate, yCoordinate ] = meshgrid( xAxis, yAxis );

    firstBesselZero = 3.8317;
    normalizedRadius = firstBesselZero .* hypot( xCoordinate, yCoordinate) ./ airyDiskRadiusInPixels;

    OutputImage = ( 2 * besselj(1, normalizedRadius ) ./ ( normalizedRadius ) ) .^ 2;
    
    % remove NaN from result if center is an integer
    if( all(airyDiskCenter == fix( airyDiskCenter )) )
        OutputImage( airyDiskCenter(1), airyDiskCenter(2) ) = 1;
    end
 end

Thing 2 (convolution) is built into MATLAB. The code snippet below demonstrates how to generate an Airy disk and convolve it with an image stored in the variable idealImage.

% generate Airy disk
psf = SimulatedAiryDisk( 0.65, 40, 590E-9, 7.4E-9, [ 51, 51 ] );
psf = psf / sum( psf(:);

% convolve ideal image with Airy disk
blurredImage = conv2( IdealImage, psf, 'same' );

Simulating noise

The MATLAB function randn( N, M ) returns an N row by M column matrix of pseudorandom numbers drawn from a normal distribution with $ \mu = 0 $ and $ \sigma = 1 $. Recall that all of the arithmetic operators in MATLAB like + and - and .* and ./ can operate on matrices. So it's very easy to add a matrix of random values in a single statement using MATLAB's built-in + operator.

Another function you will find useful for simulating noise is poissrnd( Lambda ). This function returns a matrix of Poisson-distributed random numbers. Lambda is the mean value of the distribution. If Lambda is a matrix, the function will return another matrix of the same size where each element of the matrix $ R_{y,x} $ is drawn from a Poisson distribution with mean \mu=\lambda_{y,x}, where y and x are the matrix indexes. Here is an example of poissrnd:

% generate logarithmically-spaced numbers between 1 and 1E4
foo = logspace( 0, 4, 100 );

% turn it into a 100 x 100 matrix by replicating foo along the vertical axis
foo = repmat( foo, [ 100 1 ] );

% generate poisson-distributed random numbers
bar = poissrnd( foo );
plot ( foo, bar, 'x' );

The plot has one "x" for each pseudorandom result, plotted versus the parameter of the distribution (the mean). Do the average values and spread of values increase as you expected?

For full documentation of any MATLAB functions, type doc <function-name> at the command prompt.

Write a function


Pencil.png

Write a function that generates synthetic images of fluorescent microspheres under the following conditions.

  • peak intensities vary randomly from 5,000 to 25,000 photons
  • camera quantum efficiency of 0.6
  • exposure time of 1 second
  • camera gain of 0.25 ADU per electron
  • detector resolution of 12 bits (values go from 0-4095)
  • dark current of 350 electrons per second
  • read noise with a standard deviation of 15 electrons
  • optical system numerical aperture of 0.65
  • detector resolution (digital image size) of 492 x 656 pixels.

The images should include realistic noise and optical blurring.

Turn in two synthetic images generated by your function: one image of 100 microspheres with r = 90 nm and one of five microspheres with r = 3.2μm



Navigation