如何对卷积图像进行归一化?我需要吗?

6

我正在尝试使用卷积进行边缘检测。 我认为在卷积后需要对图像进行归一化。

我正在使用此处指定的卷积矩阵: https://en.wikipedia.org/wiki/Kernel_(image_processing)#Convolution

附上一些r代码,以及源图像和输出图像...

require(jpeg)
myjpg <- readJPEG("mtg.jpg")

grayImg <- myjpg[,,1]+myjpg[,,2]+myjpg[,,3] # reduce to gray
grayImg <- grayImg/max(grayImg) # normalize
dim(grayImg)


convolve <- function(img, f){
    newimg <- img
    radius <- as.integer(nrow(f)/2)+1
    print(radius)
    for(i in c(1:nrow(img))){
        for(j in c(1:ncol(img))){
            f_sub <- f[c(max(1,radius-i+1):min(nrow(f),nrow(img)-i+radius)),c(max(1,radius-j+1):min(ncol(f),ncol(img)-j+radius))]
            img_sub <- img[c(max(1,i-radius+1):min(nrow(img),i+radius-1)),c(max(1,j-radius+1):min(ncol(img),j+radius-1))]
            wavg <- sum(as.vector(f_sub)*as.vector(img_sub))# / sum(as.vector(f_sub)) # todo, not sure about this division
            newimg[i,j] <- wavg
        }
    }
    return(newimg)
}

edgeFilter <- matrix(c(-1,-1,-1,-1,8,-1,-1,-1,-1), ncol = 3)

outimg <- convolve(grayImg,edgeFilter)

outimg <- outimg - min(outimg)
outimg <- outimg/max(outimg)

plot(c(0,1),c(0,1),t='n')
rasterImage(outimg, 0,0,1,1)

处理前的灰度图像:

enter image description here

处理后的灰度图像:

enter image description here

我感到困惑,因为我看到的例子中,卷积后的图像是黑白的。在这里,我的卷积需要归一化,并且它不是纯黑白的。

2个回答

9
你的可视化是完全正常的。正在发生的是,您正在重新映射像素值,以便将最低强度设置为0,最高强度设置为1。所有其他值都会线性重新映射以符合[0,1]范围内的规定。您可能看到只有黑色和白色的原因是由于剪辑。发布这些结果的用户可能已截断了动态范围,在该范围内,任何小于0的值都被设置为0,任何大于1(或您正在查看的数据类型的最大值)的值都被设置为1。
您正在计算一个边缘检测,其中核/掩模具有负系数,因此您的结果可能会得到负值和正值。以那种方式重新缩放图像,您将看到值为0的值被映射为灰色(大约为0.5),因为负强度最小值被拉升到0,这自然意味着您的0值被拉升到某个非零数字。同样,那些非常大的值被归一化为1。
然而,在执行归一化时,标准做法是对核进行归一化。这样做的原因是确保每个像素的输出值不超出数据类型的动态范围。通过对核进行归一化,确保所有系数都加权在[0,1]之间,核的总和为1。这样做可以确保在需要时无需检查输出并裁剪值。这也确保您不需要在每个像素的卷积代码中除以权重总和,因为核归一化步骤已经处理了该归一化。您只需要进行一次归一化。但是,当核中存在负系数时,这就成为一个棘手的问题。如果存在负系数,则很少进行归一化...至少在我实践中所见到的。

现在,回到"黑白"的问题,如果您使用另一个滤镜,比如说平均滤镜,您肯定会得到一张"黑白"图片,因为没有任何负值...即使您通过最小-最大方法将输出归一化到[0,1]之间。请注意,这将执行对比度拉伸,如果您的强度集中在[0,1]范围的一小部分上,则输出将被拉伸,以便最低强度下降到0,最高强度映射到1。

我已经修改了您的代码来实现这一点。请注意,我找不到您原来没有轴线的原始图像,所以我拍摄了一张快照并将其保存为PNG格式。因此,我使用的是png包而不是jpeg包:

require(png) # Change
myjpg <- readPNG("mtg.png") # Change

grayImg <- myjpg[,,1]+myjpg[,,2]+myjpg[,,3] # reduce to gray
grayImg <- grayImg/max(grayImg) # normalize
dim(grayImg)


convolve <- function(img, f){
    newimg <- img
    radius <- as.integer(nrow(f)/2)+1
    print(radius)
    for(i in c(1:nrow(img))){
        for(j in c(1:ncol(img))){
            f_sub <- f[c(max(1,radius-i+1):min(nrow(f),nrow(img)-i+radius)),c(max(1,radius-j+1):min(ncol(f),ncol(img)-j+radius))]
            img_sub <- img[c(max(1,i-radius+1):min(nrow(img),i+radius-1)),c(max(1,j-radius+1):min(ncol(img),j+radius-1))]
            wavg <- sum(as.vector(f_sub)*as.vector(img_sub))# / sum(as.vector(f_sub)) # todo, not sure about this division
            newimg[i,j] <- wavg
        }
    }
    return(newimg)
}

#edgeFilter <- matrix(c(-1,-1,-1,-1,8,-1,-1,-1,-1), ncol = 3) 
averageFilter <- matrix(c(1,1,1,1,1,1,1,1,1), ncol=3) / 9# Change

#outimg <- convolve(grayImg,edgeFilter) # Change
outimg <- convolve(grayImg,averageFilter)

outimg <- outimg - min(outimg)
outimg <- outimg/max(outimg)

plot(c(0,1),c(0,1),t='n')
rasterImage(outimg, 0,0,1,1)

这是我得到的结果:

enter image description here

将此与原始图像进行比较:

enter image description here

如果你仔细盯着它看,你会发现两者之间有些模糊。如果你增加平均过滤器的大小,比如说7 x 7,你会看到更多的模糊。
averageFilter <- matrix(rep(1,49), ncol=7) / 49

这样做,我们得到的图像如下:

enter image description here

我们期望的是,当你决定通过最小-最大方式将数据标准化时,数据的动态范围将决定图像的可视化效果。如果存在负值,则可以预期,围绕0的值将被推到一些非零值,通常为灰色。如果您指定了一个带有负系数的核,这种情况就会发生。如果您有一个严格具有正系数的核,您将不会看到任何负值,可视化效果与您预期的相同。

1
我认为你所看到的示例没有对图像进行归一化处理,这会导致负值被截断,只有正值可见,并且由于灰度值未经缩放,正值显示为图像中存在的最高值。而你正在对比例尺进行归一化处理,因此没有发生灰度值的截断和夹紧,所有都取决于可视化。

1
谢谢。你说得对。我可以使用以下代码获得你提到的剪切效果:outimg <- convolve(grayImg,edgeFilter)

norm 1

outimg1 <- outimg - min(outimg) outimg1 <- outimg1/max(outimg1) plot(c(0,1),c(0,1),t='n') rasterImage(outimg1, 0,0,1,1)

norm 2

outimg2 <- ifelse(outimg < 0, 0, outimg) outimg2 <- ifelse(outimg > 1, 1, outimg2) plot(c(0,1),c(0,1),t='n') rasterImage(outimg2, 0,0,1,1)
- JoeBass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接