在进行高斯卷积(2d)时,边界处的急剧过渡
Sharp transition at borders when doing Gaussian Convolution (2d)
我正在尝试使用高斯二维卷积模糊矩阵。但是我在边界元素处得到了尖锐的过渡。
下面是我正在运行的一段代码:
// create 1D Kernel
void createGaussianKerenel_1D() {
unsigned kernelSize = 2 * kernelRad_ + 1;
gaussian1Dkernel_ = vector<double>(kernelSize);
double sigma = (double)kernelRad_;
double sum = 0.0;
for(unsigned i = 0; i < kernelSize; ++i) {
gaussian1Dkernel_[i] = gaussian(i, sigma);
sum += gaussian1Dkernel_[i];
}
// normalize
for(unsigned i = 0; i < kernelSize; ++i) {
gaussian1Dkernel_[i] /= sum;
cout << gaussian1Dkernel_[i] << endl;
}
}
// gaussian function
double gaussian(unsigned int i, double sigma) const {
double x = ((double)i - (double)kernelRad_) / sigma;
return exp(-x * x / 2);
}
// do Separable 2D Convolution (in place)
// my initialMatrix_ is of yn_ x xn_ size
void getBlurredThermalMap() {
assert(!gaussian1Dkernel_.empty());
vector<vector<double> > tmpMatrix(yn_);
unsigned kernelSize = 2 * kernelRad_ + 1;
// in x direction
for(unsigned i = 0; i < yn_; ++i) {
for(unsigned j = 0; j < xn_; ++j) {
double approxVal = 0.0;
for(unsigned row = 0; row < kernelSize; ++row) {
unsigned neighbor_j = j + row - kernelRad_;
// ignore values that are out of bound
if(neighbor_j >= 0 && neighbor_j < xn_) {
approxVal += initialMatrix_[i][neighbor_j] * gaussian1Dkernel_[row];
}
}
tmpMatrix[i].push_back(approxVal);
}
}
// in y direction
for(unsigned j = 0; j < xn_; ++j) {
for(unsigned i = 0; i < yn_; ++i) {
double approxVal = 0.0;
for(unsigned col = 0; col < kernelSize; ++col) {
unsigned neighbor_i = i + col - kernelRad_;
if(neighbor_i >= 0 && neighbor_i < yn_) {
approxVal += tmpMatrix[neighbor_i][j] * gaussian1Dkernel_[col];
}
}
initialMatrix_[i][j] = approxVal;
}
}
}
。对于边界元素,我使用了相同的核。我已经测试了这个代码在100x100矩阵和内核2半径。例如,我在1,97和2,97处的元素之间有相当大的差异,尽管在初始矩阵中,这两个位置没有明显的过渡。
也许我需要改变核计算近似值的边界元素?
这可能是因为您没有正确处理边界条件。在你的测试中:
if(neighbor_i >= 0 && neighbor_i < yn_)
第一部分总是为真,因为neighbor_i
是unsigned
,因此总是正数。您可能希望将其更改为带符号的值,稍微修改其声明。你的编译器可以用适当的警告标志为你检查这些错误(试试-Wall -Wextra
)。
编辑:实际上,测试可能不是您的问题的原因,因为您正在使用相对较小的图像,使neighbor_i
的值大于yn_
,当试图在其中存储负值时。
同样,请使用库来做卷积。特别是有相当好的和有效的近似(Canny-Deriche,傅立叶域积,…)高斯模糊
我是这样解决这个问题的:
在createGaussianKerenel_1D()函数中不要规范化内核。相反,可以在getBlurredThermalMap()函数中执行,如下所示:
void getBlurredThermalMap() {
assert(!gaussian1Dkernel_.empty());
vector<vector<double> > tmpMatrix(yn_);
unsigned kernelSize = 2 * kernelRad_ + 1;
// in x direction
for(unsigned i = 0; i < yn_; ++i) {
for(unsigned j = 0; j < xn_; ++j) {
double approxVal = 0.0;
double sumNorm = 0.0;
for(unsigned row = 0; row < kernelSize; ++row) {
unsigned neighbor_j = j + row - kernelRad_;
// ignore values that are out of bound
if(neighbor_j >= 0 && neighbor_j < xn_) {
approxVal += initialMatrix_[i][neighbor_j] * gaussian1Dkernel_[row];
sumNorm += gaussian1Dkernel_[row];
}
}
approxVal /= sumNorm;
tmpMatrix[i].push_back(approxVal);
}
}
// in y direction
for(unsigned j = 0; j < xn_; ++j) {
for(unsigned i = 0; i < yn_; ++i) {
double approxVal = 0.0;
double sumNorm = 0.0;
for(unsigned col = 0; col < kernelSize; ++col) {
unsigned neighbor_i = i + col - kernelRad_;
if(neighbor_i >= 0 && neighbor_i < yn_) {
approxVal += tmpMatrix[neighbor_i][j] * gaussian1Dkernel_[col];
sumNorm += gaussian1Dkernel_[row];
}
}
approxVal /= sumNorm;
initialMatrix_[i][j] = approxVal;
}
}
}
相关文章:
- 在C++上实现高斯赛德尔迭代方法
- C++:矩阵高斯消除不起作用:使用单维数组来存储元素
- (C++)(Visual Studio) 将高斯模糊滤镜应用于 RGB 中的灰度图像
- 用于创建高斯随机数的 c++ 函数
- 将高斯模糊应用于灰度图像
- 高斯雅各比法
- 用高斯Seidel红色黑色求解1D泊松方程
- 如何改变高斯分布(提升)中的种子
- 并行化高斯模糊链
- 为什么在 C++ 中实现高斯勒让德算法没有产生结果
- 生成高斯噪声
- 部分透视/高斯消除 - 交换列而不是产生错误输出的行
- 使用高斯模糊进行图像卷积,可以加速
- 如何使用 1D 高斯内核在 Filter2D 上创建自定义 2D 内核
- ***检测到堆栈粉碎***:在高斯消除中
- 使用C 加入高斯噪声
- 高斯滤波器核值
- 用于高斯过程的准随机数生成器
- OpenCV中的高斯模糊:在边界外设置0常数
- 在进行高斯卷积(2d)时,边界处的急剧过渡