c中Sobel算法的多个问题
Multiple problems with Sobel algorithm in c
我正在尝试使用以下代码构建边缘检测程序。虽然我遇到了各种各样的问题,但我不知道如何解决。
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define xrows 700
#define ycolumns 1244
int Gradient[xrows][ycolumns];
int Image_input[xrows][ycolumns];
int G_x[xrows][ycolumns];
int G_y[xrows][ycolumns];
int main() {
FILE *fw = fopen("sobel_outt.txt", "w");
FILE *fr = fopen("ny.txt", "r");
int x, y, row, column, num;
int i = 0;
int XLENGTH = 700;
int YLENGTH = 1244;
for (row = 0; row < XLENGTH; row++) {
for (column = 0; column < YLENGTH; column++) {
fscanf(fr, "%d " ",", &num);
Image_input[row][column] = num;
}
}
fclose(fr);
for (x = 0; x < XLENGTH; x += 3) {
i++;
for (y = 0; y < YLENGTH; y += 3) {
if ((x == 0) || (x == XLENGTH - 1) || (y == 0) || (y == YLENGTH - 1)) {
G_x[x][y] = G_y[x][y] = Gradient[x][y] = 0;
} else {
G_x[x][y] = Image_input[x + 1][y - 1]
+ 2 * Image_input[x + 1][y]
+ Image_input[x + 1][y + 1]
- Image_input[x - 1][y - 1]
- 2 * Image_input[x - 1][y]
- Image_input[x - 1][y + 1];
G_y[x][y] = Image_input[x - 1][y + 1]
+ 2 * Image_input[x][y + 1]
+ Image_input[x + 1][y + 1]
- Image_input[x - 1][y - 1]
- 2 * Image_input[x][y - 1]
- Image_input[x + 1][y - 1];
Gradient[x][y] = (abs(G_x[x][y]) + abs(G_y[x][y]));
if (Gradient[x][y] > 255) {
Gradient[x][y] = 255;
}
}
fprintf(fw, "%d,\n", Gradient[x][y]);
}
}
printf("i= %d", i);
fclose(fw);
return 0;
}
当 devcpp IDE 中的 运行 并且所有矩阵都声明为全局变量时,程序似乎可以正常执行。每当我在主函数中声明它们时,程序就会崩溃。
我尝试 运行 使用 Visual Studio 的程序,但我遇到了更多问题。我收到一些错误消息,指出 fscanf
被忽略并且 fprintf
不安全。
最后但并非最不重要的一点是我收到另一个错误,指出我用完了所有可用的堆栈内存。
欢迎提出任何建议。
编辑:你们中的许多人认为我造成了堆栈溢出。我将尝试使用堆内存作为替代方案。我的第二个问题仍然存在。
将矩阵定义为具有自动存储功能的局部变量使用了将近 14MB 的堆栈 space。在许多平台上,这肯定会导致 堆栈溢出 。建议从堆中分配数据。
Microsoft 的 Visual C 编译器被配置为抱怨 fscanf
和 fprintf
,并提倡使用 fscanf_s
和 fprintf_s
。他们设法获得了这个和其他函数,包括 C 标准(附件 K),但是 API 以微妙的方式进行了更改以保持一致性(使用 size_t
而不是 UINT
数组长度)和 Microsoft没有改变他们的版本。这种差异对于 32 位目标并不重要,但类型 size_t
和 unsigned
现在在大多数 64 位平台上有所不同。
因此不建议将 fscanf_s()
用于可移植程序。您可以通过在包含 <stdio.h>
.
之前添加 #define _CRT_SECURE_NO_WARNINGS
来禁用编译器警告
但是请注意,您不应忽略 fscanf()
的 return 值来检测无效或丢失的数据:如果转换失败,目标变量将保持不变,从而导致不正确的结果甚至未定义的行为.
这是从堆中分配矩阵的修改版本:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS // disable warnings in fscanf
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROWS 700
#define COLS 1244
int main() {
int (*Gradient)[COLS] = calloc(sizeof(*Gradient), ROWS);
int (*Image_input)[COLS] = calloc(sizeof(*Image_input), ROWS);
int (*G_x)[COLS] = calloc(sizeof(*G_x), ROWS);
int (*G_y)[COLS] = calloc(sizeof(*G_y), ROWS);
if (!Gradient || !Image_input || !G_x || !G_y) {
fprintf(stderr, "cannot allocate memory\n");
return 1;
}
FILE *fr = fopen("ny.txt", "r");
if (fr == NULL) {
fprintf(stderr, "cannot open ny.txt: %s\n", strerror(errno));
return 1;
}
FILE *fw = fopen("sobel_outt.txt", "w");
if (fw == NULL) {
fprintf(stderr, "cannot open sobel_outt.txt: %s\n",
strerror(errno));
return 1;
}
int x, y, row, column, num;
int i = 0;
int XLENGTH = ROWS;
int YLENGTH = COLS;
for (row = 0; row < XLENGTH; row++) {
for (column = 0; column < YLENGTH; column++) {
if (fscanf(fr, "%d ,", &num) != 1) {
fprintf(stderr, "cannot read value for Image_input[%d][%d]\n",
row, column);
return 1;
}
Image_input[row][column] = num;
}
}
fclose(fr);
for (x = 0; x < XLENGTH; x += 3) {
i++;
for (y = 0; y < YLENGTH; y += 3) {
if (x == 0 || x == XLENGTH - 1 || y == 0 || y == YLENGTH - 1) {
G_x[x][y] = G_y[x][y] = Gradient[x][y] = 0;
} else {
G_x[x][y] = Image_input[x + 1][y - 1]
+ 2 * Image_input[x + 1][y]
+ Image_input[x + 1][y + 1]
- Image_input[x - 1][y - 1]
- 2 * Image_input[x - 1][y]
- Image_input[x - 1][y + 1];
G_y[x][y] = Image_input[x - 1][y + 1]
+ 2 * Image_input[x][y + 1]
+ Image_input[x + 1][y + 1]
- Image_input[x - 1][y - 1]
- 2 * Image_input[x][y - 1]
- Image_input[x + 1][y - 1];
Gradient[x][y] = abs(G_x[x][y]) + abs(G_y[x][y]);
if (Gradient[x][y] > 255) {
Gradient[x][y] = 255;
}
}
fprintf(fw, "%d,\n", Gradient[x][y]);
}
}
fclose(fw);
printf("i= %d\n", i);
free(Gradient);
free(Image_input);
free(G_x);
free(G_y);
return 0;
}
请注意,i
的最终值应始终为 XLENGTH
。
这是一种对所有数据使用单一结构的替代方法,比分配的二维矩阵更容易处理:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROWS 700
#define COLS 1244
struct sobel {
int Gradient[ROWS][COLS];
int Image_input[ROWS][COLS];
int G_x[ROWS][COLS];
int G_y[ROWS][COLS];
};
int main() {
struct sobel *data = (struct sobel *)calloc(sizeof(*data), 1);
if (!data) {
fprintf(stderr, "cannot allocate memory\n");
return 1;
}
FILE *fr = fopen("ny.txt", "r");
if (fr == NULL) {
fprintf(stderr, "cannot open ny.txt: %s\n", strerror(errno));
return 1;
}
FILE *fw = fopen("sobel_outt.txt", "w");
if (fw == NULL) {
fprintf(stderr, "cannot open sobel_outt.txt: %s\n", strerror(errno));
return 1;
}
int x, y, row, column, num;
int i = 0;
int XLENGTH = ROWS;
int YLENGTH = COLS;
for (row = 0; row < XLENGTH; row++) {
for (column = 0; column < YLENGTH; column++) {
if (fscanf(fr, "%d " ",", &num) != 1) {
fprintf(stderr, "cannot read value for Image_input[%d][%d]\n", row, column);
return 1;
}
data->Image_input[row][column] = num;
}
}
fclose(fr);
for (x = 0; x < XLENGTH; x += 3) {
i++;
for (y = 0; y < YLENGTH; y += 3) {
if (x == 0 || x == XLENGTH - 1 || y == 0 || y == YLENGTH - 1) {
data->G_x[x][y] = data->G_y[x][y] = data->Gradient[x][y] = 0;
} else {
data->G_x[x][y] = data->Image_input[x + 1][y - 1]
+ 2 * data->Image_input[x + 1][y]
+ data->Image_input[x + 1][y + 1]
- data->Image_input[x - 1][y - 1]
- 2 * data->Image_input[x - 1][y]
- data->Image_input[x - 1][y + 1];
data->G_y[x][y] = data->Image_input[x - 1][y + 1]
+ 2 * data->Image_input[x][y + 1]
+ data->Image_input[x + 1][y + 1]
- data->Image_input[x - 1][y - 1]
- 2 * data->Image_input[x][y - 1]
- data->Image_input[x + 1][y - 1];
data->Gradient[x][y] = abs(data->G_x[x][y]) + abs(data->G_y[x][y]);
if (data->Gradient[x][y] > 255) {
data->Gradient[x][y] = 255;
}
}
fprintf(fw, "%d,\n", data->Gradient[x][y]);
}
}
fclose(fw);
printf("i= %d\n", i);
free(data);
return 0;
}
我正在尝试使用以下代码构建边缘检测程序。虽然我遇到了各种各样的问题,但我不知道如何解决。
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define xrows 700
#define ycolumns 1244
int Gradient[xrows][ycolumns];
int Image_input[xrows][ycolumns];
int G_x[xrows][ycolumns];
int G_y[xrows][ycolumns];
int main() {
FILE *fw = fopen("sobel_outt.txt", "w");
FILE *fr = fopen("ny.txt", "r");
int x, y, row, column, num;
int i = 0;
int XLENGTH = 700;
int YLENGTH = 1244;
for (row = 0; row < XLENGTH; row++) {
for (column = 0; column < YLENGTH; column++) {
fscanf(fr, "%d " ",", &num);
Image_input[row][column] = num;
}
}
fclose(fr);
for (x = 0; x < XLENGTH; x += 3) {
i++;
for (y = 0; y < YLENGTH; y += 3) {
if ((x == 0) || (x == XLENGTH - 1) || (y == 0) || (y == YLENGTH - 1)) {
G_x[x][y] = G_y[x][y] = Gradient[x][y] = 0;
} else {
G_x[x][y] = Image_input[x + 1][y - 1]
+ 2 * Image_input[x + 1][y]
+ Image_input[x + 1][y + 1]
- Image_input[x - 1][y - 1]
- 2 * Image_input[x - 1][y]
- Image_input[x - 1][y + 1];
G_y[x][y] = Image_input[x - 1][y + 1]
+ 2 * Image_input[x][y + 1]
+ Image_input[x + 1][y + 1]
- Image_input[x - 1][y - 1]
- 2 * Image_input[x][y - 1]
- Image_input[x + 1][y - 1];
Gradient[x][y] = (abs(G_x[x][y]) + abs(G_y[x][y]));
if (Gradient[x][y] > 255) {
Gradient[x][y] = 255;
}
}
fprintf(fw, "%d,\n", Gradient[x][y]);
}
}
printf("i= %d", i);
fclose(fw);
return 0;
}
当 devcpp IDE 中的 运行 并且所有矩阵都声明为全局变量时,程序似乎可以正常执行。每当我在主函数中声明它们时,程序就会崩溃。
我尝试 运行 使用 Visual Studio 的程序,但我遇到了更多问题。我收到一些错误消息,指出 fscanf
被忽略并且 fprintf
不安全。
最后但并非最不重要的一点是我收到另一个错误,指出我用完了所有可用的堆栈内存。
欢迎提出任何建议。
编辑:你们中的许多人认为我造成了堆栈溢出。我将尝试使用堆内存作为替代方案。我的第二个问题仍然存在。
将矩阵定义为具有自动存储功能的局部变量使用了将近 14MB 的堆栈 space。在许多平台上,这肯定会导致 堆栈溢出 。建议从堆中分配数据。
Microsoft 的 Visual C 编译器被配置为抱怨 fscanf
和 fprintf
,并提倡使用 fscanf_s
和 fprintf_s
。他们设法获得了这个和其他函数,包括 C 标准(附件 K),但是 API 以微妙的方式进行了更改以保持一致性(使用 size_t
而不是 UINT
数组长度)和 Microsoft没有改变他们的版本。这种差异对于 32 位目标并不重要,但类型 size_t
和 unsigned
现在在大多数 64 位平台上有所不同。
因此不建议将 fscanf_s()
用于可移植程序。您可以通过在包含 <stdio.h>
.
#define _CRT_SECURE_NO_WARNINGS
来禁用编译器警告
但是请注意,您不应忽略 fscanf()
的 return 值来检测无效或丢失的数据:如果转换失败,目标变量将保持不变,从而导致不正确的结果甚至未定义的行为.
这是从堆中分配矩阵的修改版本:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS // disable warnings in fscanf
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROWS 700
#define COLS 1244
int main() {
int (*Gradient)[COLS] = calloc(sizeof(*Gradient), ROWS);
int (*Image_input)[COLS] = calloc(sizeof(*Image_input), ROWS);
int (*G_x)[COLS] = calloc(sizeof(*G_x), ROWS);
int (*G_y)[COLS] = calloc(sizeof(*G_y), ROWS);
if (!Gradient || !Image_input || !G_x || !G_y) {
fprintf(stderr, "cannot allocate memory\n");
return 1;
}
FILE *fr = fopen("ny.txt", "r");
if (fr == NULL) {
fprintf(stderr, "cannot open ny.txt: %s\n", strerror(errno));
return 1;
}
FILE *fw = fopen("sobel_outt.txt", "w");
if (fw == NULL) {
fprintf(stderr, "cannot open sobel_outt.txt: %s\n",
strerror(errno));
return 1;
}
int x, y, row, column, num;
int i = 0;
int XLENGTH = ROWS;
int YLENGTH = COLS;
for (row = 0; row < XLENGTH; row++) {
for (column = 0; column < YLENGTH; column++) {
if (fscanf(fr, "%d ,", &num) != 1) {
fprintf(stderr, "cannot read value for Image_input[%d][%d]\n",
row, column);
return 1;
}
Image_input[row][column] = num;
}
}
fclose(fr);
for (x = 0; x < XLENGTH; x += 3) {
i++;
for (y = 0; y < YLENGTH; y += 3) {
if (x == 0 || x == XLENGTH - 1 || y == 0 || y == YLENGTH - 1) {
G_x[x][y] = G_y[x][y] = Gradient[x][y] = 0;
} else {
G_x[x][y] = Image_input[x + 1][y - 1]
+ 2 * Image_input[x + 1][y]
+ Image_input[x + 1][y + 1]
- Image_input[x - 1][y - 1]
- 2 * Image_input[x - 1][y]
- Image_input[x - 1][y + 1];
G_y[x][y] = Image_input[x - 1][y + 1]
+ 2 * Image_input[x][y + 1]
+ Image_input[x + 1][y + 1]
- Image_input[x - 1][y - 1]
- 2 * Image_input[x][y - 1]
- Image_input[x + 1][y - 1];
Gradient[x][y] = abs(G_x[x][y]) + abs(G_y[x][y]);
if (Gradient[x][y] > 255) {
Gradient[x][y] = 255;
}
}
fprintf(fw, "%d,\n", Gradient[x][y]);
}
}
fclose(fw);
printf("i= %d\n", i);
free(Gradient);
free(Image_input);
free(G_x);
free(G_y);
return 0;
}
请注意,i
的最终值应始终为 XLENGTH
。
这是一种对所有数据使用单一结构的替代方法,比分配的二维矩阵更容易处理:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROWS 700
#define COLS 1244
struct sobel {
int Gradient[ROWS][COLS];
int Image_input[ROWS][COLS];
int G_x[ROWS][COLS];
int G_y[ROWS][COLS];
};
int main() {
struct sobel *data = (struct sobel *)calloc(sizeof(*data), 1);
if (!data) {
fprintf(stderr, "cannot allocate memory\n");
return 1;
}
FILE *fr = fopen("ny.txt", "r");
if (fr == NULL) {
fprintf(stderr, "cannot open ny.txt: %s\n", strerror(errno));
return 1;
}
FILE *fw = fopen("sobel_outt.txt", "w");
if (fw == NULL) {
fprintf(stderr, "cannot open sobel_outt.txt: %s\n", strerror(errno));
return 1;
}
int x, y, row, column, num;
int i = 0;
int XLENGTH = ROWS;
int YLENGTH = COLS;
for (row = 0; row < XLENGTH; row++) {
for (column = 0; column < YLENGTH; column++) {
if (fscanf(fr, "%d " ",", &num) != 1) {
fprintf(stderr, "cannot read value for Image_input[%d][%d]\n", row, column);
return 1;
}
data->Image_input[row][column] = num;
}
}
fclose(fr);
for (x = 0; x < XLENGTH; x += 3) {
i++;
for (y = 0; y < YLENGTH; y += 3) {
if (x == 0 || x == XLENGTH - 1 || y == 0 || y == YLENGTH - 1) {
data->G_x[x][y] = data->G_y[x][y] = data->Gradient[x][y] = 0;
} else {
data->G_x[x][y] = data->Image_input[x + 1][y - 1]
+ 2 * data->Image_input[x + 1][y]
+ data->Image_input[x + 1][y + 1]
- data->Image_input[x - 1][y - 1]
- 2 * data->Image_input[x - 1][y]
- data->Image_input[x - 1][y + 1];
data->G_y[x][y] = data->Image_input[x - 1][y + 1]
+ 2 * data->Image_input[x][y + 1]
+ data->Image_input[x + 1][y + 1]
- data->Image_input[x - 1][y - 1]
- 2 * data->Image_input[x][y - 1]
- data->Image_input[x + 1][y - 1];
data->Gradient[x][y] = abs(data->G_x[x][y]) + abs(data->G_y[x][y]);
if (data->Gradient[x][y] > 255) {
data->Gradient[x][y] = 255;
}
}
fprintf(fw, "%d,\n", data->Gradient[x][y]);
}
}
fclose(fw);
printf("i= %d\n", i);
free(data);
return 0;
}