Joe*_*ass 4 r image-processing
我试图用卷积进行边缘检测.我想我需要在卷积后对图像进行标准化.
我正在使用此处指定的卷积矩阵: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)
Run Code Online (Sandbox Code Playgroud)
处理前的灰色图像:
处理后的灰色图像:
我很困惑,因为在我看到的例子中,卷积图像是黑白的.在这里,我的卷积需要归一化,而且,它不是纯黑色和白色.
您的可视化非常正常.发生的事情是您正在重新映射像素值,以便将最低强度设置为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)
Run Code Online (Sandbox Code Playgroud)
这是我得到的:
将其与原始图像进行比较:
如果你更仔细地盯着它,你会发现两者之间存在一些模糊.如果你增加平均滤镜尺寸,你会看到更多的模糊...说... 7 x 7:
averageFilter <- matrix(rep(1,49), ncol=7) / 49
Run Code Online (Sandbox Code Playgroud)
这样做,这是我们得到的图像:
正如我们所料......更加模糊.但是,重点在于,当您决定通过min-max方式对图像进行标准化时,数据的动态范围将决定图像的可视化方式.如果存在负值,则期望大约为0的值将被推送到某个非零值...通常为灰色.如果指定具有负系数的内核,则会发生这种情况.如果您的内核具有严格的正系数,您将看不到任何负值,并且可视化与您预期的一样.
| 归档时间: |
|
| 查看次数: |
3179 次 |
| 最近记录: |