图像处理距离变换算法

距离

定义

  满足以下函数条件
  D(p,q)>=0,当且仅当p=q时D(p,q)=0;
        D(p,q)=D(q,p)
  D(p,r)<=D(p,q)+D(q,r)

欧式距离

  D[(i,j),(k,h)]=((i-k)^2+(j-h)^2)^(1/2);

城市街区距离

  只允许横向以及纵向的移动
  D[(i,j),(k,h)]=|i-k|+|j-h|;

棋盘距离

  允许横向、纵向以及对角线上的移动
  D[(i,j),(k,h)]=max{|i-k|,|j-h|}

算法实现

步骤

  1.按照一种距离度量D,D是D4或D8,对大小为M*N的图像的一个子集S计算距离变换,建立一个M*N的数组F并作初始化:子集S中元素置为0,
    其他置为无穷。
  2.按行遍历图像,从上到下,从左到右。对于上方和左面的邻接像素设F(p)=min[F(p),D(p,q)+F(q)]。
  3.按行遍历图像,从下到上,从右到左。对于下方和右面的邻接像素设F(p)=min[F(p),D(p,q)+F(q)]。
  4.数组F中得到的是子集S的斜切。

具体函数

初始化函数
  void DistanceTransformD4(vector<vector<int>> &src, vector<vector<int>> &f)
  {
      int cols = src[0].size();
      int rows = src.size();

      //初始化
      for (int i = 0; i < rows; ++i)
      	for (int j = 0; j < cols; ++j)
      		if (src[i][j] == 1)
      		      f[i][j] = 0;
      		else
      		      f[i][j] = INT_MAX - 2;//简单的防止溢出
      //按行遍历图像,从上到下,从左到右
      for (int i = 0; i < rows; ++i)
      	for (int j = 0; j < cols; ++j)
      		D4AL(i, j, rows, cols, f);
  
      //按行遍历图像,从下到上,从右到左
      for (int i = rows - 1; i >= 0; --i)
      	for (int j = cols - 1; j >= 0; --j)
	      	D4BR(i, j, rows, cols, f);
  }
左变换函数
  void D4AL(int i,int j, int rows, int cols, vector<vector<int>> &f)
  {
      //上
      if (InArea(i - 1, j, rows, cols))
      	      f[i][j] = min(f[i][j], 1 + f[i - 1][j]);
      //左上
      if (InArea(i - 1, j - 1, rows, cols))
	      f[i][j] = min(f[i][j], 2 + f[i - 1][j - 1]);
      //左
      if (InArea(i, j - 1, rows, cols))
	      f[i][j] = min(f[i][j], 1 + f[i][j - 1]);
      //左下
      if (InArea(i + 1, j - 1, rows, cols))
	      f[i][j] = min(f[i][j], 2 + f[i + 1][j - 1]);
  }
右变换函数
  void D4BR(int i, int j, int rows, int cols, vector<vector<int>> &f)
  {
      //下
      if (InArea(i + 1, j, rows, cols))
	      f[i][j] = min(f[i][j], 1 + f[i + 1][j]);
      //右下
      if (InArea(i + 1, j + 1, rows, cols))
	      f[i][j] = min(f[i][j], 2 + f[i + 1][j + 1]);
      //右
      if (InArea(i, j + 1, rows, cols))
	      f[i][j] = min(f[i][j], 1 + f[i][j + 1]);
      //右上
      if (InArea(i - 1, j + 1, rows, cols))
	      f[i][j] = min(f[i][j], 2 + f[i - 1][j + 1]);
  }
判断是否出界函数
  bool InArea(int i, int j, int rows, int cols)
  {
        if (i<0 || i>=rows)
              return false;
        if (j<0 || j>=cols)
              return false;
        return true;
  }
posted @ 2020-07-22 11:03  luoqi123456  阅读(1773)  评论(0编辑  收藏  举报