可分离的sobel滤波器实现openCV C++
我正在创建我自己的可分离sobel滤波器实现的实现。我的函数的输入是kernelSize,梯度Y的水平滤波器为pixelsY1,梯度Y的垂直滤波器为像素Y2,梯度X的水平滤波器为像素X1,梯度X的垂直滤波器为像素X2。可分离的sobel滤波器实现openCV C++
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];
}
}
可分离滤波器的计算方法是有效两次通过。 (通道可以是交错的,但是如果按照该顺序执行,则垂直滤波器使用的所有值必须已经由水平滤波器计算)。在注释//then here I do the vertical multiplication
的右下方,对像素X和像素Y的访问实际上是第二遍可分离式过滤器。前面已经计算了x的负值所访问的值,并且x的正值的值尚未通过水平通过计算。
结帐Halide。它使这种代码更容易和更高效。 (性病::载体的双重嵌套是不是一个很好的路要走。)
好了,所以我的错误,实际上在这个
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的其余部分的计算,并且我循环。所以,我创建了另一个矢量矢量,并将它推到了X和Y的位置,这就解决了我的问题。
啊应该已经意识到Sobel并不像2D卷积。同样的问题,垂直计算中的一半值来自水平计算,一半来自原始图像。修正是让他们都从原来的而不是我的建议,把他们全部从水平计算.. –
好吧,如果我理解正确,我再次通过图像,并进行垂直乘法? – Vipoon