傅立叶理想低通滤波器的结果有点奇怪

时间:2018-12-03 00:30:30

标签: javascript opencv image-processing fft lowpass-filter

我正在尝试实现傅立叶理想的低通滤波器。我得到的结果是正确的(我猜是吗?),但是图像周围有一些奇怪的未处理像素。

50是截止半径。

这是原始图像的图片,经过灰度,傅立叶变换+滤波,然后反向转换回原始图像。

result

这是我的代码:

function idealLowHighPass(img,par,d0){
  let height=img.rows;
  let width=img.cols;
  let prettypls=img.clone();
  let temp=createArray(height,width);
  let tmp = fastFourier(img);
  var tempD;

  let fraction = 0.3;
  let filter = 1;
  var x = width/2;
  var y = height/2;
  var state = -1;
  for(i=0;i<height;i++){
    for(j=0;j<width;j++){

      if(i > y && j > x){
        state = 3;
      }
      else if( i > y){
        state = 1;
      }
      else if (j > x){
        state = 2;
      }
      else{
        state = 0;
      }

      switch(state){
        case 0:
            tempD = (i * i + j * j);
            tempD = Math.sqrt(tempD);
            break;
        case 1:
            tempD = ((height - i) * (height - i) + j * j);
            tempD = Math.sqrt(tempD);
            break;
        case 2:
            tempD = (i * i + (width - j) * (width - j));
            tempD = Math.sqrt(tempD);
            break;
        case 3:
            tempD = ((height - i) * (height - i) + (width - j) * (width - j));
            tempD = Math.sqrt(tempD);
            break;
        default:
            break;
      }

      if(par == 'ideallowpass'){

        if(tempD <= d0){
            tempD = 1;
        }
        else{
            tempD = 0;
        }
      }
      tmp[i][j].re*=tempD;
      tmp[i][j].im*=tempD; 
    }
  }

  //HANDLE FFT
  //take the magnitudes
  for(i=0;i<height;i++){
    for(j=0;j<width;j++){
      temp[i][j]=Math.round(tmp[i][j].re);
    }
  }

  temp=logTransform(temp,height,width);
  for(i=0;i<height;i++){
    for(j=0;j<width;j++){
      let pixel = prettypls.ucharPtr(i,j);
      pixel[0]=Math.round(temp[i][j]);
    }
  }

  // rearrange the quadrants of Fourier image
  // so that the origin is at the image center
  let cx = prettypls.cols / 2;
  let cy = prettypls.rows / 2;
  let tmp2 = new cv.Mat();

  let rect0 = new cv.Rect(0, 0, cx, cy);
  let rect1 = new cv.Rect(cx, 0, cx, cy);
  let rect2 = new cv.Rect(0, cy, cx, cy);
  let rect3 = new cv.Rect(cx, cy, cx, cy);

  let q0 = prettypls.roi(rect0);
  let q1 = prettypls.roi(rect1);
  let q2 = prettypls.roi(rect2);
  let q3 = prettypls.roi(rect3);

  // exchange 1 and 4 quadrants
  q0.copyTo(tmp2);
  q3.copyTo(q0);
  tmp2.copyTo(q3);

  // exchange 2 and 3 quadrants
  q1.copyTo(tmp2);
  q2.copyTo(q1);
  tmp2.copyTo(q2);

  cv.imshow('fourierTransform', prettypls);

  //HANDLE IFFT
  let tmp1 = reverseFastFourier(tmp,height,width);
  //take the magnitudes
  for(i=0;i<height;i++){
    for(j=0;j<width;j++){
      temp[i][j]=Math.round(tmp1[i][j].re);
    }
  }

  for(i=0;i<height;i++){
    for(j=0;j<width;j++){
      let pixel = prettypls.ucharPtr(i,j);
      pixel[0] = Math.max(0, Math.min(255, temp[i][j]));
    }
  }
  cv.imshow('reverseFourier', prettypls);
  temp=[];tmp=[];prettypls.delete();
}

是我遗漏了一些东西还是我的代码有问题?

1 个答案:

答案 0 :(得分:0)

我猜你的问题在这一行:

pixel[0]=Math.round(temp[i][j]);

在这里,您将傅里叶逆变换的实数部分产生的浮点值复制到一个无符号的8位整数中(我从代码中可以看到)。

如果这些值之一略大于255(由于振铃效应,使用“理想的”低通滤波器可能会发生),则转换为8位无符号整数将导致该值回绕。

>

您需要做的是将值限制在[0,255]范围内。将该行替换为:

pixel[0] = Math.max(0, Math.min(255, temp[i][j]));

注意:我猜测此语法将基于一些快速的谷歌搜索而起作用,但这是您需要查看的概念

Math.round调用是不必要的,因为temp已包含舍入值。