2013-04-04 68 views
1

我已經使用Lanczos重新採樣編寫了一個圖像調整器。我已經從維基百科的方向直接執行了這個實現。結果看起來不錯,但由於某種原因,它與Matlab的調整大小與Lanczos的結果不相符(像素誤差)。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; 
} 

回答

0

我認爲你的sinc函數有一個錯誤。在分數條下方,你必須平方pi和x。此外,你必須乘以lanczos尺寸的功能 L(x) = **a***sin(pi*x)*sin(pi*x/a) * (pi**²**x**²**)^-1

編輯:我的錯,有一切。

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++) 

不知道,但也許還有其他的錯誤流連忘返了。

2

這是Lanczosh在一個單一的循環。沒有錯誤。 在頂級程序中提到的用法。

空隙ResizeDD( 雙* const的pixelsSrc,const int的old_cols,const int的old_rows, 雙* const的pixelsTarget,整數常量new_rows,整數常量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; 
    } 
} 

}

+0

有是一個小錯誤,因爲它的結果更模糊,那麼他們應該是。過濾行應該是'const double lanc_term = LanczosFilter(row_within - i)* LanczosFilter(col_within - j);' – 2017-04-09 20:45:13