同态过滤器 - python溢出

信息处理 Python opencv 过滤
2022-01-30 17:21:58

我正在尝试实现本研究文章所实现的同态过滤 - 步骤 4 (pdf)

我试图翻译成 Python 的原始 Matlab 代码如下(警告:只有开关的第一种情况是相关的):

%%%%%%%%%%%%%%%%%%%%%%%
% Homomorphic filtering
% Stéphane BAZEILLE
% 15/10/07
%%%%%%%%%%

function result=homomorphic_filtering(I,type,RH,RL,cutoff)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% I = image (en niveau de gris et double entre 0 et 1)              %%
%% type= 'HighPassLiao' 'HighPassCufi' 'HighPassFilter'              %%
%%       'LowPassFilter' 'BandPassFilter' 'OnesFilter'               %%
%% !!!!!!!!! afficher avec imshow sans contrast_stretching !!!!!!!!! %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   

[rows,cols,dim]=size(I);

%figure;imshow(I);title('homo in');

% figure;hist(I,0.01:0.01:1.49);

disp(['Homomorphic filtering (',type,',',num2str(RH),',',num2str(RL),')']);

%Modélisation du filtre
if mod(cols,2) xrange = [-(cols-1)/2:(cols-1)/2]/(cols-1);
else           xrange = [-cols/2:(cols/2-1)]/cols;  
end
if mod(rows,2) yrange = [-(rows-1)/2:(rows-1)/2]/(rows-1);
else           yrange = [-rows/2:(rows/2-1)]/rows;  
end
[x,y] = meshgrid(xrange, yrange);
radius = sqrt(x.^2 + y.^2);
switch type
        case 'HighPassLiao' 
            DX=cols/cutoff;
            G = ones(rows,cols);
            for m = 1:rows
                for n = 1:cols
                    G (m,n) = ((RH-RL)*(1-exp(-(((m-rows/2))*((m-rows/2))+((n-cols/2))*((n-cols/2)))/(2*DX*DX))))+RL;
                    %G (m,n) = ((RH-RL)*(1-exp(-(((m-rows/8))*((m-rows/8))+((n-cols/8))*((n-cols/8)))/(2*DX*DX))))+RL;
                end
            end
        case 'HighPassCufi'
            cutoff = 0.4; % 0 - 0.5
            offset = 0.5;
            boost  = 2;
            scale  = 50;
            G = boost./(1.0 + exp(-scale*(radius-cutoff))) + offset;
        case 'HighPassFilter' 
            cutoff = 0.3;  % 0 - 0.5
            n      = 3;    % n >= 1
            boost  = 0.2;  % 0<= boost=<1
            G = (1-boost)*(1 - (1 ./ (1.0 + (radius ./ cutoff).^(2*n))))+boost;
        case 'LowPassFilter'
            cutoff = 0.1;  % 0 - 0.5
            n      = 3;    % n >= 1
            boost  = 0.2;  % 0<= boost <1 
            G = (1-boost) ./ (1.0 + (radius ./ cutoff).^(2*n))+boost;
        case 'BandPassFilter'
            cutoff = 0.1;  % 0 - 0.5
            cutin  = 0.01; % 0 - 0.5
            n = 3;         % n >= 1
            G = (1 ./ (1.0 + (radius ./ cutoff).^(2*n)))-(1 ./ (1.0 + (radius ./ cutin).^(2*n)));
        case 'OnesFilter'
            G=ones(rows,cols);
end

%Filtrage homomorphique
if(dim==1)
    Idft=fft2(log(I+0.01));
    filtree=G.*fftshift(Idft);
    result=exp(real(ifft2(ifftshift(filtree))));
else
    Idft=fft2(log(I(:,:,1)+0.01));
    filtree=G.*fftshift(Idft);
    result(:,:,1)=exp(real(ifft2(ifftshift(filtree))));

    Idft=fft2(log(I(:,:,2)+0.01));
    filtree=G.*fftshift(Idft);
    result(:,:,2)=exp(real(ifft2(ifftshift(filtree))));

    Idft=fft2(log(I(:,:,3)+0.01));
    filtree=G.*fftshift(Idft);
    result(:,:,3)=exp(real(ifft2(ifftshift(filtree))));
end
end

它被称为如下:

%param: full image name
function prefilter_demo(name)

ori = imread(name);  
ori = double(ori)/255;
disp('Image Loaded');
figure;subplot(1,2,1);imshow(ori);axis off

tic;

disp('BEGIN FILTERING');
% EXTEND AND RESIZE IMAGE
[nl nc I ori]=picture_power_of_2(ori,5);
% CONVERT RGB TO YCBCR
ycbcr = rgb2ycbcr(I);
% HOMOMORPHIC FILTERING
ycbcr(:,:,1)=homomorphic_filtering(ycbcr(:,:,1),'HighPassLiao',2.5,0.5,32);

我的问题是在最终的指数计算中出现溢出错误:

test_CV.py:64: RuntimeWarning: overflow encountered in exp

我不明白为什么,因为我认为我的 Python 代码等同于 Matlab 原始代码。我没有预处理阶段来将图像大小调整为 2 像素平方的幂,但我仍然在 512x512 图像上执行我的脚本。

这是我的 Python 脚本:

#!/usr/bin/env python3
# coding: utf-8

import cv2
import numpy as np

img = cv2.imread('bleu_carree_512.jpg',-1)

rows,cols,dim=img.shape

rh, rl, cutoff = 2.5,0.5,32

imgYCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
y,cr,cb = cv2.split(imgYCrCb)

y_log = np.log(y+0.01)

y_fft = cv2.dft(np.float32(y_log),flags = cv2.DFT_COMPLEX_OUTPUT)
y_fft_shift = np.fft.fftshift(y_fft)


DX = cols/cutoff
G = np.ones((rows,cols,2))
for i in range(rows):
    for j in range(cols):
        G[i][j][0]=((rh-rl)*(1-np.exp(-((i-rows/2)**2+(j-cols/2)**2)/(2*DX**2))))+rl
        G[i][j][1]=((rh-rl)*(1-np.exp(-((i-rows/2)**2+(j-cols/2)**2)/(2*DX**2))))+rl


result_filter = np.multiply(y_fft_shift,G)

result_interm = np.real(cv2.idft(np.fft.ifftshift(result_filter)))

#################################
### OVERFLOW SOURCE BELOW #######
#################################

result = np.exp(result_interm) 

print(result.shape)

cv2.imshow('résultat',result)
cv2.waitKey(0)
cv2.destroyAllWindows()

与文章相关的所有代码都可以在这里找到

谢谢 !

编辑和修复:

错误确实是缺乏归一化,并且使用归一化cv2.dft()会返回一个 3 维数组。为了等效于 的计算matlab fft2(),我切换到numpy.fft()which 返回一个二维数组,就像 Matlab 所做的那样。

调整大小和对称化似乎不是绝对必要的(更正的脚本在没有它的情况下工作)。

尽管如此,它似乎matlab rgb2ycbcr()没有给出与python cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)(结果数组略有不同)相同的 Y 分量。这会影响所有后续处理和最终结果。

此外,Matlab 不需要对生成的图像进行反规范化以显示后者,而我需要result*255在我的 Python 脚本中将其可视化。这有一种趋势,以及 RGB->RCrCb 转换的细微差异,将过滤器转换为 Python 的“质量”改变。

话虽如此,如果有人感兴趣,这里是功能性 Python 脚本:

#!/usr/bin/python2.7
# coding: utf-8

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('U352.jpg',-1)
img = np.float32(img)
img = img/255

rows,cols,dim=img.shape

rh, rl, cutoff = 2.5,0.5,32

imgYCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
y,cr,cb = cv2.split(imgYCrCb)

y_log = np.log(y+0.01)

y_fft = np.fft.fft2(y_log)

y_fft_shift = np.fft.fftshift(y_fft)


DX = cols/cutoff
G = np.ones((rows,cols))
for i in range(rows):
    for j in range(cols):
        G[i][j]=((rh-rl)*(1-np.exp(-((i-rows/2)**2+(j-cols/2)**2)/(2*DX**2))))+rl

result_filter = G * y_fft_shift

result_interm = np.real(np.fft.ifft2(np.fft.ifftshift(result_filter)))

result = np.exp(result_interm)
1个回答

使固定:

错误确实是缺乏归一化,并且使用归一化cv2.dft()会返回一个 3 维数组。为了等效于 的计算matlab fft2(),我切换到numpy.fft()which 返回一个二维数组,就像 Matlab 所做的那样。

调整大小和对称化似乎不是绝对必要的(更正的脚本在没有它的情况下工作)。

尽管如此,它似乎matlab rgb2ycbcr()没有给出与python cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)(结果数组略有不同)相同的 Y 分量。这会影响所有后续处理和最终结果。

此外,Matlab 不需要对生成的图像进行反规范化以显示后者,而我需要result*255在我的 Python 脚本中将其可视化。这有一种趋势,以及 RGB->RCrCb 转换的细微差异,将过滤器转换为 Python 的“质量”改变。

话虽如此,如果有人感兴趣,这里是功能性 Python 脚本:

#!/usr/bin/python2.7
# coding: utf-8

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('U352.jpg',-1)
img = np.float32(img)
img = img/255

rows,cols,dim=img.shape

rh, rl, cutoff = 2.5,0.5,32

imgYCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
y,cr,cb = cv2.split(imgYCrCb)

y_log = np.log(y+0.01)

y_fft = np.fft.fft2(y_log)

y_fft_shift = np.fft.fftshift(y_fft)


DX = cols/cutoff
G = np.ones((rows,cols))
for i in range(rows):
    for j in range(cols):
        G[i][j]=((rh-rl)*(1-np.exp(-((i-rows/2)**2+(j-cols/2)**2)/(2*DX**2))))+rl

result_filter = G * y_fft_shift

result_interm = np.real(np.fft.ifft2(np.fft.ifftshift(result_filter)))

result = np.exp(result_interm)