gen_gauss_filter( : ImageGauss : Sigma1, Sigma2, Phi, Norm, Mode, Width, Height : )
算法介绍
gen_gauss_filter 在频域生成一个(可能是各向异性的)高斯滤波器。高斯滤波器在空间域的标准偏差(即平滑量)由 Sigma1 和 Sigma2 决定。Sigma1 是滤波器在空间域的主方向标准偏差,由角度 Phi 决定。为了实现滤波操作的最大整体效率,参数 Norm 可用来指定滤波器的归一化系数。如果使用 fft_generic 和 Norm = 'n',则可以避免在 FFT 中进行归一化处理。Mode 可用于确定滤波器直流项的位置,或滤波器是否应在实值 FFT 中使用。如果使用 fft_generic,则可以使用 “dc_edge ”来提高效率。如果使用 fft_image 和 fft_image_inv 进行滤波,则必须使用 Norm = 'none' 和 Mode = 'dc_center'。如果使用 rft_generic,则必须使用 Mode = 'rft'。
算法原理
• 空间域高斯
,
其中 ,
为旋转矩阵。
• 频域响应
连续情形下,傅里叶变换仍为高斯:,
其中 。
• 离散化、RFT 存储
• 水平频率 u = k/W,只保留 。
• 垂直频率 v = ,j=
。
• 输出一个大小为 的矩阵,直接与 rft_generic 的结果相乘即可完成滤波。
主要实现一下Mode:
• rft:只算半频谱,输出 大小,DC 在边缘,给 rft_generic 用。
• dc_edge:输出全频谱 ,DC 在 (0,0)(边缘),可配合任意 FFT 函数(如 fft_generic + Norm='n')直接乘。
• dc_center:输出全频谱 ,DC 在中心 (H/2,W/2)。
代码:
void __cdecl GenGaussFilter(cv::Mat& ImageGauss, double Sigma1, double Sigma2, double Phi, const char* ccNorm, const char* ccMode, double Width, double Height)
{
// 计算输出尺寸
std::string Mode = std::string(ccMode);
int WF = (Mode == "rft" ? (Width / 2 + 1) : Width);
cv::Mat filt(Height, WF, CV_32F);
double cosPhi = std::cos(Phi), sinPhi = std::sin(Phi);
const double scale = -2.0 * CV_PI * CV_PI;
for (int j = 0; j < Height; ++j) {
// 计算垂直频率 v
double v;
if (Mode == "rft") {
v = (j <= Height / 2) ? double(j) / Height : double(j - Height) / Height;
}
else if (Mode == "dc_edge") {
v = (j <= Height / 2) ? double(j) / Height : double(j - Height) / Height;
}
else { // dc_center
v = (j - Height / 2) / double(Height);
}
for (int k = 0; k < WF; ++k) {
// 计算水平频率 u
double u;
if (Mode == "rft") {
u = double(k) / Width;
}
else if (Mode == "dc_edge") {
u = (k <= Width / 2) ? double(k) / Width : double(k - Width) / Width;
}
else { // dc_center
u = (k - Width / 2) / double(Width);
}
// 在主/次方向上做旋转
double u_rot = u * cosPhi + v * sinPhi;
double v_rot = -u * sinPhi + v * cosPhi;
// 频域高斯公式
double expo = scale * (
Sigma1 * Sigma1 * u_rot * u_rot +
Sigma2 * Sigma2 * v_rot * v_rot
);
filt.at<float>(j, k) = float(std::exp(expo));
}
}
// Apply normalization factor
float f = 1. / (Width * Height);
if (strcmp("n", ccNorm) == 0) {
filt *= f;
}
filt.copyTo(ImageGauss);
}
结果和Halcon一致: