我真的很接近实现这个算法,但我的代码存在一些问题。
int Gx[3][3] = {{ -1, 0, 1 },
{ -2, 0, 2 },
{ -1, 0, 1 }};
int Gy[3][3] = {{ -1, -2, -1 },
{ 0, 0, 0 },
{ 1, 2, 1 }};
unsigned int x, y;
long sumX, sumY;
int SUM;
for (x = 0; x < image->w - 1; x++) {
for (y = 0; y < image->h - 1; y++) {
sumX = 0;
sumY = 0;
if (x == 0 || x == image->w - 1)
SUM = 0;
else if (y == 0 || y == image->h - 1)
SUM = 0;
else {
sumX = (Gx[0][0] * image->pixels[(y-1)*image->w+(x-1)]) + (Gx[0][1] * image->pixels[(y-1)*image->w+(x)]) + (Gx[0][2] * image->pixels[(y-1)*image->w+(x+1)]) +
(Gx[1][0] * image->pixels[(y)*image->w+(x-1)]) + (Gx[1][1] * image->pixels[(y)*image->w+(x)]) + (Gx[1][2] * image->pixels[(y)*image->w+(x+1)]) +
(Gx[2][0] * image->pixels[(y+1)*image->w+(x-1)]) + (Gx[2][1] * image->pixels[(y+1)*image->w+(x)]) + (Gx[2][2] * image->pixels[(y+1)*image->w+(x+1)]);
sumY = (Gy[0][0] * image->pixels[(y-1)*image->w+(x-1)]) + (Gy[0][1] * image->pixels[(y-1)*image->w+(x)]) + (Gy[0][2] * image->pixels[(y-1)*image->w+(x+1)]) +
(Gy[1][0] * image->pixels[(y)*image->w+(x-1)]) + (Gy[1][1] * image->pixels[(y)*image->w+(x)]) + (Gy[1][2] * image->pixels[(y)*image->w+(x+1)]) +
(Gy[2][0] * image->pixels[(y+1)*image->w+(x-1)]) + (Gy[2][1] * image->pixels[(y+1)*image->w+(x)]) + (Gy[2][2] * image->pixels[(y+1)*image->w+(x+1)]);
}
SUM = sqrtf((sumX^2) + (sumY^2));
image->pixels[y * image->w + x] = SUM;
}
}
我使用了用Ruby编写的implementation并将其转换为C.
有一个小故障,输出不应该是黑白的?
我认为我使用的例子的创建者使用了错误的乘法。例如这个(sobel_x[0][0] * img.at(x-1,y-1))
,在这里他将sobel数组的索引乘以0,0(-1)与像素0,0相乘,因为x和y位于中心(1,1)像素阵列。相反,他应该使用(sobel_x[0][0] * img.at(x+1,y+1))
对吧?
答案 0 :(得分:0)
在C中,^
运算符是按位xor运算符。没有幂运算符,通过将其与自身相乘来执行平方sumX
:sumX * sumX
。
此外,你不应该把你的循环从边缘缩短一半,每一行的最后一个像素和最后一行不是用你当前的循环来计算的。
将系数数组Gx
和Gy
定义为static const
将允许编译器将其值保持为常量并优化代码而不从数组中加载这些值,从而删除所有这些乘法。
以下是修改后的版本:
static const int Gx[3][3] = {{ -1, 0, 1 },
{ -2, 0, 2 },
{ -1, 0, 1 }};
static const int Gy[3][3] = {{ -1, -2, -1 },
{ 0, 0, 0 },
{ 1, 2, 1 }};
unsigned int x, y;
long sumX, sumY;
int SUM;
for (x = 0; x < image->w; x++) {
for (y = 0; y < image->h; y++) {
sumX = 0;
sumY = 0;
if (x > 0 && x < image->w - 1 && y > 0 && y < image->h - 1) {
sumX = (Gx[0][0] * image->pixels[(y - 1) * image->w + (x - 1)]) +
(Gx[0][1] * image->pixels[(y - 1) * image->w + (x)]) +
(Gx[0][2] * image->pixels[(y - 1) * image->w + (x + 1)]) +
(Gx[1][0] * image->pixels[(y) * image->w + (x - 1)]) +
(Gx[1][1] * image->pixels[(y) * image->w + (x)]) +
(Gx[1][2] * image->pixels[(y) * image->w + (x + 1)]) +
(Gx[2][0] * image->pixels[(y + 1) * image->w + (x - 1)]) +
(Gx[2][1] * image->pixels[(y + 1) * image->w + (x)]) +
(Gx[2][2] * image->pixels[(y + 1) * image->w + (x + 1)]);
sumY = (Gy[0][0] * image->pixels[(y - 1) * image->w + (x - 1)]) +
(Gy[0][1] * image->pixels[(y - 1) * image->w + (x)]) +
(Gy[0][2] * image->pixels[(y - 1) * image->w + (x + 1)]) +
(Gy[1][0] * image->pixels[(y) * image->w + (x - 1)]) +
(Gy[1][1] * image->pixels[(y) * image->w + (x)]) +
(Gy[1][2] * image->pixels[(y) * image->w + (x + 1)]) +
(Gy[2][0] * image->pixels[(y + 1) * image->w + (x - 1)]) +
(Gy[2][1] * image->pixels[(y + 1) * image->w + (x)]) +
(Gy[2][2] * image->pixels[(y + 1) * image->w + (x + 1)]);
}
SUM = sqrtf(sumX * sumX + sumY * sumY);
image->pixels[y * image->w + x] = SUM;
}
}
请注意,使用正确定义的2D数组image->pixels
的本地指针可以大大简化代码:
static const int Gx[3][3] = {{ -1, 0, 1 },
{ -2, 0, 2 },
{ -1, 0, 1 }};
static const int Gy[3][3] = {{ -1, -2, -1 },
{ 0, 0, 0 },
{ 1, 2, 1 }};
unsigned int x, y;
long sumX, sumY;
pixel_type (*pixels)[image->w] = (void*)image->pixels;
for (x = 0; x < image->w; x++) {
for (y = 0; y < image->h; y++) {
sumX = sumY = 0;
if (x > 0 && x < image->w - 1 && y > 0 && y < image->h - 1) {
sumX = (Gx[0][0] * pixels[y - 1][x - 1]) +
(Gx[0][1] * pixels[y - 1][x]) +
(Gx[0][2] * pixels[y - 1][x + 1]) +
(Gx[1][0] * pixels[y][x - 1]) +
(Gx[1][1] * pixels[y][x]) +
(Gx[1][2] * pixels[y][x + 1]) +
(Gx[2][0] * pixels[y + 1][x - 1]) +
(Gx[2][1] * pixels[y + 1][x]) +
(Gx[2][2] * pixels[y + 1][x + 1]);
sumY = (Gy[0][0] * pixels[y - 1][x - 1]) +
(Gy[0][1] * pixels[y - 1][x]) +
(Gy[0][2] * pixels[y - 1][x + 1]) +
(Gy[1][0] * pixels[y][x - 1]) +
(Gy[1][1] * pixels[y][x]) +
(Gy[1][2] * pixels[y][x + 1]) +
(Gy[2][0] * pixels[y + 1][x - 1]) +
(Gy[2][1] * pixels[y + 1][x]) +
(Gy[2][2] * pixels[y + 1][x + 1]);
}
pixels[y][x] = sqrtf(sumX * sumX + sumY * sumY);
}
}
仍然存在一个主要问题:您无法就地计算此过滤器,因为修改后的像素值将用于下一列和行。您必须使用临时数组来存储结果:
static const int Gx[3][3] = {{ -1, 0, 1 },
{ -2, 0, 2 },
{ -1, 0, 1 }};
static const int Gy[3][3] = {{ -1, -2, -1 },
{ 0, 0, 0 },
{ 1, 2, 1 }};
unsigned int x, y;
long sumX, sumY;
pixel_type (*pixels)[image->w] = (void*)image->pixels;
pixel_type (*dest)[image->w] = malloc(image->h * sizeof(*dest));
for (x = 0; x < image->w; x++) {
for (y = 0; y < image->h; y++) {
sumX = sumY = 0;
if (x > 0 && x < image->w - 1 && y > 0 && y < image->h - 1) {
sumX = (Gx[0][0] * pixels[y - 1][x - 1]) +
(Gx[0][1] * pixels[y - 1][x]) +
(Gx[0][2] * pixels[y - 1][x + 1]) +
(Gx[1][0] * pixels[y][x - 1]) +
(Gx[1][1] * pixels[y][x]) +
(Gx[1][2] * pixels[y][x + 1]) +
(Gx[2][0] * pixels[y + 1][x - 1]) +
(Gx[2][1] * pixels[y + 1][x]) +
(Gx[2][2] * pixels[y + 1][x + 1]);
sumY = (Gy[0][0] * pixels[y - 1][x - 1]) +
(Gy[0][1] * pixels[y - 1][x]) +
(Gy[0][2] * pixels[y - 1][x + 1]) +
(Gy[1][0] * pixels[y][x - 1]) +
(Gy[1][1] * pixels[y][x]) +
(Gy[1][2] * pixels[y][x + 1]) +
(Gy[2][0] * pixels[y + 1][x - 1]) +
(Gy[2][1] * pixels[y + 1][x]) +
(Gy[2][2] * pixels[y + 1][x + 1]);
}
dest[y][x] = sqrtf(sumX * sumX + sumY * sumY);
}
}
memcpy(pixels, dest, image->h * sizeof(*pixels));
free(dest);