我正在尝试使用自定义float
数组进行模糊卷积。
我的数组定义为float array[width*height]
。我编辑了these函数,以便它可以与自定义数组一起使用,而不仅限于OpenCV cv::Mat
我的代码如下所示:
int reflect(int M, int x)
{
if(x < 0)
{
return -x - 1;
}
if(x >= M)
{
return 2*M - x - 1;
}
return x;
}
void separable2DConvolution(float * data, Size dataSize, float *kernel, int kernelSize)
{
// make copy of original image
float * dataCopy = new float[dataSize.width()*dataSize.height()];
memcpy(dataCopy, data, dataSize.width()*dataSize.height());
float * temp = new float[dataSize.width()*dataSize.height()];
memcpy(temp, data, dataSize.width()*dataSize.height());
float sum;
int x1, y1;
int kernelRadius = floor(kernelSize/2);
// along y - direction
for(int y = 0; y < dataSize.height(); y++){
for(int x = 0; x < dataSize.width(); x++){
sum = 0.0;
for(int i = -kernelRadius; i <= kernelRadius; i++){
y1 = reflect(dataSize.height(), y - i);
sum = sum + kernel[i + kernelRadius]*dataCopy[y1*x+y1];
}
temp[y*x+y] = sum;
}
}
// along x - direction
for(int y = 0; y < dataSize.height(); y++){
for(int x = 0; x < dataSize.width(); x++){
sum = 0.0;
for(int i = -kernelRadius; i <= kernelRadius; i++){
x1 = reflect(dataSize.width(), x - i);
sum = sum + kernel[i + kernelRadius]*temp[x1*y+x1];
}
data[x*y+y] = sum;
}
}
delete [] temp;
delete [] dataCopy;
}
数组以
separable2DConvolution
的形式传递给data
,Size
是具有定义的宽度和高度的自定义类(均为有效且大于0),kernel
是归一化的高斯数组(几乎与cv::getGaussianKernel
中的一个一致),并且kernelSize
是高斯数组的大小(我使用的是11号)。我使用此函数从 OpenCV 替换
cv::sepFilter2D
,但是输出有所不同。使用函数后,我将转换图像以查看差异。OpenCV输出具有(如预期的那样)“模糊”的值,但是在将相同的输入传递给我的函数的情况下,前三分之一是有噪点的(根本没有模糊),而图像的另一部分是完整的。
我的代码有什么问题?
谢谢您的帮助!
最佳答案
您用于保存像素总和的下标是错误的。 temp[y*x+y]
将第一列的所有结果写入第一个像素(temp[0]
)。许多其他像素将保持不变。您可能需要temp[y * dataSize.width() + x]
,在下一个循环中以及在计算下标以读取像素值时对data[x*y+y]
进行类似的更改。
无关的,您不需要对位图进行memcpy
进行复制,因为您应该写入图像中的每个像素。您根本不需要dataCopy
,因为原始data
数组尚未更改。
对于整数,使用floor
是多余的。由于kernelSize
是肯定的,因此您只能说int kernelRadius = kernelSize / 2;
,因为这会舍入。
关于c++ - 具有可分离内核的2D模糊卷积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59991103/