A quick overview of the morphological operators
, where is the image, and is the structuring element.
Solution to the assignments from the book:
This exercise aims to provide the necessary knowledge in order to work effectively withmorphological operations in Matlab. First, take a look at the help pages in Matlab and search for morphology and get a list of all available morphology Matlab operations. In the following exercises we will use the image circles.png as example image. BW = imread('circles.png'); Take a look at it with imshow(BW);
clear all close all % Loading image BW = imread('circles.png'); figure(1) imshow(BW) title('Original image of circles'); drawnow();
Image boundary Find the boundary of the circles by using the function imerode. Then you first have to design a structure element by using strel. Make two structure elements, the first should be a disk with radius 1 and the second with radius 4. What is the result of using the different structure elements?
% Let's first try a structuring image of a disk with radius 1. SE = strel('disk', 1); se = getnhood(SE); %To get the actual image figure(2) subplot(121) imshow(se,); title('Disk size 1 structure'); subplot(122) imshow(BW - imerode(BW,SE)) title('Boundary using size 1 strl'); drawnow(); % A structuring image of a disk with radius 4. figure(3) subplot(121) SE = strel('disk',4); se = getnhood(SE); %To get the actual image imshow(se); title('Disk size 4 structure'); subplot(122) imshow(BW - imerode(BW,SE)) title('Boundary using size 4 strl');
Image skeleton Then find the skeleton of the image BW by using bwmorph. The resulting image is noisy and not what we want, how can we improve it using bwmorph? Hint: use a function iteratively
figure(4) imshow(BW); title('Original image'); drawnow(); figure(5); imshow(bwmorph(BW, 'skel',10)); title('Skeleton after 10 operations'); drawnow(); figure(6); imshow(bwmorph(BW, 'skel',inf)); title('Skeleton used iteratively'); drawnow(); figure(7); imshow(bwmorph(BW, 'thin', Inf)); title('Image thinned'); drawnow();
Finding image patterns by hit-and-miss Generate an image by: I = checkerboard(10,10,10); I=abs((I<1)-1); and take a look at it. bwhitmiss(BW1,INTERVAL) performs the hit-and-miss operation defined in terms of a single array, called an interval o the image BW1. An interval is an array whose elements can contain 1, 0, or -1. The 1-valued elements make up the domain of SE1, the -1-valued elements make up the domain of SE2, and the 0-valued elements are ignored. The syntax bwhitmiss(INTERVAL) is equivalent to bwhitmiss(BW1,INTERVAL == 1, INTERVAL == -1).
%Lets make the image I = checkerboard(10,10,10); I = abs((I<1)-1); figure(7);clf imshow(I) title('Checkerboard image'); drawnow(); interval = [ 0 -1 -1 ; ... 1 1 -1 ; ... 0 1 0 ];
Answer this question before you test it: Which structure do you detect by performing a hit and miss with this interval on the image I?
- Corners (in 4-connectivity).
figure(8) imagesc(interval); colormap gray; colorbar title('The interval'); drawnow(); pause(0.5); figure(88) imshow(bwhitmiss(I, interval)) title('Hit-and-miss'); drawnow();
- Yes. What happens in the middle of the chessboard pattern? - No detection, but these ain't corners in the normal sense. How should the interval be designed in order to detect all the wanted patterns?
interval = [ 0 -1 0 ; ... 1 1 -1 ; ... 0 1 0 ]; figure(9) imagesc(interval); colormap gray; colorbar title('A different interval'); drawnow(); pause(0.5); figure(99) imshow(bwhitmiss(I, interval)) title('Hit-and-miss'); drawnow();
In inspection of electronic circuit cards there is a need to inspect the number of holes and the diameter of the holes, see figure below. We want to measure the number of holes and the diameter using morphology. Use the morphology operators in Matlab to solve the exercise. The image pcb.jpg can be downloaded from ~inf3300/www_docs/bilder/pcb.jpg (then it can be reached on the web at http://www.ifi.uio.no/~inf3300/bilder/pcb.jpg) Tip: One solution is to use the Matlab functions imfill and regionprops
clear all close all I = imread('pcb.jpg'); %Let's look at the image figure(10) subplot(121) imshow(I) title('Original'); subplot(122) imhist(I(:,:,1)) % JPEG compression error title('Histogram'); % Let's clean it into an actually binary image figure(11) BW = I(:,:,1) > 127; subplot(121) imshow(BW); title('BW image'); subplot(122) imhist(BW); title('Histogram'); drawnow();
Let's try out the hint and use the imfill function.
BW_filled = imfill(BW,'holes'); figure(12) imshow(BW_filled) title('BW after imfill'); drawnow();
The difference will leave us with only the holes
BW_holes = logical(BW_filled - BW); figure(13);clf imshow(BW_holes) title('The difference between BW and BW\_filled') drawnow();
Then we can use regionprops to estimate the diameter
figure(13);clf imshow(BW_holes) title('The holes with diameter') hold on; stats = regionprops(BW_holes, 'Area', 'Centroid'); min_radius = Inf; max_radius = -Inf; for k = 1:length(stats) %Calculate the radius and plot the diameter on the image radius = sqrt(stats(k).Area/pi); min_radius = min(min_radius, radius); max_radius = max(max_radius, radius); centroid = stats(k).Centroid; plot(centroid(1),centroid(2),'ko'); text(centroid(1)+2, centroid(2), sprintf('%.1f',2*radius) ,'Color', 'r', 'FontSize', 24, 'FontWeight', 'bold'); end drawnow();
Experiment with using either top hat or bottom hat as preprocessing before applying global thresholding to the image ~inf3300/www_docs/bilder/morf_test.png. The images contain letters on a very noisy background with varying illumination. Try to estimate a good estimate of the background, and subtract the estimated background from the original. Then try to use global thresholding on the resulting image. Do you also need a noise filter? Can you segment out the numbers fairly well? Also consider if there are gaps or connected symbols that you can improve by applying simple binary morphology operations.
clear all close all I = imread('morf_test.png'); figure(1) imshow(I,) title('Original'); drawnow(); figure(11) imshow(im2bw(I,graythresh(I))) title('Tresholded'); drawnow(); % We see that a simple graytreshold is not doing the trick
Let's try to estimate the backtround by using imcloseing with a structuring element
background = imclose(I, strel('disk', 5)); figure(2) imshow(background) title('The background'); drawnow(); I2 = background - I; figure(22) imshow(I2, ) title('The background subtracted the image'); drawnow(); figure(23) imshow(imbothat(I, strel('disk', 5)),) % the same title('Which is the same as a bottomhat'); drawnow();
Let's do another treshold to clean up a bit
figure(3) BW = im2bw(I2, graythresh(I2)); imshow(BW) title('Tresholded image to clean up a bit'); drawnow();
Remove all objects that are less than 5 pixels
figure(4) BW = bwareaopen(BW, 5); imshow(BW) drawnow(); figure(5); imshow(I,); title('Original'); drawnow(); figure(6); imshow(1-BW,); title('Cleaned up'); drawnow(); % Suggestion to further processing: % 1. Rotate back, for example imrotate() % 2. Apply some closings with line SE, e.g. horisontal, vertical and +-45 degrees. % 3. Opening with vertical line SE. % I'll let you have some fun. Maybe you could also use regionprops to for % example find all zeros?? % post_id = 692; %delete this line to force new post; % permaLink = http://inf4300.olemarius.net/2015/11/19/exercise-m-3/;