Tutorial · Intermediate · 10 min
Working with images
Read an image, look at its pixels and colour channels, clean it up with filters, find edges, fix its contrast and count the objects in it.
An image is an array
A colour image is rows × columns × 3: red, green and blue layers of whole numbers from 0 to 255 (
uint8).testimagegives built-in pictures to practise on; your own photos come in with Import andimread.
Try it ↗I = testimage('shapes'); size(I) class(I) pixel = I(40, 70, :) % one pixel: red, green, blue imshow(I)Tip: Import a JPEG or PNG with the Import button, then I = imread('yourphoto.jpg'). Web images work too: imread('https://…/picture.png').
Grey levels and arithmetic
rgb2graycombines the channels into one grey layer. Arithmetic onuint8stays between 0 and 255, soI + 80brightens without overflowing;im2doubleswitches to 0–1 for calculations.
Try it ↗G = rgb2gray(testimage('shapes')); subplot(1, 3, 1), imshow(G), title('grey') subplot(1, 3, 2), imshow(G + 80), title('G + 80') subplot(1, 3, 3), imshow(im2double(G).^3), title('im2double(G).^3')Filters
A filter replaces every pixel by a weighted mix of its neighbours.
fspecialmakes common kernels,imfilterapplies them;medfilt2takes the median instead, which removes speckles but keeps edges.
Try it ↗rng(2) G = imnoise(rgb2gray(testimage('shapes')), 'salt & pepper', 0.05); subplot(1, 3, 1), imshow(G), title('noisy') subplot(1, 3, 2), imshow(imfilter(G, fspecial('gaussian', 7, 1.5))), title('Gaussian') subplot(1, 3, 3), imshow(medfilt2(G)), title('median')Edges
edgemarks where brightness changes quickly. Sobel is fast; Canny smooths first, thins the edges to one pixel and links them, so it gives cleaner outlines.
Try it ↗G = rgb2gray(testimage('noisy')); subplot(1, 2, 1), imshow(edge(G, 'sobel')), title('Sobel') subplot(1, 2, 2), imshow(edge(G, 'canny')), title('Canny')Histogram and contrast
imhistcounts how many pixels have each grey level. A narrow histogram means low contrast;imadjuststretches it,histeqflattens it.
Try it ↗G = imgaussfilt(rgb2gray(testimage('noisy')), 1); dull = uint8(100 + 0.25 * double(G)); subplot(2, 2, 1), imshow(dull), title('dull') subplot(2, 2, 2), imshow(imadjust(dull)), title('imadjust') subplot(2, 2, 3), imhist(dull) subplot(2, 2, 4), imhist(imadjust(dull))Count and measure
Threshold to black and white (
imbinarize), tidy up with morphology (imopen,imfill), thenbwlabelnumbers the regions andregionpropsmeasures them. In MathLab each measurement is a column:s.Area,s.Centroid.
Try it ↗rng(5) BW = imfill(imopen(imbinarize(testimage('blobs')), strel('disk', 2)), 'holes'); s = regionprops(BW, 'Area', 'Centroid'); imshow(BW), hold on plot(s.Centroid(:, 1), s.Centroid(:, 2), 'r+', 'MarkerSize', 10), hold off title(sprintf('%d regions, median area %.0f pixels', s.Count, median(s.Area)))