function [ outputImg ] = isolatePlate( inputImg ) % ISOLATEPLATE Draw a box around a license plate in the input image % More info. % Params %SIZE_THRESHOLD = 60; TRUE = 1; FALSE = 0; % Show the original inputImg = im2double( inputImg ); %figure, imshow( inputImg ), title( 'Original Image' ); %%%%% Image Prep % Convert To Grayscale Using the NTSC standard red = immultiply( inputImg(:,:,1), 299 ); green = immultiply( inputImg(:,:,2), 587 ); blue = immultiply( inputImg(:,:,3), 114 ); newImg = red + green + blue; newImg = imdivide( newImg, 1000 ); % Smooth the image smoother = ones( 6, 6 ); newImg = imfilter( newImg, smoother ); newImg = imdivide( newImg, 36 ); %figure, imshow( newImg ), title( 'Grayscale Image' ); flipImg = rot90( newImg ); % create a new light gray image so we can see the boxes. lightGray = imdivide( newImg, 4 ); lightGray = imadd( lightGray, 0.749 ); % % Find the center of the red data, to find the column that the license % % plate should cross % % scaledRed = mat2gray( red ); % scaledBlue = mat2gray( blue ); % scaledGreen = mat2gray( green ); % % % threadhold the red values... % redMap = scaledRed > 0.30 & scaledGreen < 0.40 & scaledBlue < 0.40; % % se = strel( 'disk', 5 ); % redMap = imclose( redMap, se ); % % [row,column] = find( redMap ); % redColumn = sum( column ) / size( column, 1 ); % redRow = sum( row ) / size( row, 1 ); % % figure, imshow( imcomplement( redMap ) ), title( 'Red Map' ); % rectangle( 'Position', [ redColumn 1 1 size( red, 1 ) ] ); % rectangle( 'Position', [ 0 redRow size( red, 2 ) 1 ] ); %%%%% Vertical Edge Detection % Create our mask - a Sobel for vertical edge detection mask = fspecial( 'sobel' ); mask = rot90( mask, 1 ); % Do the actual detection vEdges = imfilter( newImg, mask ); hEdges = rot90( imfilter( flipImg, mask ), -1 ); vEdgesScaled = immultiply( vEdges, 0.7 ); hEdgesScaled = immultiply( hEdges, 0.3 ); edges = imadd( vEdgesScaled, hEdgesScaled ); % Show what we have so far %figure, imshow( vEdges ), title( 'Vertical Edges' ); %figure, imshow( hEdges ), title( 'Horizontal Edges' ); %figure, imshow( edges ), title( 'Edges' ); %%%%% Edge Density Map Generation % Create our mask of ones to add up the edge values %densityMask = ones( 3, 15 ); densityMask = ones( 3, 15 ); % Sum it up edgeMap = imfilter( edges, densityMask ); edgeMap = imdivide( edgeMap, 45 ); % Show what we have so far %figure, imshow( edgeMap ), title( 'Edge Map' ); %%%%% Binarization / Clean Up / Dilation % Binarize!!!! Use Otsu's Method. It's fast. level = graythresh( edgeMap ); binary = im2bw( edgeMap, level ); % Show what we have so far %figure, imshow( binary ), title( 'Binarized Edge Map' ); % Clean Up by getting rid of small horizontal lines se = strel( 'disk', 2 ); cleanImage = imopen( binary, se ); % Show what we have so far %cleanImage = binary; % skipping the clean up step...don't seem to need it %figure, imshow( cleanImage ), title( 'Cleaned Image' ); % Dilate the Image %se = ones( 1, 9 ); %se = ones( 100, 100 ); se = strel( 'disk', 13 ); dilated = imdilate( cleanImage, se ); % Show what we have so far %figure, imshow( dilated ), title( 'Dilated Image' ); %%%%% License Plate Location % find all the 8-connected regions in the dilated binary image [labeled, num] = bwlabel( dilated ); % Feature Extraction % here we will loop through the dilated image... info = []; imgWidth = size( newImg, 2 ); imgHeight = size( newImg, 1 ); for k = 1:1:num % get the indices of one connected region (current k value for this % iteration) [row,column] = find( labeled == k ); % get the top left row&column topLeftRow = min( row ); topLeftColumn = min( column ); % BR row&column bottomRightRow = max( row ); bottomRightColumn = max( column ); % get the size of...yeah... numPixels = size( row, 1 ); % numbers! width = bottomRightColumn - topLeftColumn + 1; height = bottomRightRow - topLeftRow + 1; % Check whether the box is within another box % structure of each row: TL row, TL col, BR row, BR col, numpixels, % width, height. Note that it's 7 columns... newRow = [ topLeftRow topLeftColumn bottomRightRow bottomRightColumn numPixels width height ]; % add it to our dater structure to store it! ratio = width / height; area = width * height; % check aspect ratio if ( ratio > 1.3 & ratio < 2.35 ) % check min. size through area if ( area > 16000 ) % check max size through percent of image if ( width < 0.7 * imgWidth & height < 0.7 * imgHeight ) info = cat( 1, info, newRow ); end end end end %%%% If we still have more than one box, then try to filter some more sums = []; if ( size( info, 1 ) > 1 ) % Take a slice of the remaining boxes sliceHeight = 4; sliceImg = zeros( size( inputImg, 1 ), size( inputImg, 2 ) ); for k = 1:1:size( info, 1 ) row = info( k, : ); sliceWidth = row( 6 ); sliceX = row( 2 ); sliceY = ( row( 7 ) / 2 ) - ( sliceHeight / 2 ) + row( 1 ); sliceImg( sliceY:sliceY + sliceHeight, sliceX:sliceX + sliceWidth ) = 1; % sum up what's in our slice slice = vEdges( sliceY:sliceY + sliceHeight, sliceX:sliceX + sliceWidth ); slice = slice > graythresh( slice ); figure, imshow( slice ); edgeResponse = sum( sum( slice ) ); sums = cat( 1, sums, edgeResponse ); end sliceImg = immultiply( double( sliceImg ), vEdges ); figure, imshow( sliceImg ), title( 'Slices' ); %%%% Filter based on slices [ component, index ] = max( sums ); info sums component index info = info( index, : ); end %%%% Draw our boxes that we have left figure, imshow( inputImg ), title( 'Original Image - With Boxes' ); for k = 1:1:size( info, 1 ) row = info( k, : ); % 1 2 3 4 5 6 7 % [ topLeftRow topLeftColumn bottomRightRow bottomRightColumn numPixels width height ]; % rectangle( 'Position', [ row( 2 ) row( 1 ) row( 6 ) row( 7 ) ] ); inputImg = drawrectangle( inputImg, row( 2 ), row(1), row( 6 ), row(7), 1, 0, 0 ); end % now return the processed image... outputImg = inputImg;