c" Discontinuity"高斯模糊的边缘周围的图像



我一直在尝试实现具有特定半径rs=((int)2.75*sigma+0.5)的高斯核的nxn图像的高斯模糊函数。

for (x=0;x<n;x++){
    for (y=0;y<n;y++){
        sum=0.0,wsum=0.0;
        //Position correction at the edges
        if(x-rs<0){
            ix=0;
        }
        else ix=rs;
        if(y-rs<0){
            iy=0;
        }
        else iy=rs;
        if (x+rs>n-1){
            jx=n-1-x;
        }
        else jx=rs;
        if (y+rs>n-1){
            jy=n-1-y;
        }
        else jy=rs;
        //Kernel mean value correction at the edges
        if ( x-rs < 0 ){
            meanx=x+((int)rs/2);
        }
        else meanx=x;
        if(y-rs<0){
            meany=y+((int)rs/2);
        }
        else meany=y;
        if (x+rs>n-1){
            meanx=x-((int)rs/2);
        }
        else meanx=x;
        if (y+rs>n-1){
            meany=y-((int)rs/2);
        }
        else meany=y;   

        for (i=x-ix;i<=x+jx;i++){
            for (j=y-iy;j<=y+jy;j++){
                weight=1/(2*M_PI*sigma*sigma)*exp(-((meanx-i)*(meanx-i)+(meany-j)*(meany-j))/(2*sigma*sigma));
                sum+=pic1.intenzity[i][j]*weight;
                wsum+=weight;
            }
        }
        pic2->intenzity[x][y]=((int)sum/wsum+0.5);
        fprintf(fw,"%dn",pic2->intenzity[x][y]);   
    }

当我在边缘不使用平均值校正时,结果看起来像这样:

没有平均值校正

,当我尝试移动内核的平均值时,它也在图像的下部和右侧边缘产生不连续:

的平均值移动到rs/2

我必须修正边缘位置,因为总和会溢出。现在看来,由于某种原因,当高斯卷积从x和y的上边缘和左边缘的位置为rs时,它突然跳跃。我想使它的行为方式与它在图像的"内部"中所做的相同,或者可能使强度随着位置接近边缘而减弱为0。

我可以将图像放大rs,但这会导致边缘位置出现问题。

谢谢你的帮助:)

让我们看看在伪代码中应用于图像的典型过滤器内核。让我们使用变量

# source[y][x]    Old image (read-only)
# target[y][x]    New image (write-only)
# image_height    Image height (y = 0 .. image_height-1)
# image_width     Image width (x = 0 .. image_width-1)
# filter[y][x]    Filter (weights) to be applied
# filter_height   Filter height (y = 0 .. filter_height-1)
# filter_width    Filter width (x = 0 .. filter_width-1)
# filter_y        Target pixel y coordinate in filter (filter_height/2)
# filter_x        Target pixel x coordinate in filter (filter_width/2)

,其中filter_y = floor(filter_width / 2)filter_x = floor(filter_height / 2),如果滤波器以目标像素为中心(即。对称)。伪代码大致为

For base_y = 0 to image_height - 1:
   # y range relative to base_y ...
   min_y = -filter_y
   max_y = filter_height - 1 - filter_y
   # ... must not exceed the image boundaries.
   If min_y + base_y < 0:
       min_y = -base_y
   End If
   If max_y + base_y < 0:
       max_y = -base_y
   End If
   If min_y + base_y >= image_height:
       min_y = image_height - 1 - base_y
   End If
   If max_y + base_y >= image_height:
       max_y = image_height - 1 - base_y
   End If
   For base_x = 0 to image_width - 1:
       # x range relative to base_x ...
       min_x = -filter_x
       max_x = filter_width - 1 - filter_x
       # ... must not exceed the image boundaries.
       If min_x + base_x < 0:
           min_x = -base_x
       End If
       If max_x + base_x < 0:
           max_x = -base_x
       End If
       If min_x + base_x >= image_width:
           min_x = image_width - 1 - base_x
       End If
       If max_x + base_x >= image_height:
           max_x = image_width - 1 - base_x
       End If
       ValueSum = 0
       WeightSum = 0
       For y = min_y to max_y:
           For x = min_x to max_x:
               Value = source[y + base_y][x + base_x]
               Weight = filter[y + filter_y][x + filter_x]
               ValueSum = ValueSum + Value * Weight
               WeightSum = WeightSum + Weight
           End For
        End For
        If WeightSum != 0:
            target[base_y][base_x] = ValueSum / WeightSum
        End If
    End For
End For

在最内层的循环中,[base_y][base_x]是我们正在计算的目标像素;[y+base_y][x+base_x][y+filter_y][x+filter_x]加权后的源像素。xy为相对值,取值范围为-filter_x-filter_y ~ filter_width-1-filter_xfilter_height-1-filter_y

只要ValueSumWeightSum有足够的取值范围,无论图像和过滤器数据是整数还是浮点,相同的代码都可以工作。

棘手的部分,以及引起OP看到的伪像的部分,是如何正确计算min_y, max_y, min_xmax_x

要进行调试,请删除最内层的两个循环,并打印类似

的内容。
printf("y = %d, ymin = %d (%d), ymax = %d (%d)n",
       base_y, min_y, min_y + base_y, max_y, max_y + base_y);

在外循环内(不需要为每个base_x打印它!),和

printf("x = %d, xmin = %d (%d), xmax = %d (%d)n",
       base_x, min_x, min_x + base_x, max_x, max_x + base_x);

在最内层循环一次(不需要为每个base_y再打印一次),例如if (y == 0) printf("...");。这将输出image_width + image_height行,并允许您验证您定义的范围是否正确。

在OP的情况下,在图像边缘附近的范围是不正确的;也就是说,上面伪代码对应的一些if子句计算/分配了不正确的min_xmax_xmin_ymax_y的值。

最新更新