gpt4 book ai didi

c - 高斯模糊、均值滤波器、卷积

转载 作者:行者123 更新时间:2023-12-04 04:37:57 25 4
gpt4 key购买 nike

我想实现一个卷积函数以在均值滤波器和高斯滤波器中使用,并且我还需要实现这两个滤波器以应用于 pgm 文件。
我有

typedef struct _PGM{
int row;
int col;
int max_value;
int **matrix;
}PGM;

结构和
int convolution(int ** kernel,int ksize, PGM * image, PGM * output){

int i, j, x, y;
int sum;
int data;
int scale =ksize*ksize;
int coeff;

for (x=ksize/2; x<image->row-ksize/2;++x) {
for (y=ksize/2; y<image->col-ksize/2; ++y){
sum = 0;
for (i=-ksize/2; i<=ksize/2; ++i){
for (j=-ksize/2; j<=ksize/2; ++j){
data = image->matrix[x +i][y +j];
coeff = kernel[i+ksize/2][j+ksize/2];
sum += data * coeff;
}
}
output->matrix[x][y] = sum / scale;
}
}

return sum/scale;
}

卷积函数但我在卷积函数中出错(实际上它终止了)所以我无法继续过滤
你能帮我实现吗?

谢谢。

最佳答案

在您的卷积中,有两件事可能不会导致崩溃。第一个是样式:您正在使用 x迭代图像的行,我更像一个 y位移,反之亦然。第二个是当你计算总和时,你没有重置变量 sum = 0在评估每个像素的内核(内部两个循环)之前。相反,你积累 sum在所有像素上,可能最终导致整数溢出。虽然严格来说这是 UB 并且可能导致崩溃,但这不是您面临的问题。

如果您确认崩溃发生在第一个像素( x = ksize/2y = ksize/2 ),那么由于崩溃发生在从内核读取的第一个系数,我怀疑您可能已经通过了“错误的事情”作为kernel .正如所介绍的,kernelint** .对于 3x3 的内核大小,这意味着要正确调用此函数,您必须在堆或堆栈上分配 int* 的数组。 ,您在其中存储了 3 个指向 int 的指针每个有 3 个系数的数组。如果您改为通过 int[3][3]数组,卷积函数将尝试解释第一个或两个 int在数组中作为指向 int 的指针当它不是时,并尝试取消引用它以引入系数。这很可能会导致段错误。

我也不知道你为什么要退回累计金额。这不是卷积的“传统”输出,但我推测您对输出图像的平均亮度感兴趣,这是合法的;在这种情况下,您应该使用单独且更宽的整数累加器( longlong long ),最后将其除以输出中的像素数。

您可能从 Internet 上找到了 PGM 数据结构,例如 here .请允许我放弃这个最佳实践建议。在我的领域(计算机视觉)中,选择的计算机视觉库 OpenCV 不会将矩阵表示为 row 的数组。指向 col 的缓冲区的指针元素。相反,分配了一大块内存,在这种情况下,大小为 image->row * image->col * sizeof(int)至少,但经常 image->row * image->step * sizeof(int)哪里image->stepimage->col四舍五入到下一个 4 或 16 的倍数。然后,只保留一个指针,一个指向整个图像底部的指针,尽管如果图像不连续,则必须保留一个额外的字段(步骤)。

因此,我将重新编写您的代码:

/* Includes */
#include <stdlib.h>



/* Defines */
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))



/* Structure */

/**
* Mat structure.
*
* Stores the number of rows and columns in the matrix, the step size
* (number of elements to jump from one row to the next; must be larger than or
* equal to the number of columns), and a pointer to the first element.
*/

typedef struct Mat{
int rows;
int cols;
int step;
int* data;
} Mat;



/* Functions */

/**
* Allocation. Allocates a matrix big enough to hold rows * cols elements.
*
* If a custom step size is wanted, it can be given. Otherwise, an invalid one
* can be given (such as 0 or -1), and the step size will be chosen
* automatically.
*
* If a pointer to existing data is provided, don't bother allocating fresh
* memory. However, in that case, rows, cols and step must all be provided and
* must be correct.
*
* @param [in] rows The number of rows of the new Mat.
* @param [in] cols The number of columns of the new Mat.
* @param [in] step The step size of the new Mat. For newly-allocated
* images (existingData == NULL), can be <= 0, in
* which case a default step size is chosen; For
* pre-existing data (existingData != NULL), must be
* provided.
* @param [in] existingData A pointer to existing data. If NULL, a fresh buffer
* is allocated; Otherwise the given data is used as
* the base pointer.
* @return An allocated Mat structure.
*/

Mat allocMat(int rows, int cols, int step, int* existingData){
Mat M;

M.rows = max(rows, 0);
M.cols = max(cols, 0);
M.step = max(step, M.cols);

if(rows <= 0 || cols <= 0){
M.data = 0;
}else if(existingData == 0){
M.data = malloc(M.rows * M.step * sizeof(*M.data));
}else{
M.data = existingData;
}

return M;
}

/**
* Convolution. Convolves input by the given kernel (centered) and stores
* to output. Does not handle boundaries (i.e., in locations near the border,
* leaves output unchanged).
*
* @param [in] input The input image.
* @param [in] kern The kernel. Both width and height must be odd.
* @param [out] output The output image.
* @return Average brightness of output.
*
* Note: None of the image buffers may overlap with each other.
*/

int convolution(const Mat* input, const Mat* kern, Mat* output){
int i, j, x, y;
int coeff, data;
int sum;
int avg;
long long acc = 0;

/* Short forms of the image dimensions */
const int iw = input ->cols, ih = input ->rows, is = input ->step;
const int kw = kern ->cols, kh = kern ->rows, ks = kern ->step;
const int ow = output->cols, oh = output->rows, os = output->step;

/* Kernel half-sizes and number of elements */
const int kw2 = kw/2, kh2 = kh/2;
const int kelem = kw*kh;

/* Left, right, top and bottom limits */
const int l = kw2,
r = max(min(iw-kw2, ow-kw2), l),
t = kh2,
b = max(min(ih-kh2, oh-kh2), t);

/* Total number of pixels */
const int totalPixels = (r-l)*(b-t);

/* Input, kernel and output base pointers */
const int* iPtr = input ->data;
const int* kPtr = kern ->data + kw2 + ks*kh2;
int* oPtr = output->data;


/* Iterate over pixels of image */
for(y=t; y<b; y++){
for(x=l; x<r; x++){
sum = 0;

/* Iterate over elements of kernel */
for(i=-kh2; i<=kh2; i++){
for(j=-kw2; j<=kw2; j++){
data = iPtr[j + is*i + x];
coeff = kPtr[j + ks*i ];
sum += data * coeff;
}
}

/* Compute average. Add to accumulator and store as output. */
avg = sum / kelem;
acc += avg;
oPtr[x] = avg;
}

/* Bump pointers by one row step. */
iPtr += is;
oPtr += os;
}

/* Compute average brightness over entire output */
if(totalPixels == 0){
avg = 0;
}else{
avg = acc/totalPixels;
}

/* Return average brightness */
return avg;
}


/**
* Main
*/

int main(int argc, char* argv[]){
/**
* Coefficients of K. Binomial 3x3, separable. Unnormalized (weight = 16).
* Step = 3.
*/

int Kcoeff[3][3] = {{1, 2, 1}, {2, 4, 2}, {1, 2, 1}};

Mat I = allocMat(1920, 1080, 0, 0);/* FullHD 1080p: 1920x1080 */
Mat O = allocMat(1920, 1080, 0, 0);/* FullHD 1080p: 1920x1080 */
Mat K = allocMat( 3, 3, 3, &Kcoeff[0][0]);

/* Fill Mat I with something.... */

/* Convolve with K... */
int avg = convolution(&I, &K, &O);

/* Do something with O... */

/* Return */
return 0;
}

引用资料:多年计算机视觉经验。

关于c - 高斯模糊、均值滤波器、卷积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19413386/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com