首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Lanczos重采样错误

Lanczos重采样错误
EN

Stack Overflow用户
提问于 2013-04-04 08:57:27
回答 3查看 5.1K关注 0票数 1

我已经写了一个使用Lanczos重采样的图像大小调整程序。我直接从维基百科上的说明中获取了实现。结果在视觉上看起来很好,但由于某些原因,它与Matlab使用Lanczos调整大小的结果不太匹配(像素误差)。

有没有人看到什么错误?这根本不是我的专业领域...

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

代码语言:javascript
复制
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;
  }
}

和我调整图像大小的代码:

代码语言:javascript
复制
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;
}
EN

回答 3

Stack Overflow用户

发布于 2016-03-17 22:51:37

这是单循环中的Lanczosh。没有错误。在顶级过程中提到的用法。

代码语言:javascript
复制
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;
    }
}

}

票数 2
EN

Stack Overflow用户

发布于 2014-10-27 04:02:52

这条线

代码语言:javascript
复制
for (int i = floor_x - lanczos_size_ + 1; i < floor_x + lanczos_size_; i++)

应该是

代码语言:javascript
复制
for (int i = floor_x - lanczos_size_ + 1; i <= floor_x + lanczos_size_; i++)

不知道,但也许其他错误也挥之不去。

票数 1
EN

Stack Overflow用户

发布于 2013-08-08 22:54:44

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

编辑:我的错误,这是正确的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15800827

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档