局部预处理之使用旋转掩膜平均
介绍
本节主要介绍图像平滑方法使用旋转掩膜的平均的算法
基本理论
使用旋转掩膜技术的图像平滑算法如下:
1. 考虑图像的每个像素(i,j)
2.根据式计算像素(i,j)所有可能的旋转掩膜的散步;
3.选择具有最小散布的掩膜。
4.将所选掩膜内的平均亮度赋给输出图像中的像素(i,j)。
使用旋转掩膜的平均(averaging using a rotating mask)是一种非线性的平滑方法,它通过搜索当前像素邻域的同态部分,可以避免边缘模糊。其结果实际上是锐化图像。亮度的平均只在这个区域计算,一个亮度散布用作区域一致性度量。设区域R的像素数目是n且输入图像是g.散布如下计算:
式(5.29)的散布计算的计算复杂度经如下改写后可以减少:
计算出了区域一致性,我们来考虑形态和大小。如图5.11 给出了3x3的掩膜的8种可以的旋转,覆盖了当前像素的一个5x5的邻域。第9个掩膜是当前像素自身的一个3x3邻域。也可以使用其他掩膜形态。图5.12给出了覆盖了当前像素的一个5x5的邻域的另一给8个掩膜。第9个掩膜还是当前像素自身的一个3x3邻域。另一种可能性是旋转一个小的2x1模板覆盖当前像素的3x3邻域。
另一种可能是,旋转一个小的2x1模板,以覆盖当前像素的3x3邻域。
使用旋转掩膜技术的图像平滑算法
算法:使用旋转掩膜的平均
- 1.考虑图像的每个像素(i,j).
- 2.根据(5.29)式计算像素(i,j)所有可能的旋转掩膜的散布.
- 3.选择具有最小散布的掩膜.
- 4.将所选掩膜内的平均亮度赋给输出图像中的像素(i,j).
此算法可以迭代地使用,迭代过程会相当快地收敛到一个稳定状态。掩膜的大小和形态影响收敛速度。
Matlab代码
- % Usage: im_out = rotmask(im,method,datatype)
- % Outputs: im_out [m x n] Filtered image.
- if nargin<3
- datatype = 'double';
- end
- if nargin<2
- method = 'vectorized';
- end
- imdatatype = class(im);
- VECTORIZED = strcmp(lower(method),'vectorized');
- INTEGRAL = strcmp(lower(method),'integral');
- LOOP = strcmp(lower(method),'loop');
- if size(im,3)>1
- error('rot_mask does not work for full-colour images')
- end
- mask_size = 9; % size of the rotating mask
- mask=logical(zeros(5,5,mask_size));
- im = double(im);
- im_out = zeros(size(im));
- if INTEGRAL
- im_integral = feval( datatype, integralim(im) );
- imsquare_integral = feval( datatype, integralim(im.^2) );
- mask = zeros(2,4,9);
- mask(:,:,1) = [-3 -3 0 0; -1 2 -1 2];
- mask(:,:,2) = [-3 -3 0 0; -2 1 -2 1];
- mask(:,:,3) = [-3 -3 0 0; -3 0 -3 0];
- mask(:,:,4) = [-2 -2 1 1; -3 0 -3 0];
- mask(:,:,5) = [-1 -1 2 2; -3 0 -3 0];
- mask(:,:,6) = [-1 -1 2 2; -2 1 -2 1];
- mask(:,:,7) = [-1 -1 2 2; -1 2 -1 2];
- mask(:,:,8) = [-2 -2 1 1; -1 2 -1 2];
- mask(:,:,9) = [-2 -2 1 1; -2 1 -2 1];
- im_int_mat = zeros( 4,(size(im,1)-4)*(size(im,2)-4), 9,class(im_integral));
- im_sq_mat = zeros( 4,(size(im,1)-4)*(size(im,2)-4), 9,class(imsquare_integral));
- row_pos = 3 : size(im,1)-2;
- col_pos = 3 : size(im,2)-2;
- for i = 1:9
- for j = [1 4] % for each of the +corner
- row_mask_pos = row_pos(1)+mask(1,j,i)+1 : row_pos(end)+mask(1,j,i)+1;
- col_mask_pos = col_pos(1)+mask(2,j,i)+1 : col_pos(end)+mask(2,j,i)+1;
- im_int_mat(j,:,i) = ...
- reshape(im_integral(row_mask_pos,col_mask_pos),1,size(im_int_mat,2));
- im_sq_mat(j,:,i) = ...
- reshape(imsquare_integral(row_mask_pos,col_mask_pos),1,size(im_sq_mat,2));
- end
- for j = [2 3]
- row_mask_pos = row_pos(1)+mask(1,j,i)+1 : row_pos(end)+mask(1,j,i)+1;
- col_mask_pos = col_pos(1)+mask(2,j,i)+1 : col_pos(end)+mask(2,j,i)+1;
- im_int_mat(j,:,i) = ...
- -reshape(im_integral(row_mask_pos,col_mask_pos),1,size(im_int_mat,2));
- im_sq_mat(j,:,i) = ...
- -reshape(imsquare_integral(row_mask_pos,col_mask_pos),1,size(im_sq_mat,2));
- end
- end
- sums = squeeze( sum(im_int_mat,1) )';
- means = sums./mask_size;
- sums_squares = squeeze( sum(im_sq_mat,1) )';
- variances = mask_size*(means.^2) + sums_squares - 2*means.*sums;
- [foo,idx_mins] = min(variances);
- im_filt = means(sub2ind(size(means),idx_mins,[1:size(means,2)]));
- im_filt = reshape( im_filt, length(row_mask_pos), length(col_mask_pos) );
- im_out(3:end-2,3:end-2) = im_filt;
- else % VECTORIZED and LOOP methods loop over (almost) all pixels in image
- basic_shape = 1;
- mask(1:3,3:5,1) = basic_shape;
- mask(1:3,2:4,2) = basic_shape;
- mask(2:4,2:4,9) = basic_shape;
- for i = 3:8
- mask(:,:,i) = rot90( mask(:,:,i-2) );
- end
- variances = zeros(1,9);
- for i = 3:size(im,1)-2
- for j = 3:size(im,2)-2
- if VECTORIZED
- sub_mat = im( i-2:i+2, j-2:j+2, ones(9,1) );
- sub_mat = reshape( sub_mat(mask), mask_size, 9 );
- means = sum(sub_mat)/mask_size;
- variances = sum( (sub_mat-means(ones(mask_size,1),:)).^2 );
- [min_disp,idx_min] = min(variances);
- im_out(i,j) = means(idx_min);
- elseif LOOP
- sub_im = im( i-2:i+2, j-2:j+2 );
- for m = 1:9
- vec = sub_im( mask(:,:,m) );
- variances(m) = sum( (vec-sum(vec)/mask_size).^2 );
- end
- [min_disp,idx_min] = min(variances);
- im_out(i,j) = sum( sub_im(mask(:,:,idx_min)) ) / mask_size;
- else
- error('Unknown method');
- end
- end % for columns
- fprintf( 1, '\b\b\b\b\b\b\b\b %05.2f %%', 100*(i-2)/(size(im,1)-2) );
- end % for rows
- fprintf(1,'\b\b\b\b\b\b\b\b %05.2f %% \n',100)
- end % if INTEGRAL
- if strcmp(imdatatype,'uint8')
- im_out = uint8(round(im_out));
- end
- if strcmp(imdatatype,'uint16')
- im_out = uint16(round(im_out));
- end
- if strcmp(imdatatype,'double') | strcmp(imdatatype,'single')
- im_out = im_out/255;
- end
- return; % end of rotmask
测试输出结果
原始图像如下所示:
输出图像如下所示:
参考文献
[1] Svoboda T.nKybic J., and Hlavac V. "Image Processing Analysis and Machine Vision" Thomson Engineering 2008.