Image processing with Mathematica 8

Matthias Odisio

Wolfram Research Inc.

Credits to my colleagues: Jeremy Michelson, Jian Zhao, Jingyi Jin, Lambert Chao, Mariusz Jankowski, Markus van Almsick, Piotr Wendykier, Shadi Ashnai, Timothy Kirchner, Yu-Sung Chang, and Peter Overmann

In this talk...

TextRecognize[]//Speak

Image Processing Features Overview

Morphology & Measurements
    Components, skeletons, extremas, hole filling, image analysis, shape & intensity measurements, ...

Filtering
    Fourier domain

Restoration
   Denoising, deconvolution, wavelets, ...

3D processing
   Deconvolution, morphology, visualization, ...

Segmentation
    Active contours, watershed transform, region growing, interactivity ...

Feature detection
    Edges, Lines, points-of-interest, ...

Image warping & Registration 
    General spatial transformation, image alignment & matching, multimodal registration, ...

and more...
    Text recognition, Live image capturing & processing, ...

Morphology & Measurements: Solve a Maze

i=;

Create the skeleton of the maze:

t=Thinning[i]

Convert the skeleton to a Graph:

g=MorphologicalGraph[t,"VertexLabels"->"Name"]

Find the solution (shortest path between the first and last nodes):

HighlightGraph[g,PathGraph[FindShortestPath[g,1,20]]]

Morphology & Measurements: Overlapping Cells Segmentation

i=;

Detect foreground

b=ColorNegate[Binarize[i]]

filled=FillingTransform[b]

Colorize@MorphologicalComponents[filled]

Separate Overlapping Cells

distanceT=DistanceTransform[filled,Padding->0];
ImageAdjust[distanceT]

marker=MaxDetect[ImageAdjust[distanceT],0.03]

g=GradientFilter[filled,5]

w=WatershedComponents[g,marker,Method->"Rainfall"];
Colorize[w]

Highlight Cells

cells=SelectComponents[w,"Count",1000<#<7000&];
Colorize[cells]

circles=ComponentMeasurements[cells,{"Centroid","EquivalentDiskRadius","Label"}];
Show[i,Graphics[{Blue,Thick,Circle@@#&/@(Most/@circles[[All,2]]),MapThread[Text,{circles[[All,2,3]],circles[[All,2,1]]}]}]]

Fourier domain: Halftone Removal

i = ;

Compute the Fourier transform

ft=Fourier[ImageData[i]];
Image@Abs[ft]

Mask the high frequency peaks corresponding to the halftone artifacts

mdata=ConstantArray[0,Reverse@ImageDimensions[i]];
mdata[[{1,-1},{1,-1}]]=1;
mask=Dilation[Image[mdata],DiskMatrix[60]]

Return to the spatial domain

ift=InverseFourier[ImageData[mask]*ft];
res=ImageAdjust[Image[Re@ift,ImageSize->All]]

Restoration: Denoising

pantheon=;

noisy = ImageEffect[pantheon,{"PoissonNoise",0.5}]

Magnify[ImageTake[noisy,{101,200},{101,200}],4]

tv = TotalVariationFilter[noisy,0.35,Method->"Poisson"];

Apply wavelet based denoising

WaveletDenoise[img_]:=DiscreteWaveletTransform[img,CDFWavelet[]]//WaveletThreshold[#,"SmoothGarrote"]& //InverseWaveletTransform;

wv=WaveletDenoise[noisy];

Magnify[GraphicsRow[{
ImageTake[pantheon,{101,200},{101,200}],
ImageTake[noisy,{101,200},{101,200}],
ImageTake[tv,{101,200},{101,200}],
ImageTake[wv,{101,200},{101,200}]}],3]

Restoration: Deconvolution

i=;

ImageDeconvolve[i,GaussianMatrix[5], Method->{"Hybrid", "Preconditioned"-> True}]

3D processing: Deconvolution

Many functions can also process arbitrary rank data:

data=ListDeconvolve[GaussianMatrix[{{5,5,1}}],ImageData[i]];

Image@data

3D processing: Volume erosion

slices=ColorCombine[{,,,,,,,,,,}];

Perform a 2D erosion, channel by channel:

MinFilter[slices,{1,1}]//ColorSeparate

Perform a 3D erosion:

data3D=ImageData[slices,Interleaving->False];
Dimensions@data3D

result=MinFilter[data3D,{1,1,1}];
Image/@result

3D rendering using CUDALink

Needs["CUDALink`"]
data=CUDAVolumetricDataRead[FileNameJoin[{$CUDALinkExampleDataPath,"stent8.raw"}],512,174];
CUDAVolumetricRender[data,"Width"->400,"Height"->400]

Segmentation: Active contours for chroma key

((F((Subscript[c, 1]),(Subscript[c, 2]),Γ)=μ Length[Γ]+ν Area(𝒟)+(Subscript[λ, 1])(∫_( 𝒟))|𝒻-(Subscript[c, 1])|)^2)dx dy+(Subscript[λ, 2])(((∫_( Ω\𝒟))|𝒻-(Subscript[c, 2])|)^2)dx dy

i=

scene=;

Detect the green background

background=ChanVeseBinarize[i,"TargetColor"->Green,"LengthPenalty"->1]

Make the green background transparent

ii=SetAlphaChannel[i,ColorNegate@background]

Compose with the desired image

ImageCompose[scene,ii]

Segmentation: Watershed transform for trabacular bone analysis

ReliefImage[]

(ws=WatershedComponents[])//Colorize

Histogram[ComponentMeasurements[ws, "Area"][[All, 2]],{0, 100, 2}]

bone=ws//Image

MorphologicalGraph[ColorNegate[bone]]

Segmentation: Interactive Segmentation

Module[{i=},
Manipulate[Row[{Show[i], Image[ImageForestingComponents[i, pts, 5]//Colorize, ImageSize->All]}], {{pts,RandomReal[Min[ImageDimensions[i]],{4,2}]},{0,0},ImageDimensions[i],Locator,LocatorAutoCreate->{2,5}}]
]

Feature detection: Edges

i=;

EdgeDetect[i,1]

Create your own edge detector using building blocks:

CrossingDetect[LaplacianGaussianFilter[i,1],0.006]

ImageMultiply[GradientFilter[i,1],%]//ImageAdjust

MorphologicalBinarize[%]

Feature detection: Lines

img=;
lines=ImageLines[EdgeDetect[img],.28,.06]

Visualize the vanishing point:

Show[img,Graphics[{Thick,Red,Line/@lines}]]

Feature Detection: Corresponding Points

is={ ,};

Show keypoints on an image

xy=ImageKeypoints[is[[1]]];
Show[is[[1]],Graphics[{PointSize[Medium],Yellow,Point[xy]}]]

Show matching keypoints on the two images

matches = ImageCorrespondingPoints[Sequence@@is];
MapThread[Show[#1,Graphics[{Yellow,MapIndexed[Inset[#2[[1]],#1]& ,#2]}]]&,{is,matches}]

Image Warping: Arbitrary transformation

Transform Mona Lisa to produce a wave effect

Manipulate[ImageTransformation[,{First[#1]+(1/10) Sin[p Last[#1]],Last[#1]}&,Padding->"Reflected"],{p,1,30}]

Image Warping: Perspective rectification

ImagePerspectiveTransformation[,{{1,0,0},{0,1,0},{0,-3.5,1}},1500,PlotRange->All,Resampling->"Bilinear"]

Registration: Panorama stitching

imgs={,,};

Create a canvas

canvas=Image[ConstantArray[{1,1,1,0},{500,1000}],ColorSpace->"RGB"];
canvas=ImageCompose[canvas,imgs[[2]]];
Framed[canvas]

Find the spatial relationship between the images to stitch them to the canvas

{e,t}=FindGeometricTransform[canvas,imgs[[1]]]

xform=ImagePerspectiveTransformation[imgs[[1]],t,DataRange->Full,PlotRange->Transpose[{{0,0},ImageDimensions[canvas]}],Padding->Transparent]

canvas=ImageCompose[canvas,xform];
{e,t}=FindGeometricTransform[canvas,imgs[[3]]];
xform=ImagePerspectiveTransformation[imgs[[3]],t,DataRange->Full,PlotRange->Transpose[{{0,0},ImageDimensions[canvas]}],Padding->Transparent];
canvas=ImageCompose[canvas,xform];
ImageCrop[canvas]

Registration: Multimodal registration of a human metatarsal specimen

Images courtesy of Brian Snyder, Center for Advanced Orthopedic Studies at Beth Israel Deaconess Medical Center

bse=;
ct=;

Reflect the CT image to provide better initialization conditions

ct2=ImageReflect[ct,Left->Bottom];
ImageCompose[ImageApply[{1,1,0}*#&,bse],{ImageApply[{0,0,1}*#&,ct2],.6}]

Register the two images

ctaligned=ImageAlign[bse,ct2]

ImageCompose[ImageApply[{1,1,0}*#&,bse],{ctaligned,.6}]

There is much more... Going further

Attend the image processing workshop tomorrow; bring your laptop!

TextRecognize[]//Speak

Dynamic[EdgeDetect[CurrentImage[]]]

Documentation: tutorials, guide pages

Virtual conference presentations on line

Online seminars