如何对卷积图像进行归一化?我应该吗?

How to normalize a convolved image? Should I?

提问人:JoeBass 提问时间:9/16/2015 最后编辑:Chris LoonamJoeBass 更新时间:9/17/2015 访问量:6131

问:

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

我使用的是这里指定的卷积矩阵: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

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

R 图像处理

评论


答:

1赞 Ankit Dixit 9/16/2015 #1

我认为您看到的示例不是对图像进行归一化,因此将裁剪负值,只看到正值,并且由于灰度值的非缩放,正值显示为图像中存在的最高值,而您正在归一化比例,因此不会发生灰度值的剪裁和夹紧, 一切都取决于可视化。

评论

1赞 JoeBass 9/17/2015
谢谢。你是对的。我可以通过以下代码获得您提到的剪切效果: outimg <- convolve(grayImg,edgeFilter) # 规范 1 outimg1 <- outimg - min(outimg) outimg1 <- outimg1/max(outimg1) plot(c(0,1),c(0,1),t='n') rasterImage(outimg1, 0,0,1,1) # 规范 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)
9赞 rayryeng 9/17/2015 #2

您的可视化是完全正常的。发生的情况是,您正在重新映射像素值,以便将最低强度设置为 0,将最高强度设置为 1。所有其他值都会线性重新映射以符合该范围。您可能只看到黑白的原因是由于剪切。发布这些结果的用户可能截断了动态范围,其中任何小于 0 的值都设置为 0,任何大于 1 的值(或您正在查看的数据类型的最大值)都设置为 1。[0,1]

您正在计算边缘检测,其中核/掩码具有负系数,因此您完全有可能在结果中同时获得负值和正值。以这种方式重新缩放图像,您会看到 0 的值被映射到灰色(大约 0.5 左右),因为负的最小强度被拉高到 0,这自然意味着您的 0 值被拉到某个非零数字。同样,那些非常大的值被规范化为 1。

但是,在执行规范化时,标准做法是规范化内核。原因是因为这样做可以确保每个像素的输出值永远不会超出数据类型的动态范围。通过对内核进行归一化,可以确保所有系数的权重介于内核和总和之间,并且内核的总和为 1。通过这样做,您可以确保永远不必检查输出并在必要时裁剪值。这也确保了您不需要除以每个像素的卷积代码中的权重之和,因为内核归一化步骤已经处理了归一化。您只需要规范化一次。但是,当您的内核中有负系数时,这是一项棘手的业务。如果存在负系数,则很少进行归一化。至少我在实践中看到的。[0,1]

现在,回到“黑白”的东西,如果你使用另一个过滤器......说。。。一个普通的过滤器,你肯定会得到一张“黑白”的图片,因为没有负数值。即使在将输出归一化为通过最小值-最大值方法之后。请记住,这将执行对比度拉伸,如果强度集中在范围的一小部分上,则输出将拉伸,以便最低强度降至 0,最大强度映射到 1。[0,1][0,1]

我已经修改了您的代码来执行此操作。请记住,我找不到没有轴线的原始图像,所以我拍摄了快照并将其保存为 PNG。因此,我使用了包而不是包:pngjpeg

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 附近的值将被推送到某个非零值...通常为灰色。如果指定具有负系数的内核,则会发生这种情况。如果您的内核具有严格的正系数,则不会看到任何负值,并且可视化效果符合预期。