我正在创建自己的可分离sobel过滤器实现的实现。我的函数输入kernelSize,梯度Y的水平滤波器作为像素Y1,梯度Y的垂直滤波器作为像素Y2,梯度X的水平滤波器作为像素X1,梯度X的垂直滤波器作为像素X2。
X1的输入为[1,0,-1](水平)
X2的输入是[1,2,1](垂直)
Y1的输入为[1,2,1](水平)
Y2的输入为[1,0 -1](垂直)
void gradientFilter1D(Mat& img, int kernelSize, vector<double> pixelsY1, vector<double> pixelsY2, vector<double> pixelsX1, vector<double> pixelsX2)
{
int sumMin = INT_MAX, sumMax = INT_MIN;
//gradient X
vector<vector<int>> pixelsX(img.rows, vector<int>(img.cols, 0));
//gradient Y
vector<vector<int>> pixelsY(img.rows, vector<int>(img.cols, 0));
vector<vector<int>> sumArray(img.rows, vector<int>(img.cols, 0));
for (int j = kernelSize / 2; j < img.rows - kernelSize / 2; j++)
{
for (int i = kernelSize / 2; i < img.cols - kernelSize / 2; i++)
{
double totalX = 0;
double totalY = 0;
//this is the horizontal multiplication
for (int x = -kernelSize / 2; x <= kernelSize / 2; x++)
{
totalY += img.at<uchar>(j, i + x) * pixelsY1[x + (kernelSize / 2)];
totalX += img.at<uchar>(j, i + x) * pixelsX1[x + (kernelSize / 2)];
//cout << int(img.at<uchar>(j, i + x)) << " " << pixelsY1[x + (kernelSize / 2)] << endl;
}
pixelsX[j][i] = totalX;
pixelsY[j][i] = totalY;
}
}
for (int j = kernelSize / 2; j < img.rows - kernelSize / 2; j++)
{
for (int i = kernelSize / 2; i < img.cols - kernelSize / 2; i++)
{
double totalX = 0;
double totalY = 0;
//this is the vertical multiplication
for (int x = -kernelSize / 2; x <= kernelSize / 2; x++)
{
totalY += pixelsY[j + x][i] * pixelsY2[x + (kernelSize / 2)];
totalX += pixelsX[j + x][i] * pixelsX2[x + (kernelSize / 2)];
//cout << int(img.at<uchar>(j, i + x)) << " " << pixelsY1[x + (kernelSize / 2)] << endl;
}
pixelsX[j][i] = totalX;
pixelsY[j][i] = totalY;
}
}
for (int j = 0; j < img.rows; j++)
{
for (int i = 0; i < img.cols; i++)
{
int sum;
sum = sqrt(pow(pixelsX[j][i], 2) + pow(pixelsY[j][i], 2));
sumArray[j][i] = sum;
sumMin = sumMin < sum ? sumMin : sum;
sumMax = sumMax > sum ? sumMax : sum;
}
}
//normalization
for (int j = 0; j < img.rows; j++)
for (int i = 0; i < img.cols; i++)
{
sumArray[j][i] = (sumArray[j][i] - sumMin) * ((255.0 - 0) / (sumMax - sumMin)) + 0;
img.at<uchar>(j, i) = sumArray[j][i];
}
}
答案 0 :(得分:0)
可分离滤波器的计算结果实际为两次。 (传递可以是交错的,但如果按顺序执行,则垂直滤波器使用的所有值都必须由水平滤波器计算。)在注释//then here I do the vertical multiplication
的正下方,可以访问pixelsX和pixelsY这实际上是可分离滤波器的第二遍。之前已经计算了x的负值所访问的值,并且尚未通过水平传递计算x的正值的值。
结帐Halide。它使这种代码更容易,更高效。 (std :: vector的双重嵌套不是一个好方法。)
答案 1 :(得分:0)
好的,所以我的错误实际上是在这个
for (int j = kernelSize / 2; j < img.rows - kernelSize / 2; j++)
{
for (int i = kernelSize / 2; i < img.cols - kernelSize / 2; i++)
{
double totalX = 0;
double totalY = 0;
//this is the vertical multiplication
for (int x = -kernelSize / 2; x <= kernelSize / 2; x++)
{
totalY += pixelsY[j + x][i] * pixelsY2[x + (kernelSize / 2)];
totalX += pixelsX[j + x][i] * pixelsX2[x + (kernelSize / 2)];
//cout << int(img.at<uchar>(j, i + x)) << " " << pixelsY1[x + (kernelSize / 2)] << endl;
}
pixelsX[j][i] = totalX; <---- I overwrite the old values
pixelsY[j][i] = totalY; <--- I overwrite the old values
}
}
因此,pixelsX [j] [i] = totalX等等是错误的,因为我需要旧值才能在j的其余部分完成计算,并且i循环。所以,我创建了另一个向量向量,并在其中推送了totalX&#39; s和Y&#39; s,这解决了我的问题。