meanshift图像分割实例matlab程序(支持高斯核和Epanechnikov核)

本来不想写这篇文章的,因为代码只是对CSDN上一篇博客(https://blog.csdn.net/full_speed_turbo/article/details/83181982)上的程序做了小小的改动,不敢掠人之美。不过原博客大概由于没有给出中文注释和处理结果图像而似乎并没有受到应有的关注。故而纠结了几天,最后还是决定在这里给出改动后的版本以助其发扬光大,同时希望能帮助到有需要的人。

基于meanshift的图像分割函数:

function l=meanshift(im,hs,hr,err,kernelType) 
% MEANSHSEGM Mean shift segmentation
% CMP Vision Algorithms http://visionbook.felk.cvut.cz
%  
% Segment a grayscale or color image using mean shift image segmentation
% Warning: Segmenting a medium-size image (200x 300 pixels)
% takes a couple of minutes and the time increases with
% the image and kernel size.  
%
% Usage: l = meanshsegm(im,hs,hr)
%  im   [m x n x d]  Scalar (d=1) or color (d=3) input image.
%  hs  (default 10)
%      Spatial kernel size, in pixels.
%  hr  (default 20 for gaussian kernel and default 40 for Epanechnikov kernel)
%      Range kernel size.
% err  (default 0.2)
% norm of error which determine when to stop iteration
% kernelType (default 'gaussian')
% 'gaussian' for gaussian kernel, 'Epan' for Epanechnikov kernel
% l  [m x n]  Output labeling. Each pixel position contains an integer
%  1... N corresponding to an assigned region number; N is the
%  number of regions.
  
% 设置默认参数
if ~exist('kernelType','var')
    kernelType='gaussian'
end

if ~exist('hs','var')
    hs=15;
end

if ~exist('hr','var')
    if strcmp(kernelType,'gaussian')==1
        hr=20;
    else
        hr=40;
    end
end

if ~exist('err','var')
    err=0.2;
end

% 构造空域-值域联合尺度因子
[m,n,d] = size(im);
h  = [hs hs repmat(hr,1,d)];
z  = zeros( m, n, d+2 );
im = double(im);

% 对每个像素点进行均值移位
for ix = 1:n
  for iy = 1:m
    % 构造当前点空域-值域联合特征向量     
    y = double( [ix iy reshape(im(iy,ix,:),1,d)] );
    % 构造邻域像素点的空域-值域联合特征向量(组合成矩阵)  
    xl = max(ix-hs,1);  xh = min(ix+hs,n);  nw = xh-xl+1;
    yl = max(iy-hs,1);  yh = min(iy+hs,m);  mw = yh-yl+1;
    nw = nw*mw;  iw = (0:(nw-1))';
    fw = [fix(iw/mw+xl) mod(iw,mw)+yl reshape(im(yl:yh,xl:xh,:),[],d)];

    while true
      r = (fw-repmat(y,nw,1)) ./ repmat(h,nw,1);
      rs = sum( r.*r, 2 );

      if strcmp(kernelType,'gaussian')==1
          w=exp(-rs/2);
      else
          w=1-rs;
          w(w<0)=0;
      end
      y0 = y;
      y = w'*fw/sum(w);
      if norm(y-y0)<err, break; end
    end
    z(iy,ix,:) = y;
  end % for iy
end % for ix

% 使用超像素技术根据像素对的连接关系构造连通域
% 对应原始像素点的网格点值设为1,其余设为0
% 若水平、垂直像素对的特征量各维度均小于对应尺度值,则将对应网格点的值设为1
s = ones( 2*m+1, 2*n+1, 'int8' );
s(1:2:(2*m+1),:) = zeros( m+1, 2*n+1, 'int8' );
s(:,1:2:(2*n+1)) = zeros( 2*m+1, n+1, 'int8' );

s(2:2:2*m,3:2:(2*n-1)) = all(cat(3, ...                % horizontal edges
  abs(z(:,2:end,1:2)-z(:,1:(end-1),1:2)) < hs, ...
  abs(z(:,2:end,3:end)-z(:,1:(end-1),3:end)) < hr ),3);
s(3:2:(2*m-1),2:2:2*n) = all(cat(3, ...                % vertical edges
  abs(z(2:end,:,1:2)-z(1:(end-1),:,1:2)) < hs, ...
  abs(z(2:end,:,3:end)-z(1:(end-1),:,3:end)) < hr ),3);

% 连通域标记
l = bwlabel( s, 4 );                                   % find connected regions
l = l( 2:2:2*m, 2:2:2*n );                             % extract labeling

脚本文件:

% MEANSHSEGM_DEMO Demo showing the usage of meanshsegm 
% CMP Vision algorithms http://visionbook.felk.cvut.cz
% Example

clear all;close all;clc;
ImageDir='images/';%directory containing the images
% addpath('..') ;
% cmpviapath('..') ;
if (exist('output_images')~=7)
  mkdir('output_images');
end

if 1
img=imresize(imread([ImageDir 'onion.png']),0.5) ;
l=meanshift(img,15,20,0.1,'gaussian') ;
% l=meanshift(img,15,40,0.1,'Epan') ;

figure;
imagesc(img); % title('input image');
axis image ; axis off ; 

figure; 
imagesc(label2rgb(l-1,'jet','w','shuffle')) ; 
axis image ; axis off ; 
end

F=getframe(gcf);
I=frame2im(F);
[I,map]=rgb2ind(I,256);
imwrite(I,map,'r.png')

原图:

使用gaussian核采用默认值处理结果:

使用Epanechnikov核采用默认值处理结果:

 

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
以下是基于mean shift图像分割实例matlab程序: ```matlab clc;clear all;close all; % 读取图像 I = imread('test.jpg'); figure;imshow(I);title('原始图像'); % 转换为L*a*b*颜色空间 cform = makecform('srgb2lab'); lab_I = applycform(I,cform); % 归一化 ab = double(lab_I(:,:,2:3)); nrows = size(ab,1); ncols = size(ab,2); ab = reshape(ab,nrows*ncols,2); % mean shift 算法 [cluster_idx, ~] = mean_shift(ab',2); % 重构图像 pixel_labels = reshape(cluster_idx,nrows,ncols); segmented_images = cell(1,max(cluster_idx)); rgb_label = repmat(pixel_labels,[1 1 3]); for i = 1:max(cluster_idx) color = I; color(rgb_label ~= i) = 0; segmented_images{i} = color; end % 显示分割结果 figure; subplot(2,2,1);imshow(segmented_images{1});title('分割1'); subplot(2,2,2);imshow(segmented_images{2});title('分割2'); subplot(2,2,3);imshow(segmented_images{3});title('分割3'); subplot(2,2,4);imshow(segmented_images{4});title('分割4'); ``` 解释: 1. 读取图像; 2. 将图像转换为 L*a*b* 颜色空间; 3. 归一化; 4. 使用 mean shift 算法进行图像分割; 5. 重构图像; 6. 显示分割结果。 其中,第4步中的 mean shift 算法可以使用如下的函数实现: ```matlab function [cluster_idx, cluster_center] = mean_shift(X,bandwidth) % 使用 mean shift 算法进行聚类 % % 输入参数: % X:数据矩阵,每一列代表一个数据点 % bandwidth:函数带宽 % % 输出参数: % cluster_idx:聚类标签 % cluster_center:聚类中心 % % 作者:hanchen % 时间:2018年5月2日 if nargin < 2 error('请指定函数带宽'); end [m,n] = size(X); num_iter = 5; % 初始化 cluster_center = X; for i = 1:num_iter disp(['mean shift 迭代次数:',num2str(i)]); % 计算距离矩阵 dist_mat = pdist2(X',cluster_center'); % 计算函数 kernel_val = exp(-dist_mat.^2/(2*bandwidth^2)); % 计算均值偏移向量 shift_vec = sum(repmat(kernel_val,[n,1]).*X',2)./sum(kernel_val,2); % 更新聚类中心 cluster_center = shift_vec'; end % 计算聚类标签 dist_mat = pdist2(X',cluster_center'); [~,cluster_idx] = max(dist_mat,[],2); ``` 该函数的实现方式如下: 1. 输入数据矩阵 X 和函数带宽 bandwidth; 2. 进行 5 次 mean shift 迭代; 3. 计算距离矩阵; 4. 计算函数; 5. 计算均值偏移向量; 6. 更新聚类中心; 7. 计算聚类标签。 最终输出聚类标签和聚类中心。 希望能够帮助到你。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值