1

我已经使用 Lanczos 重新采样编写了一个图像缩放器。我直接从 wikipedia 上的说明进行了实施。结果在视觉上看起来不错,但由于某种原因,它与 Matlab 使用 Lanczos 调整大小的结果不匹配(像素错误)。

有人看到任何错误吗?这根本不是我的专业领域...

这是我的过滤器(我默认使用 Lanczos3):

double lanczos_size_ = 3.0;
inline double sinc(double x) {
  double pi = 3.1415926;
  x = (x * pi);
  if (x < 0.01 && x > -0.01)
    return 1.0 + x*x*(-1.0/6.0 + x*x*1.0/120.0);
  return sin(x)/x;
}

inline double LanczosFilter(double x) {
  if (std::abs(x) < lanczos_size_) {
    double pi = 3.1415926;
    return sinc(x)*sinc(x/lanczos_size_);
  } else {
    return 0.0;
  }
}

还有我调整图像大小的代码:

Image Resize(Image& image, int new_rows, int new_cols) {
  int old_cols = image.size().cols;
  int old_rows = image.size().rows;
  double col_ratio =
      static_cast<double>(old_cols)/static_cast<double>(new_cols);
  double row_ratio =
      static_cast<double>(old_rows)/static_cast<double>(new_rows);

  // Apply filter first in width, then in height.
  Image horiz_image(new_cols, old_rows);
  for (int r = 0; r < old_rows; r++) {
    for (int c = 0; c < new_cols; c++) {
      // x is the new col in terms of the old col coordinates.
      double x = static_cast<double>(c)*col_ratio;
      // The old col corresponding to the closest new col.
      int floor_x = static_cast<int>(x);

      horiz_image[r][c] = 0.0;
      double weight = 0.0;
      // Add up terms across the filter.
      for (int i = floor_x - lanczos_size_ + 1; i < floor_x + lanczos_size_; i++) {
        if (i >= 0 && i < old_cols) {
          double lanc_term = LanczosFilter(x - i);
          horiz_image[r][c] += image[r][i]*lanc_term;
          weight += lanc_term;
        }
      }
      // Normalize the filter.
      horiz_image[r][c] /= weight;
      // Strap the pixel values to valid values.
      horiz_image[r][c] = (horiz_image[r][c] > 1.0) ? 1.0 : horiz_image[r][c];
      horiz_image[r][c] = (horiz_image[r][c] < 0.0) ? 0.0 : horiz_image[r][c];
    }
  }

  // Now apply a vertical filter to the horiz image.
  Image new_image(new_cols, new_rows);
  for (int r = 0; r < new_rows; r++) {
    double x = static_cast<double>(r)*row_ratio;
    int floor_x = static_cast<int>(x);
    for (int c = 0; c < new_cols; c++) {      
      new_image[r][c] = 0.0;
      double weight = 0.0;
      for (int i = floor_x - lanczos_size_ + 1; i < floor_x + lanczos_size_; i++) {
        if (i >= 0 && i < old_rows) {
          double lanc_term = LanczosFilter(x - i);
          new_image[r][c] += horiz_image[i][c]*lanc_term;
          weight += lanc_term;
        }
      }
      new_image[r][c] /= weight;
      new_image[r][c] = (new_image[r][c] > 1.0) ? 1.0 : new_image[r][c];
      new_image[r][c] = (new_image[r][c] < 0.0) ? 0.0 : new_image[r][c];
    }
  }
  return new_image;
}
4

3 回答 3

2

这是一个循环中的 Lanczosh。没有错误。顶部程序中提到的用途。

void ResizeDD(
double* const pixelsSrc, 
const int old_cols, 
const int old_rows,
double* const pixelsTarget, 
int const new_rows, int const new_cols)
{
double col_ratio =
    static_cast<double>(old_cols) / static_cast<double>(new_cols);
double row_ratio =
    static_cast<double>(old_rows) / static_cast<double>(new_rows);

// Now apply a filter to the image.
for (int r = 0; r < new_rows; ++r)
{
    const double row_within = static_cast<double>(r)* row_ratio;
    int floor_row = static_cast<int>(row_within);
    for (int c = 0; c < new_cols; ++c)
    {
        // x is the new col in terms of the old col coordinates.
        double col_within = static_cast<double>(c)* col_ratio;
        // The old col corresponding to the closest new col.
        int floor_col = static_cast<int>(col_within);

        double& v_toSet = pixelsTarget[r * new_cols + c];
        v_toSet = 0.0;
        double weight = 0.0;
        for (int i = floor_row - lanczos_size_ + 1; i <= floor_row + lanczos_size_; ++i)
        {
            for (int j = floor_col - lanczos_size_ + 1; j <= floor_col + lanczos_size_; ++j)
            {
                if (i >= 0 && i < old_rows && j >= 0 && j < old_cols)
                {
                    const double lanc_term = LanczosFilter(row_within - i + col_within - j);
                    v_toSet += pixelsSrc[i * old_rows + j] * lanc_term;
                    weight += lanc_term;
                }
            }
        }

        v_toSet /= weight;
        v_toSet = (v_toSet > 1.0) ? 1.0 : v_toSet;
        v_toSet = (v_toSet < 0.0) ? 0.0 : v_toSet;
    }
}

}

于 2016-03-17T14:51:37.410 回答
1

线

for (int i = floor_x - lanczos_size_ + 1; i < floor_x + lanczos_size_; i++)

应该

for (int i = floor_x - lanczos_size_ + 1; i <= floor_x + lanczos_size_; i++)

不知道,但也许还有其他错误。

于 2014-10-26T20:02:52.053 回答
0

我认为您的 sinc 函数有错误。在分数栏下方,您必须平方 pi 和 x。另外,您必须将函数与 lanczos 大小相乘 L(x) = **a***sin(pi*x)*sin(pi*x/a) * (pi**²**x**²**)^-1

编辑:我的错,没关系。

于 2013-08-08T14:54:44.063 回答