Discrete Wavelets

031 - Introduction to Digital Images

Helmut  Knaust - Department of Mathematical Sciences, University of Texas at El Paso, hknaust@utep.edu
01/28/2009. Last edit 01/23/2024.

SetDirectory[NotebookDirectory[]];
<<DW.wl

ASCII, decimal and binary representation

Keyboard input (ASCII characters) can be converted to decimals or represented in binary code :

TableForm[Partition[Table[Reverse[{BaseForm[i,2],i,FromCharacterCode[i]}],{i,32,127}],8]]

If one wants to store characters as a sequence of 8 zeros and ones ("8-bit representation"), one can actually represent 256 characters:

TableForm[Partition[Table[Reverse[{BaseForm[i,2],i,FromCharacterCode[i]}],{i,0,255}],8]]

The 8 - bit grayscale intensity scale

Similarly, 8 bit can represent 256 shades of gray. 0 corresponds to black, 255 to white.

eight=Table[i,{i,0,255}]

Graphics[Raster[{eight/255}],AspectRatio->.075,Frame->True,FrameTicks->{Table[k 2^4,{k,0,16}],None}]

From matrices to grayscale images

mat=RandomInteger[{0,255},{5,5}]

Let' s use a command form the package  ' DW.m' to view the matrix as an image:

?ImagePlot

ImagePlot[mat,PixelConstrained->20]

BTW, a question mark in front of a command gives a short description of the command :

?Transpose

From B&W photos to matrices to grayscale images

pic=Import["Images\\Grayscale\\landscape_small.png","Data"];

ImagePlot[pic]

pic2=Import["Images/Grayscale/canoes_small.png","Data"];

ImagePlot[pic2]

Image processing: Negative

The negative image :

neg=255-pic;

ImagePlot[neg]

ImagePlot[neg+pic,Scaled->False]

Image processing: Averaging

mat=RandomInteger[{0,255},{8,4}]

ImagePlot[mat,PixelConstrained->20]

mat
ave=Transpose[.5{{1,1,0,0},{0,0,1,1}}]

mat2=mat.ave

Grid[{{ImagePlot[mat,PixelConstrained->40,Scaled->False],ImagePlot[mat2,PixelConstrained->40,Scaled->False]}}]

ave2=.5{{1,1,0,0,0,0,0,0},{0,0,1,1,0,0,0,0},{0,0,0,0,1,1,0,0},{0,0,0,0,0,0,1,1}}

ave2.mat2

Grid[{{ImagePlot[mat,PixelConstrained->40,Scaled->False],ImagePlot[mat2,PixelConstrained->40,Scaled->False],ImagePlot[ave2.mat2,PixelConstrained->40,Scaled->False]}}]

Here is the same procedure applied to an image :

pic=Import["Images\\Grayscale\\landscape.png","Data"];{dimr,dimc}=Dimensions[pic];
H[dim_]:=SparseArray[{{i_,j_}/;i==2j-1->.5,{i_,j_}/;i==2j->.5},{dim,dim/2}];
small=Transpose[H[dimr]].pic.H[dimc];
Grid[{{ImagePlot[pic,PlotLabel->StringForm["Dimensions: `1` x `2`",dimr,dimc]]},{ImagePlot[small,PixelConstrained->1,Scaled->False,PlotLabel->StringForm["Dimensions: `1` x `2`",dimr/2,dimc/2]]}}]

The small picture blown up to original size :

ImagePlot[small,PixelConstrained->2,Scaled->False,PlotLabel->StringForm["Dimensions: `1` x `2`",dimr/2,dimc/2]]

Image processing: Edge detection

pic=Import["Images\\Grayscale\\church.png","Data"];
{dimr,dimc}=Dimensions[pic];
diff=SparseArray[{{i_,j_}/;i==j->1,{i_,j_}/;i==j+1->-1,{1,dimc}->-1},{dimc,dimc}];
Normal[diff[[1;;10,1;;10]]]
ImagePlot[pic]

Dimensions[Abs[pic.diff]]

ve=Abs[pic.diff];
ImagePlot[ve]
ImagePlot[255-ve]

Image Processing : Cropping

car=Import["Images\\Grayscale\\car.png","Data"];
Dimensions[car]

ImagePlot[car]

We can crop this picture to show only rows 250 to 450 and columns 50 to 500 :

carcrop=car[[250;;450,50;;500]];
ImagePlot[carcrop]

Image Processing : Gamma correction

A gamma correction function is any increasing function γ : [0, 1]⟶[0, 1], satisfying γ(0)=0 and γ(1)=1.

γ[t_]=Sqrt[t];
Plot[{t,γ[t]},{t,0,1},PlotStyle->{{Red,Dashed},{Thick,Blue}}]

ImagePlot[carcrop,PlotLabel->"Original Image"]
ImagePlot[car2=Round[255Map[Function[x,γ[x]],carcrop/255.,{2}]],PlotLabel->"γ-corrected Image"]
ImagePlot[Abs[car2-carcrop],PlotLabel->"Absolute Difference",Scaled->False]

gammacorr[funct_,image_]:=Module[{},Grid[{{ImagePlot[image],Plot[t,{t,0,1}]},
{ImagePlot[Round[255Map[funct,image/255,{2}]]],Plot[{t,funct[t]},{t,0,1},PlotStyle->{Dashed,Thick},PlotLabel->"γ"]}}]]

gammacorr[Function[x,x^2],carcrop]

Image Processing : Histogram Equalization

Let' s first look at the histogram of an image: a histogram lists the frequency with which every value between 0 and 255 shows up in the image:

pic=Import["Images\\Grayscale\\car.png","Data"];
ImagePlot[pic]
flat=Flatten[pic];
ListPlot[Table[{i,Count[flat,i]},{i,0,255}],PlotRange->{{1,256},All}]

Here is a slightly fancier version from the DW.m package :

FrequencyHistogram[pic]

Here is the cumulative frequency plot  (also from the DW.m package):

CFrequency[flat]

Let' s define T(k) next :

tab=Accumulate[Table[Count[flat,i],{i,0,255}]]/Length[flat];
T[k_]:=N[tab[[k+1]]]
ListPlot[Table[{k,T[k]},{k,0,255}],ImageSize->700]

ListPlot[Table[{k,255T[k]},{k,0,255}],PlotStyle->{Blue,AbsoluteThickness[3]}, Joined->True,Epilog->{Dashed,Thick,Blue,Table[Line[{{k,0},{k,Round[255T[k]]},{0,Round[255T[k]]}}],{k,0,255,50}]},ImageSize->650,AxesLabel->{"Before Equalization","After Equalization"},BaseStyle->{Bold,14},PlotRange->{0,256}]

piceq=Round[255Map[T,pic,{2}]];
ImagePlot[piceq,PlotLabel->"Equalized Image"]

ImagePlot[pic]

Let' s compare the histograms before and after :

Grid[{{FrequencyHistogram[pic,PlotLabel->"Before Equalization"],
FrequencyHistogram[piceq,PlotLabel->"After Equalization"]}}]

The number of grayscale values in an image usually gets smaller when an image is equalized :

Print["Grayscale values before equalization: ",Length[Union[Flatten[pic]]]]
Print["Grayscale values after equalization: ",Length[Union[Flatten[piceq]]]]

A quiz: Here is a histogram for randomly chosen  integers between 0 and 255 :

FrequencyHistogram[rd=RandomInteger[{0,255},{25500}]]

What will its cumulative frequency plot look like?

CFrequency[rd]