<filter id="edge">
<feColorMatrix type="luminanceToAlpha" />
<feConvolveMatrix order="3" kernelMatrix="-1 -2 -1 0 0 0 1 2 1" />
<feConvolveMatrix order="3" kernelMatrix="-1 -2 -1 0 0 0 1 2 1" />
</filter>
在wikipedia page后,我需要一种方法来查找两个feConvolveMatrix
结果之间的距离。我可以通过合成来平方并添加它们,但似乎没有任何方法可以获得平方根运算符。有可能吗?
我在下面添加了我当前的解决方案,但它与参考资料不完全匹配。
答案 0 :(得分:1)
feDiffuseLighting
实际上会计算一个sobel过滤器来生成法线。我将以下内容放在一起,将RGB提取为三个白色图像,每个图像的R,G和B为高度图的alpha。然后使用位于图像上方的定向光提取法线的z
分量(1 - sqrt(dx^2 + dy^2)
)。最后它被反转(仅获得sqrt(dx^2 + dy^2)
)并且所有三个通道被组合。
我不太确定color-interpolation-filters="sRGB"
图像是否非常暗,所以我设置surfaceScale="8.0"
以提高增量的变化。它仍然看起来不像参考,但它很接近。此外,无论出于何种原因,过滤器向外扩展以覆盖HTML的其他部分(编辑:请参阅this)。
从this page测试图像:
.sobelme {
-webkit-filter: url('#sobel');
-moz-filter: url('#sobel');
-ms-filter: url('#sobel');
-o-filter: url('#sobel');
filter: url('#sobel');
}
<img class="sobelme" src="http://i.stack.imgur.com/sld5Y.png" />
<img src="http://i.stack.imgur.com/wq077.png" />
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="0">
<filter id="sobel" color-interpolation-filters="sRGB">
<feColorMatrix type="matrix" in="SourceGraphic" result="RA" values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
1 0 0 0 0"></feColorMatrix>
<feColorMatrix type="matrix" in="SourceGraphic" result="GA" values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 1 0 0 0"></feColorMatrix>
<feColorMatrix type="matrix" in="SourceGraphic" result="BA" values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 0 1 0 0"></feColorMatrix>
<feDiffuseLighting in="RA" result="R" surfaceScale="8.0">
<feDistantLight elevation="90"></feDistantLight>
</feDiffuseLighting>
<feDiffuseLighting in="GA" result="G" surfaceScale="8.0">
<feDistantLight elevation="90"></feDistantLight>
</feDiffuseLighting>
<feDiffuseLighting in="BA" result="B" surfaceScale="8.0">
<feDistantLight elevation="90"></feDistantLight>
</feDiffuseLighting>
<feColorMatrix type="matrix" in="R" result="RS" values="-1 0 0 0 1
0 0 0 0 0
0 0 0 0 0
0 0 0 0 1"></feColorMatrix>
<feColorMatrix type="matrix" in="G" result="GS" values="0 0 0 0 0
0 -1 0 0 1
0 0 0 0 0
0 0 0 0 1"></feColorMatrix>
<feColorMatrix type="matrix" in="B" result="BS" values="0 0 0 0 0
0 0 0 0 0
0 0 -1 0 1
0 0 0 0 1"></feColorMatrix>
<feComposite in="RS" in2="GS" result="RSGS" operator="arithmetic" k1="0" k2="1" k3="1" k4="0"></feComposite>
<feComposite in="RSGS" in2="BS" operator="arithmetic" k1="0" k2="1" k3="1" k4="0"></feComposite>
</filter>
</svg>
更新:
测试图像是一种近似值,忽略水平和垂直增量之间的距离并简单地对它们求和。使用上述feDiffuseLighting
进行正常计算的Sobel滤波器被归一化,这就是需要按比例缩放8的原因。简单地添加水平和垂直增量的绝对值,而sqrt()
类似于@MichaelMullany's answer,可以如下实现。一个优点是不会发生过滤器在边界外的恼人膨胀。 color-interpolation-filters
是必要的,否则会应用伽玛,会产生奇怪的结果。它仍然与测试图像不完全匹配,但它越来越简单。
.sobelme {
-webkit-filter: url('#sobel');
-moz-filter: url('#sobel');
-ms-filter: url('#sobel');
-o-filter: url('#sobel');
filter: url('#sobel');
}
<img class="sobelme" src="http://i.stack.imgur.com/sld5Y.png" />
<img src="http://i.stack.imgur.com/wq077.png" />
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="0">
<filter id="sobel" color-interpolation-filters="sRGB">
<feConvolveMatrix in="SourceGraphic" order="3" preserveAlpha="true" kernelMatrix="-1 -2 -1
0 0 0
1 2 1 " result="VP" />
<feConvolveMatrix in="SourceGraphic" order="3" preserveAlpha="true" kernelMatrix="1 2 1
0 0 0
-1 -2 -1 " result="VN" />
<feConvolveMatrix in="SourceGraphic" order="3" preserveAlpha="true" kernelMatrix="-1 0 1
-2 0 2
-1 0 1 " result="HP" />
<feConvolveMatrix in="SourceGraphic" order="3" preserveAlpha="true" kernelMatrix="1 0 -1
2 0 -2
1 0 -1 " result="HN" />
<feComposite operator="arithmetic" in="VN" in2="VP" k2="1" k3="1" result="V" />
<feComposite operator="arithmetic" in="HN" in2="HP" k2="1" k3="1" result="H" />
<!-- <feComposite operator="arithmetic" in="V" in2="H" k2="1" k3="1" /> -->
<feBlend mode="lighten" in="H" in2="V" />
</filter>
</svg>
答案 1 :(得分:1)
示例代码错误。这是一个使用卷积的传统索贝尔。它将通道分离出来并将它们转换为alpha,运行边缘检测,将它们重新转换回RGB并将通道重新添加到一起。要获得确切的参考结果,看起来它们会添加阈值 - 您可以使用feComponentTransfer执行此操作。
<svg width="600px" height="800px" >
<defs>
<filter id="sobel" x="0%" y="0%" width="100%" height="100%">
<!-- convert source image to luminance map-->
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
1 0 0 0 0" result="RChan" />
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 1 0 0 0" result="GChan" />
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 0 1 0 0" result="BChan" />
<!-- sobel edge detection-->
<feConvolveMatrix in="RChan" order="3" kernelMatrix="-1 -2 -1
0 0 0
1 2 1 "
result="Rhor" />
<feConvolveMatrix in="RChan" order="3" kernelMatrix="-1 0 1
-2 0 2
-1 0 1" result="Rver" />
<feComposite operator="arithmetic" k2="1" k3="1" in="Rhor" in2="Rver" />
<feColorMatrix type="matrix" values="0 0 0 1 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 1" result="rededge"/>
<feConvolveMatrix in="GChan" order="3" kernelMatrix="-1 -2 -1
0 0 0
1 2 1"
result="Ghor" />
<feConvolveMatrix in="GChan" order="3" kernelMatrix="-1 0 1
-2 0 2
-1 0 1" result="Gver" />
<feComposite operator="arithmetic" k2="1" k3="1" in="Ghor" in2="Gver" />
<feColorMatrix type="matrix" values="0 0 0 0 0
0 0 0 1 0
0 0 0 0 0
0 0 0 0 1" result="greenedge"/>
<feConvolveMatrix in="BChan" order="3" kernelMatrix="-1 -2 -1
0 0 0
1 2 1 " result="Bhor" />
<feConvolveMatrix in="BChan" order="3" kernelMatrix="-1 0 1
-2 0 2
-1 0 1" result="Bver" />
<feComposite operator="arithmetic" k2="1" k3="1" in="Bhor" in2="Bver"/>
<feColorMatrix type="matrix" values="0 0 0 0 0
0 0 0 0 0
0 0 0 1 0
0 0 0 0 1" result="blueedge"/>
<feComposite operator="arithmetic" in="blueedge" in2="rededge" k2="1" k3="1"/>
<feComposite operator="arithmetic" in2="greenedge" k2="1" k3="1" result="finaledges"/>
<feFlood flood-color="black" result="black"/>
<feComposite operator="over" in="finaledges"/>
</filter>
</defs>
<image width="400" height="300" preserveAspectRatio="xMinYMin meet" xlink:href="http://www.roborealm.com/help/Sobel_src.jpg"/>
<image filter="url(#sobel)" y="400" width="400" height="300" xlink:href="http://www.roborealm.com/help/Sobel_src.jpg"/>
</svg>