傅立叶理想低通滤波器结果有点奇怪
Fourier Ideal Lowpass filter result is bit weird
我正在尝试实现傅立叶理想低通滤波器。我得到的结果有点正确(我猜?),但是图像周围有一些奇怪的未处理像素。
50 是截止半径。
这里是原图,灰度图,傅立叶变换+滤波,反变换回原图。
这是我的代码:
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();
}
是不是我遗漏了什么或者我的代码有问题?
我猜你的问题出在这一行:
pixel[0]=Math.round(temp[i][j]);
在这里,您将傅里叶逆变换的实数分量产生的浮点值复制为无符号 8 位整数(我从代码中看到的推测)。
如果其中一个值略高于 255(由于振铃假象,"ideal" 低通滤波器可能会发生这种情况),则转换为 8 位无符号整数将导致值回绕左右。
您需要做的是将值限制在 [0,255] 范围内。将该行替换为:
pixel[0] = Math.max(0, Math.min(255, temp[i][j]));
注意:我猜这个语法将基于一些快速的谷歌搜索工作,但它是你需要看的概念...
不需要调用 Math.round
,因为 temp
已经包含了舍入值。
我正在尝试实现傅立叶理想低通滤波器。我得到的结果有点正确(我猜?),但是图像周围有一些奇怪的未处理像素。
50 是截止半径。
这里是原图,灰度图,傅立叶变换+滤波,反变换回原图。
这是我的代码:
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();
}
是不是我遗漏了什么或者我的代码有问题?
我猜你的问题出在这一行:
pixel[0]=Math.round(temp[i][j]);
在这里,您将傅里叶逆变换的实数分量产生的浮点值复制为无符号 8 位整数(我从代码中看到的推测)。
如果其中一个值略高于 255(由于振铃假象,"ideal" 低通滤波器可能会发生这种情况),则转换为 8 位无符号整数将导致值回绕左右。
您需要做的是将值限制在 [0,255] 范围内。将该行替换为:
pixel[0] = Math.max(0, Math.min(255, temp[i][j]));
注意:我猜这个语法将基于一些快速的谷歌搜索工作,但它是你需要看的概念...
不需要调用 Math.round
,因为 temp
已经包含了舍入值。