Moved IPCV1 in year1

This commit is contained in:
2024-04-09 12:07:14 +02:00
parent 60fdee47f4
commit 6609bde39a
77 changed files with 1 additions and 1 deletions

View File

@ -0,0 +1 @@
../../../ainotes.cls

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 KiB

View File

@ -0,0 +1,428 @@
<mxfile host="app.diagrams.net" modified="2024-03-03T15:35:06.773Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0" etag="uWZKu0vPefJa62H8nD4q" version="24.0.1" type="device">
<diagram name="Pagina-1" id="GgXEJ81RuVTFlW8kEIqq">
<mxGraphModel dx="683" dy="355" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="MWH0NgEk_9BQr2TDpznU-21" value="" style="endArrow=classicThin;startArrow=classicThin;html=1;rounded=0;entryX=1;entryY=0;entryDx=0;entryDy=0;exitX=1;exitY=1;exitDx=0;exitDy=0;startSize=2;endSize=2;endFill=1;startFill=1;" parent="1" source="MWH0NgEk_9BQr2TDpznU-22" target="MWH0NgEk_9BQr2TDpznU-22" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="120" y="230" as="sourcePoint" />
<mxPoint x="120" y="190" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-53" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="480" y="520" as="sourcePoint" />
<mxPoint x="480" y="360" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-52" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="520" as="sourcePoint" />
<mxPoint x="400" y="360" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-1" value="" style="endArrow=classic;html=1;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="500" as="sourcePoint" />
<mxPoint x="400" y="390" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-3" value="&lt;i&gt;U&lt;/i&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=15;fontFamily=Computer modern;" parent="jqilrqFg0j0umUQvlnIg-1" vertex="1" connectable="0">
<mxGeometry x="0.95" relative="1" as="geometry">
<mxPoint x="10" y="-5" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-2" value="" style="endArrow=classic;html=1;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="440" as="sourcePoint" />
<mxPoint x="650" y="440" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-4" value="&lt;i&gt;Z&lt;/i&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=15;fontFamily=Computer modern;" parent="jqilrqFg0j0umUQvlnIg-2" vertex="1" connectable="0">
<mxGeometry x="0.9472" y="-2" relative="1" as="geometry">
<mxPoint x="8" y="9" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-5" value="" style="endArrow=classic;html=1;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="480" y="440" as="sourcePoint" />
<mxPoint x="480" y="390" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-6" value="&lt;i&gt;X&lt;/i&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=15;fontFamily=Computer modern;" parent="jqilrqFg0j0umUQvlnIg-5" vertex="1" connectable="0">
<mxGeometry x="0.9325" relative="1" as="geometry">
<mxPoint x="10" y="-4" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-7" value="&lt;i&gt;C&lt;/i&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="477" y="414" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-8" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="470" y="430" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-9" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="590" y="370" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-10" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="390" y="470" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-13" value="" style="endArrow=none;html=1;rounded=0;dashed=1;" parent="1" source="jqilrqFg0j0umUQvlnIg-10" target="jqilrqFg0j0umUQvlnIg-9" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="420" y="450" as="sourcePoint" />
<mxPoint x="470" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-17" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;f&lt;/i&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;" parent="1" vertex="1">
<mxGeometry x="400" y="410" width="80" height="20" as="geometry" />
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-18" value="" style="endArrow=classicThin;startArrow=classicThin;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=1;startFill=1;endFill=1;startSize=3;endSize=3;" parent="1" source="jqilrqFg0j0umUQvlnIg-17" target="jqilrqFg0j0umUQvlnIg-17" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="420" y="450" as="sourcePoint" />
<mxPoint x="470" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-20" value="&lt;font style=&quot;font-size: 15px;&quot; face=&quot;Computer modern&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;M&lt;/i&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;" parent="1" vertex="1">
<mxGeometry x="570" y="350" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-21" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;m&lt;/i&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=right;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;" parent="1" vertex="1">
<mxGeometry x="400" y="480" width="20" height="10" as="geometry" />
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-23" value="&lt;i style=&quot;font-size: 15px;&quot;&gt;&lt;font style=&quot;font-size: 15px;&quot; face=&quot;Computer modern&quot;&gt;u&lt;/font&gt;&lt;/i&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;" parent="1" vertex="1">
<mxGeometry x="370" y="440" width="20" height="40" as="geometry" />
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-24" value="" style="endArrow=classicThin;startArrow=classicThin;html=1;rounded=0;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;startSize=3;endSize=3;startFill=1;endFill=1;" parent="1" source="jqilrqFg0j0umUQvlnIg-23" target="jqilrqFg0j0umUQvlnIg-23" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="450" y="460" as="sourcePoint" />
<mxPoint x="380" y="420" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-27" value="&lt;font style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;z&lt;/i&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="480" y="448" width="120" height="12" as="geometry" />
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-28" value="" style="endArrow=classicThin;startArrow=classicThin;html=1;rounded=0;exitX=0;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;strokeWidth=1;startFill=1;endFill=1;startSize=3;endSize=3;" parent="1" source="jqilrqFg0j0umUQvlnIg-27" target="jqilrqFg0j0umUQvlnIg-27" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="540" y="499.77" as="sourcePoint" />
<mxPoint x="590" y="449.77" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-29" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;x&lt;/i&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;" parent="1" vertex="1">
<mxGeometry x="610" y="380" width="20" height="60" as="geometry" />
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-30" value="" style="endArrow=classicThin;startArrow=classicThin;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;startSize=3;endSize=3;startFill=1;endFill=1;" parent="1" source="jqilrqFg0j0umUQvlnIg-29" target="jqilrqFg0j0umUQvlnIg-29" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="700" y="400" as="sourcePoint" />
<mxPoint x="630" y="360" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-31" value="" style="endArrow=none;html=1;rounded=0;dashed=1;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="600" y="440" as="sourcePoint" />
<mxPoint x="600" y="380" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-36" value="" style="endArrow=none;html=1;rounded=0;curved=1;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="506" y="440" as="sourcePoint" />
<mxPoint x="503" y="429" as="targetPoint" />
<Array as="points">
<mxPoint x="510" y="432" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-38" value="" style="endArrow=none;html=1;rounded=0;curved=1;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="460" y="450" as="sourcePoint" />
<mxPoint x="455" y="440" as="targetPoint" />
<Array as="points">
<mxPoint x="453" y="447" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-39" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="450" as="sourcePoint" />
<mxPoint x="410" y="440" as="targetPoint" />
<Array as="points">
<mxPoint x="410" y="450" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-40" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="590" y="440" as="sourcePoint" />
<mxPoint x="600" y="430" as="targetPoint" />
<Array as="points">
<mxPoint x="590" y="430" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-41" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="451" y="448" as="sourcePoint" />
<mxPoint x="459" y="445" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-42" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="503" y="435" as="sourcePoint" />
<mxPoint x="511" y="433" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-43" value="" style="endArrow=none;html=1;rounded=0;curved=1;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="468" as="sourcePoint" />
<mxPoint x="412" y="474" as="targetPoint" />
<Array as="points">
<mxPoint x="410" y="466" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-44" value="" style="endArrow=none;html=1;rounded=0;curved=1;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="588" y="386" as="sourcePoint" />
<mxPoint x="600" y="392" as="targetPoint" />
<Array as="points">
<mxPoint x="591" y="393" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-45" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="404" y="471" as="sourcePoint" />
<mxPoint x="406" y="464" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-46" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="407" y="472" as="sourcePoint" />
<mxPoint x="409" y="465" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-47" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="590" y="394" as="sourcePoint" />
<mxPoint x="593" y="387" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jqilrqFg0j0umUQvlnIg-49" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="592" y="395" as="sourcePoint" />
<mxPoint x="595" y="388" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-1" value="" style="endArrow=classic;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="170" y="220" as="sourcePoint" />
<mxPoint x="170" y="100" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-25" value="&lt;font style=&quot;font-size: 12px;&quot; face=&quot;Computer modern&quot;&gt;&lt;i&gt;Z&lt;/i&gt;&lt;/font&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="MWH0NgEk_9BQr2TDpznU-1" vertex="1" connectable="0">
<mxGeometry x="0.9248" relative="1" as="geometry">
<mxPoint x="9" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-2" value="" style="endArrow=classic;html=1;rounded=0;" parent="1" source="MWH0NgEk_9BQr2TDpznU-28" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="270" y="220" as="sourcePoint" />
<mxPoint x="270" y="100" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-26" value="&lt;font style=&quot;font-size: 12px;&quot; face=&quot;Computer modern&quot;&gt;&lt;i&gt;Z&lt;/i&gt;&lt;/font&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="MWH0NgEk_9BQr2TDpznU-2" vertex="1" connectable="0">
<mxGeometry x="0.9086" relative="1" as="geometry">
<mxPoint x="10" y="-2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-3" value="" style="endArrow=none;html=1;rounded=0;strokeWidth=2;strokeColor=#a9a9a9;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="140" y="180" as="sourcePoint" />
<mxPoint x="200" y="180" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-5" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="210" y="110" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-6" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="180" y="170" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-9" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=1;rounded=0;entryX=0.572;entryY=0.636;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="MWH0NgEk_9BQr2TDpznU-27" target="MWH0NgEk_9BQr2TDpznU-5" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="170" y="220" as="sourcePoint" />
<mxPoint x="250" y="140" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-12" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="270" y="220" as="sourcePoint" />
<mxPoint x="220" y="120" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-13" value="&lt;font style=&quot;font-size: 12px;&quot; face=&quot;Computer modern&quot;&gt;&lt;i style=&quot;font-size: 12px;&quot;&gt;p&lt;span style=&quot;font-size: 12px;&quot;&gt;&lt;sub&gt;R&lt;/sub&gt;&lt;/span&gt;&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;" parent="1" vertex="1">
<mxGeometry x="230" y="180" width="20" height="10" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-14" value="&lt;font style=&quot;font-size: 12px;&quot; face=&quot;Computer modern&quot;&gt;&lt;i style=&quot;font-size: 12px;&quot;&gt;P&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;" parent="1" vertex="1">
<mxGeometry x="210" y="100" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-15" value="&lt;font face=&quot;Computer modern&quot;&gt;&lt;i&gt;O&lt;sub&gt;L&lt;/sub&gt;&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;" parent="1" vertex="1">
<mxGeometry x="160" y="220" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-16" value="" style="endArrow=classicThin;startArrow=classicThin;html=1;rounded=0;entryX=1;entryY=1;entryDx=0;entryDy=0;exitX=0;exitY=1;exitDx=0;exitDy=0;endFill=1;startFill=1;startSize=2;endSize=2;" parent="1" source="MWH0NgEk_9BQr2TDpznU-17" target="MWH0NgEk_9BQr2TDpznU-17" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="60" y="150" as="sourcePoint" />
<mxPoint x="110" y="100" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-17" value="&lt;font face=&quot;Computer modern&quot;&gt;u&lt;sub&gt;L&lt;/sub&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="171" y="160" width="19" height="15" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-19" value="" style="endArrow=classicThin;startArrow=classicThin;html=1;rounded=0;entryX=1;entryY=1;entryDx=0;entryDy=0;exitX=0;exitY=1;exitDx=0;exitDy=0;endFill=1;startFill=1;startSize=2;endSize=2;" parent="1" source="MWH0NgEk_9BQr2TDpznU-20" target="MWH0NgEk_9BQr2TDpznU-20" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="140" y="150" as="sourcePoint" />
<mxPoint x="190" y="100" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-20" value="&lt;font style=&quot;font-size: 12px;&quot; face=&quot;Computer modern&quot;&gt;u&lt;/font&gt;&lt;font style=&quot;font-size: 12px;&quot; face=&quot;Computer modern&quot;&gt;&lt;sub&gt;R&lt;/sub&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="250" y="160" width="19" height="15" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-22" value="&lt;i&gt;&lt;font face=&quot;Computer modern&quot;&gt;f&lt;/font&gt;&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="140" y="181" width="20" height="39" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-23" value="&lt;i&gt;&lt;font face=&quot;Computer modern&quot;&gt;f&lt;/font&gt;&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="280" y="181" width="20" height="39" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-24" value="" style="endArrow=classicThin;startArrow=classicThin;html=1;rounded=0;entryX=0;entryY=0;entryDx=0;entryDy=0;exitX=0;exitY=1;exitDx=0;exitDy=0;startSize=2;endSize=2;endFill=1;startFill=1;" parent="1" source="MWH0NgEk_9BQr2TDpznU-23" target="MWH0NgEk_9BQr2TDpznU-23" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="170" y="230" as="sourcePoint" />
<mxPoint x="170" y="190" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-27" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="160.00000000000006" y="210" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-29" value="" style="endArrow=classic;html=1;rounded=0;" parent="1" target="MWH0NgEk_9BQr2TDpznU-28" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="270" y="220" as="sourcePoint" />
<mxPoint x="270" y="100" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-28" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="260.00000000000006" y="210" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-31" value="&lt;font style=&quot;font-size: 12px;&quot; face=&quot;Computer modern&quot;&gt;&lt;i style=&quot;font-size: 12px;&quot;&gt;p&lt;/i&gt;&lt;/font&gt;&lt;font style=&quot;font-size: 12px;&quot; face=&quot;onwhB2ShiSGjldjbIV3a&quot;&gt;&lt;span style=&quot;font-size: 12px;&quot;&gt;&lt;sub&gt;L&lt;/sub&gt;&lt;/span&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;" parent="1" vertex="1">
<mxGeometry x="190" y="180" width="20" height="10" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-32" value="&lt;font face=&quot;Computer modern&quot;&gt;&lt;i&gt;O&lt;sub&gt;R&lt;/sub&gt;&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;" parent="1" vertex="1">
<mxGeometry x="260" y="220" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-33" value="" style="endArrow=classic;html=1;rounded=0;" parent="1" source="MWH0NgEk_9BQr2TDpznU-27" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="200" y="230" as="sourcePoint" />
<mxPoint x="200" y="220" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-36" value="&lt;font size=&quot;1&quot; face=&quot;Computer modern&quot;&gt;&lt;i style=&quot;font-size: 12px;&quot;&gt;X&lt;sub&gt;L&lt;/sub&gt;&lt;/i&gt;&lt;/font&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="MWH0NgEk_9BQr2TDpznU-33" vertex="1" connectable="0">
<mxGeometry x="0.6285" relative="1" as="geometry">
<mxPoint x="13" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-34" value="" style="endArrow=classic;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="270" y="220" as="sourcePoint" />
<mxPoint x="300" y="220" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-37" value="&lt;font size=&quot;1&quot; face=&quot;Computer modern&quot;&gt;&lt;i style=&quot;font-size: 12px;&quot;&gt;X&lt;sub&gt;R&lt;/sub&gt;&lt;/i&gt;&lt;/font&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="MWH0NgEk_9BQr2TDpznU-34" vertex="1" connectable="0">
<mxGeometry x="0.6932" relative="1" as="geometry">
<mxPoint x="13" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-38" value="" style="endArrow=none;html=1;rounded=0;strokeWidth=2;strokeColor=#a9a9a9;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="240" y="180" as="sourcePoint" />
<mxPoint x="300" y="180" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-39" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="240" y="170" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-42" value="" style="endArrow=classicThin;startArrow=classicThin;html=1;rounded=0;entryX=1;entryY=0;entryDx=0;entryDy=0;exitX=0;exitY=0;exitDx=0;exitDy=0;endFill=1;startFill=1;startSize=2;endSize=2;" parent="1" source="MWH0NgEk_9BQr2TDpznU-43" target="MWH0NgEk_9BQr2TDpznU-43" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="110" y="230" as="sourcePoint" />
<mxPoint x="160" y="180" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="MWH0NgEk_9BQr2TDpznU-43" value="&lt;i&gt;&lt;font face=&quot;Computer modern&quot;&gt;b&lt;/font&gt;&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="170" y="240" width="99" height="15" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-1" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="540" y="240.5" as="sourcePoint" />
<mxPoint x="580" y="160.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-2" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="620" y="240" as="sourcePoint" />
<mxPoint x="640" y="170" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-4" value="Scene" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="520" y="140" width="80" height="20" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-5" value="Image plane" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="600" y="140" width="80" height="20" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-7" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="540" y="210" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-8" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="550" y="191" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-9" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="560" y="169" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-11" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="615" y="214" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-12" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="620" y="194" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-13" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;" parent="1" vertex="1">
<mxGeometry x="626" y="174" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-14" value="A" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="535" y="213" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-15" value="B" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="545" y="195.5" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-16" value="C" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="555" y="174" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-17" value="&lt;i&gt;a&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="612" y="217" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-18" value="&lt;i&gt;b&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="616" y="198" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-19" value="&lt;i&gt;c&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="622" y="177" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-20" value="L" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="580" y="159" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="T8Tfs2-oFsVKp512B4FH-21" value="&lt;i&gt;l&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="640" y="160" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="bci8e8O8bjfQftyRj0IN-1" value="&lt;i&gt;I&lt;/i&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=15;fontFamily=Computer modern;" vertex="1" connectable="0" parent="1">
<mxGeometry x="400" y="349.9966666666666" as="geometry" />
</mxCell>
<mxCell id="bci8e8O8bjfQftyRj0IN-2" value="&lt;i&gt;F&lt;/i&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=15;fontFamily=Computer modern;" vertex="1" connectable="0" parent="1">
<mxGeometry x="480" y="349.9966666666666" as="geometry">
<mxPoint x="2" y="-2" as="offset" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 985 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 KiB

View File

@ -0,0 +1,280 @@
<mxfile host="Electron" modified="2024-03-04T18:04:54.042Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/23.1.5 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="tQZIvrMAFS83YKa2A9_s" version="23.1.5" type="device">
<diagram name="Pagina-1" id="GgXEJ81RuVTFlW8kEIqq">
<mxGraphModel dx="1157" dy="697" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="pmmMXLmlx97vjJLDtDmT-40" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 4;strokeWidth=1;rounded=0;strokeColor=#a9a9a9;fontSize=15;fontFamily=Computer modern;" parent="1" edge="1" source="pmmMXLmlx97vjJLDtDmT-38">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="289.67" y="400" as="sourcePoint" />
<mxPoint x="289.67" y="240" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-1" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 2;strokeWidth=1;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="280" y="320" as="sourcePoint" />
<mxPoint x="520" y="320" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-3" value="" style="endArrow=none;html=1;rounded=0;strokeWidth=2;strokeColor=#a9a9a9;fontSize=15;fontFamily=Computer modern;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="290" y="370" as="sourcePoint" />
<mxPoint x="290" y="270" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-4" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 4;strokeWidth=1;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="400" as="sourcePoint" />
<mxPoint x="400" y="240" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-5" value="" style="ellipse;whiteSpace=wrap;html=1;fillColor=none;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="385" y="250" width="30" height="140" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-6" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="390" y="310" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-7" value="&lt;i style=&quot;font-size: 15px;&quot;&gt;&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;C&lt;/font&gt;&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="388" y="307" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-8" value="" style="endArrow=none;dashed=1;html=1;strokeWidth=2;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="500" y="400" as="sourcePoint" />
<mxPoint x="500" y="240" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-9" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="490" y="280" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-12" value="" style="endArrow=none;html=1;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" source="pmmMXLmlx97vjJLDtDmT-15" target="pmmMXLmlx97vjJLDtDmT-9" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="290" y="354" as="sourcePoint" />
<mxPoint x="490" y="310" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-13" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;p&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="277" y="343" width="10" height="18" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-14" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;P&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="505" y="280" width="10" height="18" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-15" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="280" y="344" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-17" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;Optical axis&lt;br style=&quot;font-size: 15px;&quot;&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=top;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="200" y="305.25" width="77" height="27.5" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-22" value="" style="endArrow=none;html=1;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" target="pmmMXLmlx97vjJLDtDmT-9" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="290" as="sourcePoint" />
<mxPoint x="460" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-23" value="" style="endArrow=none;html=1;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" source="pmmMXLmlx97vjJLDtDmT-15" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="340" y="320" as="sourcePoint" />
<mxPoint x="400" y="290" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-24" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="340" y="310" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-25" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;F&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="338" y="307" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-27" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;Deflected&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#ff0000;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="430" y="250" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-28" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;Undeflected&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#ff0000;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="410" y="348" width="90" height="16" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-29" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=0.906;entryY=0.747;entryDx=0;entryDy=0;entryPerimeter=0;startSize=2;endSize=2;strokeColor=#ff0000;fontSize=15;fontFamily=Computer modern;" parent="1" source="pmmMXLmlx97vjJLDtDmT-28" target="pmmMXLmlx97vjJLDtDmT-6" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="390" y="350" as="sourcePoint" />
<mxPoint x="440" y="300" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-30" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;startSize=2;endSize=2;strokeColor=#ff0000;fontSize=15;fontFamily=Computer modern;" parent="1" source="pmmMXLmlx97vjJLDtDmT-27" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="460" y="358" as="sourcePoint" />
<mxPoint x="400" y="290" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-31" value="&lt;i style=&quot;font-size: 15px;&quot;&gt;&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;i&lt;/font&gt;&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="290" y="370" width="110" height="24" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-32" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;startSize=4;endSize=4;fontSize=15;fontFamily=Computer modern;" parent="1" source="pmmMXLmlx97vjJLDtDmT-31" target="pmmMXLmlx97vjJLDtDmT-31" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="380" y="350" as="sourcePoint" />
<mxPoint x="430" y="300" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-34" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;o&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="400" y="370" width="100" height="24" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-35" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;startSize=4;endSize=4;fontSize=15;fontFamily=Computer modern;" parent="1" source="pmmMXLmlx97vjJLDtDmT-34" target="pmmMXLmlx97vjJLDtDmT-34" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="490" y="350" as="sourcePoint" />
<mxPoint x="540" y="300" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-36" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;f&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="350" y="230.33" width="50" height="19.67" as="geometry" />
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-37" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;startSize=4;endSize=4;fontSize=15;fontFamily=Computer modern;" parent="1" source="pmmMXLmlx97vjJLDtDmT-36" target="pmmMXLmlx97vjJLDtDmT-36" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="380" y="205.67" as="sourcePoint" />
<mxPoint x="430" y="155.67" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-43" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 4;strokeWidth=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=15;fontFamily=Computer modern;" parent="1" source="pmmMXLmlx97vjJLDtDmT-24" target="pmmMXLmlx97vjJLDtDmT-36" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="410" y="410" as="sourcePoint" />
<mxPoint x="410" y="250" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-1" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 4;strokeWidth=1;rounded=0;strokeColor=#a9a9a9;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1" target="pmmMXLmlx97vjJLDtDmT-38">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="289.67" y="400" as="sourcePoint" />
<mxPoint x="289.67" y="240" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pmmMXLmlx97vjJLDtDmT-38" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;I&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" parent="1" vertex="1">
<mxGeometry x="285" y="255" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-14" value="" style="endArrow=none;html=1;rounded=0;strokeWidth=2;strokeColor=#a9a9a9;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="200" y="730" as="sourcePoint" />
<mxPoint x="200" y="630" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-16" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 2;strokeWidth=1;rounded=0;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="190" y="680" as="sourcePoint" />
<mxPoint x="330" y="680" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-19" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;F&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="186" y="665" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-20" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 4;strokeWidth=1;rounded=0;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="250" y="759.67" as="sourcePoint" />
<mxPoint x="250" y="599.67" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-21" value="" style="ellipse;whiteSpace=wrap;html=1;fillColor=none;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="235" y="609.67" width="30" height="140" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-22" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="240" y="669.67" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-23" value="&lt;i style=&quot;font-size: 15px;&quot;&gt;&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;C&lt;/font&gt;&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="238" y="666.67" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-26" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;f&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="200" y="590" width="50" height="19.67" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-27" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;startSize=4;endSize=4;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1" source="xgRp6pG1FlOqtS_8AdJS-26" target="xgRp6pG1FlOqtS_8AdJS-26">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="230" y="565.34" as="sourcePoint" />
<mxPoint x="280" y="515.34" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-29" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 4;strokeWidth=1;rounded=0;strokeColor=#a9a9a9;fontSize=15;fontFamily=Computer modern;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" target="xgRp6pG1FlOqtS_8AdJS-26">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="200" y="760" as="sourcePoint" />
<mxPoint x="199.99999999999997" y="609.67" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-31" value="&lt;i style=&quot;font-size: 15px;&quot;&gt;&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;i&lt;/font&gt;&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="200" y="734" width="50" height="24" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-32" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;startSize=4;endSize=4;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1" source="xgRp6pG1FlOqtS_8AdJS-31" target="xgRp6pG1FlOqtS_8AdJS-31">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="230" y="714" as="sourcePoint" />
<mxPoint x="280" y="664" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-33" value="" style="endArrow=none;html=1;rounded=0;strokeWidth=2;strokeColor=#a9a9a9;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="412" y="730" as="sourcePoint" />
<mxPoint x="412" y="630" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-35" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="450" y="669.5" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-36" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;F&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="449" y="665" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-37" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 4;strokeWidth=1;rounded=0;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="508.65999999999997" y="759.67" as="sourcePoint" />
<mxPoint x="508.65999999999997" y="599.67" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-38" value="" style="ellipse;whiteSpace=wrap;html=1;fillColor=none;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="494" y="609.67" width="30" height="140" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-39" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="499" y="669.67" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-40" value="&lt;i style=&quot;font-size: 15px;&quot;&gt;&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;C&lt;/font&gt;&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="497" y="666.67" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-41" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;f&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="459" y="590" width="50" height="19.67" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-42" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;startSize=4;endSize=4;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1" source="xgRp6pG1FlOqtS_8AdJS-41" target="xgRp6pG1FlOqtS_8AdJS-41">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="489" y="565.34" as="sourcePoint" />
<mxPoint x="539" y="515.34" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-43" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 4;strokeWidth=1;rounded=0;strokeColor=#a9a9a9;fontSize=15;fontFamily=Computer modern;exitX=0;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xgRp6pG1FlOqtS_8AdJS-44">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="414" y="758" as="sourcePoint" />
<mxPoint x="412" y="598" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-44" value="&lt;i style=&quot;font-size: 15px;&quot;&gt;&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;i&lt;/font&gt;&lt;/i&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="412" y="734" width="98" height="24" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-45" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;startSize=4;endSize=4;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1" source="xgRp6pG1FlOqtS_8AdJS-44" target="xgRp6pG1FlOqtS_8AdJS-44">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="442" y="714" as="sourcePoint" />
<mxPoint x="492" y="664" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-46" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 4;strokeWidth=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="459.83" y="676.67" as="sourcePoint" />
<mxPoint x="459.83" y="596.67" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-48" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;I&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="190" y="620" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-49" value="&lt;font face=&quot;Computer modern&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;i style=&quot;font-size: 15px;&quot;&gt;I&lt;/i&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="400" y="620" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-51" value="" style="endArrow=block;html=1;rounded=0;startSize=4;endSize=4;endFill=1;strokeColor=#ff0000;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="430" y="680" as="sourcePoint" />
<mxPoint x="480" y="680" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-52" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 2;strokeWidth=1;rounded=0;fontSize=15;fontFamily=Computer modern;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="679.47" as="sourcePoint" />
<mxPoint x="540" y="680" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="xgRp6pG1FlOqtS_8AdJS-18" value="" style="shape=waypoint;sketch=0;fillStyle=solid;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;fontSize=15;fontFamily=Computer modern;" vertex="1" parent="1">
<mxGeometry x="190" y="669.5" width="20" height="20" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -0,0 +1,22 @@
\documentclass[11pt]{ainotes}
\usepackage{biblatex}
\addbibresource{./references.bib}
\title{Image Processing and Computer Vision\\(Module 1)}
\date{2023 -- 2024}
\def\lastupdate{{PLACEHOLDER-LAST-UPDATE}}
\begin{document}
\makenotesfront
\input{./sections/_image_acquisition.tex}
\input{./sections/_spatial_filtering.tex}
\input{./sections/_edge_detection.tex}
\input{./sections/_local_features.tex}
\input{./sections/_instance_obj_detection.tex}
\eoc
\printbibliography[heading=bibintoc]
\end{document}

View File

@ -0,0 +1,49 @@
@misc{ wiki:1d_convolution,
title = "Convolution --- {Wikipedia}{,} The Free Encyclopedia",
author = "{Wikipedia contributors}",
year = "2024",
howpublished = "\url{https://en.wikipedia.org/w/index.php?title=Convolution&oldid=1212399231}"
}
@misc{ wiki:dirac,
title = "Dirac delta function --- {Wikipedia}{,} The Free Encyclopedia",
author = "{Wikipedia contributors}",
year = "2024",
howpublished = "\url{https://en.wikipedia.org/w/index.php?title=Dirac_delta_function&oldid=1198785224}"
}
@misc{ wiki:kronecker,
title = "Kronecker delta --- {Wikipedia}{,} The Free Encyclopedia",
author = "{Wikipedia contributors}",
year = "2023",
howpublished = "\url{https://en.wikipedia.org/w/index.php?title=Kronecker_delta&oldid=1192529815}"
}
@book{ book:sonka,
title={Image Processing, Analysis, and Machine Vision},
author={Sonka, M. and Hlavac, V. and Boyle, R.},
isbn={978-1-133-59360-7},
year={2015},
publisher={Cengage Learning}
}
@misc{ slides:filters,
title = {Filters},
author={Ramani Duraiswami},
howpublished = {\url{http://users.umiacs.umd.edu/~ramani/cmsc828d_audio/Filters.pdf}},
year = {2006}
}
@misc{ wiki:crosscorrelation,
title = "Cross-correlation --- {Wikipedia}{,} The Free Encyclopedia",
author = "{Wikipedia contributors}",
year = "2024",
howpublished = "\url{https://en.wikipedia.org/w/index.php?title=Cross-correlation&oldid=1193503271}"
}
@misc{ slides:scale_normalized_log,
title = {Blob features},
author={Trym Vegard Haavardsholm},
howpublished = {\url{https://www.uio.no/studier/emner/matnat/its/TEK5030/v20/forelesninger/lecture_3_2_2_blob_features.pdf}},
year = {2020}
}

View File

@ -0,0 +1,391 @@
\chapter{Edge detection}
\begin{description}
\item[Edge] \marginnote{Edge}
Pixel lying in between regions of the image with different intensities.
\end{description}
\section{Gradient thresholding}
\subsection{1D step-edge}
\marginnote{1D step-edge}
In the transition region, the absolute value of the first derivative grows (the absolute value is used as the polarity is not relevant).
By fixing a threshold, an edge can be detected.
\begin{figure}[H]
\begin{subfigure}{0.4\linewidth}
\centering
\includegraphics[width=0.5\linewidth]{./img/1d_step_edge_example1.png}
\caption{Input signal}
\end{subfigure}
\begin{subfigure}{0.4\linewidth}
\centering
\includegraphics[width=0.5\linewidth]{./img/1d_step_edge_example2.png}
\caption{Derivative of the signal}
\end{subfigure}
\end{figure}
\subsection{2D step-edge}
\marginnote{2D step-edge}
In a 2D signal (e.g. an image), the gradient allows to determine the magnitude and the direction of the edge.
\[
\nabla I(x, y) =
\begin{pmatrix} \frac{\partial I(x, y)}{\partial x} & \frac{\partial I(x, y)}{\partial y} \end{pmatrix} =
\begin{pmatrix} \partial_x I & \partial_y I \end{pmatrix}
\]
\[
\begin{split}
\text{Magnitude: } & \Vert \nabla I(x, y) \Vert \\
\text{Direction: } & \arctan\left(\frac{\partial_y I}{\partial_x I}\right) \in [-\frac{\pi}{2}, \frac{\pi}{2}] \\
\text{Direction and sign: } & \arctan2(\partial_x I, \partial_y I) \in [0, 2\pi] \\
\end{split}
\]
\begin{description}
\item[Discrete gradient approximation] \marginnote{Discrete gradient approximation}
Approximation of the partial derivatives as a difference.
\begin{description}
\item[Backward difference] \marginnote{Backward difference}
\[ \partial_x I(i, j) \approx I(i, j) - I(i, j-1) \hspace{3em} \partial_y I(i, j) \approx I(i, j) - I(i-1, j) \]
\item[Forward difference] \marginnote{Forward difference}
\[ \partial_x I(i, j) \approx I(i, j+1) - I(i, j) \hspace{3em} \partial_y I(i, j) \approx I(i+1, j) - I(i, j) \]
\begin{remark}
Forward and backward differences are equivalent to applying two cross-correlations with kernels
$\begin{pmatrix} -1 & 1 \end{pmatrix}$ and $\begin{pmatrix} -1 \\ 1 \end{pmatrix}$.
\end{remark}
\item[Central difference] \marginnote{Central difference}
\[ \partial_x I(i, j) \approx I(i, j+1) - I(i, j-1) \hspace{3em} \partial_y I(i, j) \approx I(i+1, j) - I(i-1, j) \]
\begin{remark}
Central difference is equivalent to applying two cross-correlations with kernels
$\begin{pmatrix} -1 & 0 & 1 \end{pmatrix}$ and $\begin{pmatrix} -1 \\ 0 \\ 1 \end{pmatrix}$.
\end{remark}
\end{description}
\item[Discete magnitude approximation] \marginnote{Discete magnitude approximation}
The gradient magnitude can be approximated using the approximated partial derivatives:
\[
\Vert \nabla I \Vert = \sqrt{(\partial_x I)^2 + (\partial_y I)^2} \hspace{1.5em}
\Vert \nabla I \Vert_+ = \vert \partial_x I \vert + \vert \partial_y I \vert \hspace{1.5em}
\Vert \nabla I \Vert_\text{max} = \max(\vert \partial_x I \vert, \vert \partial_y I \vert)
\]
Among all, $\Vert \nabla I \Vert_\text{max}$ is the most isotropic (i.e. gives a more consistent response).
\begin{example}
Given the following images:
\[
E_v = \begin{pmatrix}
0 & 0 & h & h \\
0 & 0 & h & h \\
0 & 0 & h & h \\
0 & 0 & h & h \\
\end{pmatrix}
\,\,\,
E_h = \begin{pmatrix}
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 \\
h & h & h & h \\
h & h & h & h \\
\end{pmatrix}
\,\,\,
E_d = \begin{pmatrix}
0 & 0 & 0 & 0 & h \\
0 & 0 & 0 & h & h \\
0 & 0 & h & h & h \\
0 & h & h & h & h \\
\end{pmatrix}
\]
The magnitudes are:
\begin{center}
\begin{tabular}{c|ccc}
\toprule
& $\Vert \nabla I \Vert$ & $\Vert \nabla I \Vert_+$ & $\Vert \nabla I \Vert_\text{max}$ \\
\midrule
$E_h$ & $h$ & $h$ & $h$ \\
$E_v$ & $h$ & $h$ & $h$ \\
$E_d$ & $\sqrt{2}h$ & $2h$ & $h$ \\
\bottomrule
\end{tabular}
\end{center}
\end{example}
\end{description}
\begin{remark}
In practice, the signal of an image is not always smooth due to noise.
Derivatives amplify noise and are therefore unable to recognize edges.
Smoothing the signal before computing the derivative allows to reduce the noise but also blurs the edges making it more difficult to localize them.
A solution is to smooth and differentiate in a single operation by approximating the gradient as a difference of averages.
\end{remark}
\begin{description}
\item[Smooth derivative] \marginnote{Smooth derivative}
Compute the approximation of a partial derivative as the difference of the pixels in a given window.
For instance, considering a window of 3 pixels, the cross-correlation kernels are:
\[ \frac{1}{3} \begin{pmatrix} -1 & 1 \\ -1 & 1 \\ -1 & 1 \end{pmatrix} \hspace{3em} \frac{1}{3} \begin{pmatrix} -1 & -1 & -1 \\ 1 & 1 & 1 \end{pmatrix} \]
\begin{description}
\item[Prewitt operator] \marginnote{Prewitt operator}
Derivative approximation using central differences.
The cross-correlation kernels are:
\[
\frac{1}{3} \begin{pmatrix} -1 & 0 & 1 \\ -1 & 0 & 1 \\ -1 & 0 & 1 \end{pmatrix}
\hspace{3em}
\frac{1}{3} \begin{pmatrix} -1 & -1 & -1 \\ 0 & 0 & 0 \\ 1 & 1 & 1 \end{pmatrix}
\]
\item[Sobel operator] \marginnote{Sobel operator}
Prewitt operator where the central pixels have a higher weight.
The cross-correlation kernels are:
\[
\frac{1}{4} \begin{pmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{pmatrix}
\hspace{3em}
\frac{1}{4} \begin{pmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \end{pmatrix}
\]
\end{description}
\end{description}
\begin{remark}
Thresholding is inaccurate as choosing the threshold is not straightforward.
An image has strong and weak edges. Trying to detect one type might lead to poor detection of the other.
A better solution is to find a local maxima of the absolute value of the derivatives.
\end{remark}
\section{Non-maxima suppression (NMS)}
\marginnote{Non-maxima suppression (NMS)}
Algorithm that looks for local maxima of the absolute value of the gradient along the gradient direction.
The algorithm works as follows:
\begin{enumerate}
\item Given a pixel at coordinates $(i, j)$,
estimate the magnitude $G = \Vert \nabla I(i, j) \Vert$ and the direction $\theta$ of the gradient.
\item Consider two points $A$ and $B$ along the direction $\theta$ passing through $(i, j)$
and compute their gradient magnitudes $G_A$ and $G_B$.
\item Substitute the pixel $(i, j)$ as follows:
\[ \texttt{NMS}(i, j) = \begin{cases}
1 & (G > G_A) \land (G > G_B) \text{ (i.e. local maximum)} \\
0 & \text{otherwise} \\
\end{cases} \]
\end{enumerate}
\begin{remark}
After applying NMS, the resulting signal (now composed of 0s and 1s) is converted back to the original gradient magnitudes
in such a way that pixels 0ed by NMS remain 0 and pixels set at 1 by NMS return to their original value.
After the conversion, a thresholding step might be applied to filter out unwanted edges that are either due to noise or not relevant.
\end{remark}
\subsection{Linear interpolation}
As there might not be two points $A$ and $B$ along the direction $\theta$ belonging the the discrete pixel grid
and because one doesn't want to consider two points too far from $(i, j)$,
it is possible to use linear interpolation to estimate the gradients of $A$ and $B$ even if off-grid by an offset $\Delta x$:\\
\begin{minipage}{0.6\linewidth}
\[
\begin{split}
G_1 &= \Vert \nabla I(i-1, j) \Vert \hspace{2em} G_2 = \Vert \nabla I(i-1, j+1) \Vert \\
G_3 &= \Vert \nabla I(i+1, j) \Vert \hspace{2em} G_4 = \Vert \nabla I(i+1, j-1) \Vert \\
\end{split}
\]
\[
\begin{split}
G_A &\approx G1 + (G2 - G1)\Delta x \\
G_B &\approx G3 - (G3 - G4)\Delta x \\
\end{split}
\]
\end{minipage}
\begin{minipage}{0.35\linewidth}
\centering
\includegraphics[width=\linewidth]{./img/_nms_interpolation.pdf}
\end{minipage}
\section{Canny's edge detector}
Method based on three criteria:
\begin{descriptionlist}
\item[Good detection] Correctly detect edges in noisy images.
\item[Good localization] Minimize the distance between the found edges and the true edges.
\item[One response to one edge] Detect only one pixel at each true edge.
\end{descriptionlist}
In the 1D case, the optimal operator consists in finding the local extrema of the
signal obtained by convolving the image and the Gaussian first-order derivative.
Generalized for the 2D case, Canny's edge detector does the following: \marginnote{Canny's edge detector}
\begin{enumerate}
\item Gaussian smoothing.
\item Gradient computation.
\item NMS and thresholding.
\end{enumerate}
It is possible to exploit the convolutions property of being commutative w.r.t. differentiation
and simplify the smoothing and gradient computation:
\[
\begin{split}
\partial_x I(x, y) &= \frac{\partial}{\partial x} ( I(x, y) * G(x, y) ) = I(x, y) * \frac{\partial G(x, y)}{\partial x} \\
\partial_y I(x, y) &= \frac{\partial}{\partial y} ( I(x, y) * G(x, y) ) = I(x, y) * \frac{\partial G(x, y)}{\partial y}
\end{split}
\]
By leveraging the separability of a 2D Gaussian ($G(x, y) = G_1(x)G_2(y)$),
the computation can be reduced to 1D convolutions:
\[
\begin{split}
\partial_x I(x, y) &= I(x, y) * (G_1'(x)G_2(y)) = (I(x, y) * G_1'(x)) * G_2(y) \\
\partial_y I(x, y) &= I(x, y) * (G_1(x)G_2'(y)) = (I(x, y) * G_1(x)) * G_2'(y)
\end{split}
\]
\begin{remark}
When magnitude varies along the object contour, thresholding might remove true edges (edge streaking).
\end{remark}
\begin{description}
\item[Hysteresis thresholding] \marginnote{Hysteresis thresholding}
Given a high threshold $T_\text{h}$ and a low threshold $T_\text{l}$,
depending on its magnitude, a pixel $(i, j)$ can be considered a:
\begin{descriptionlist}
\item[Strong edge] $\nabla I(i, j) > T_h$.
\item[Weak edge] $\nabla I(i, j) > T_l$ and the pixel $(i, j)$ is a neighbor of a strong/weak edge.
\end{descriptionlist}
In practice, the algorithm starts from strong edges and "propagates" them.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\linewidth]{./img/hysteresis thresholding.png}
\caption{Application of hysteresis thresholding}
\end{figure}
\end{description}
\begin{remark}
The output of Canny's edge detector is not an image with edges but a list of edges.
Note that if the edges of two objects intersect, this will be recognized as a single edge.
\end{remark}
\section{Zero-crossing edge detector}
\begin{description}
\item[Zero-crossing edge detector] \marginnote{Zero-crossing}
Detect edges by finding zero-crossing of the second derivative of the signal.
\begin{remark}
A zero-crossing is a point at 0 where the function changes sign.
\end{remark}
\begin{remark}
This approach does not require a threshold anymore but is computationally more expensive.
\end{remark}
\begin{figure}[H]
\centering
\begin{subfigure}{0.3\linewidth}
\centering
\includegraphics[width=\linewidth]{./img/zero_crossing_example1.png}
\caption{Input signal}
\end{subfigure}
\begin{subfigure}{0.3\linewidth}
\centering
\includegraphics[width=\linewidth]{./img/zero_crossing_example2.png}
\caption{First-order derivative}
\end{subfigure}
\begin{subfigure}{0.3\linewidth}
\centering
\includegraphics[width=\linewidth]{./img/zero_crossing_example3.png}
\caption{Second-order derivative}
\end{subfigure}
\end{figure}
\item[Laplacian] \marginnote{Laplacian}
Approximation of the second-order derivative:
\[ \nabla^2 I(x, y) \approx \frac{\partial^2 I(x, y)}{\partial x^2} + \frac{\partial^2 I(x, y)}{\partial y^2} = \partial_{x,x} I + \partial_{y, y} I \]
\item[Discrete Laplacian] \marginnote{Discrete Laplacian}
Use forward difference to compute first-order derivatives,
followed by backward difference to compute second-order derivatives.
\[
\begin{split}
\partial_{x,x} I(i, j) &\approx \partial_x I(i, j) - \partial_x I(i, j-1) \\
&= \big ( I(i, j+1) - I(i, j) \big) - \big ( I(i, j) - I(i, j-1) \big) \\
&= I(i, j+1) - 2I(i, j) + I(i, j-1)
\end{split}
\]
\[
\begin{split}
\partial_{y,y} I(i, j) &\approx \partial_y I(i, j) - \partial_y I(i-1, j) \\
&= \big ( I(i+1, j) - I(i, j) \big) - \big ( I(i, j) - I(i-1, j) \big) \\
&= I(i+1, j) - 2I(i, j) + I(i-1, j)
\end{split}
\]
This is equivalent to applying the cross-correlation kernel:
\[
\nabla^2 = \begin{pmatrix}
0 & 1 & 0 \\
1 & -4 & 1 \\
0 & 1 & 0 \\
\end{pmatrix}
\]
\begin{remark}
It can be shown that zero-crossings of the Laplacian typically lay close to those of the second-order derivative.
\end{remark}
\end{description}
\subsection{Laplacian of Gaussian (LoG)}
Laplacian of Gaussian (LoG) does the following: \marginnote{Laplacian of Gaussian (LoG)}
\begin{enumerate}
\item Gaussian smoothing.
\item Second-order differentiation using the Laplacian filter.
\item Zero-crossings extraction.
\end{enumerate}
\begin{description}
\item[Discrete zero-crossing]
As the image consists of a discrete grid of pixels, finding a zero-crossing as per definition is not always possible.
Instead, an edge is detected when there is a change of sign in the magnitude.
The edge pixel can be identified as:
\begin{itemize}
\item The pixel where the magnitude is positive.
\item The pixel where the magnitude is negative.
\item The pixel where the absolute value of the magnitude is smaller.
This is usually the best choice as it is closer to the true zero-crossing.
\end{itemize}
\end{description}
\begin{remark}
A final thresholding might still be useful to remove uninteresting edges.
\end{remark}
\begin{remark}
Smaller values of $\sigma$ of the smoothing operator detect more detailed edges,
while higher $\sigma$ captures more general edges.
\end{remark}
\begin{figure}[H]
\centering
\includegraphics[width=0.8\linewidth]{./img/_example_laplacian_gaussian.pdf}
\end{figure}

View File

@ -0,0 +1,532 @@
\chapter{Image acquisition and formation}
\section{Pinhole camera}
\begin{description}
\item[Imaging device] \marginnote{Imaging device}
Gathers the light reflected by 3D objects in a scene and creates a 2D representation of them.
\item[Computer vision] \marginnote{Computer vision}
Infer knowledge of the 3D scene from 2D digital images.
\end{description}
\begin{description}
\item[Pinhole camera] \marginnote{Pinhole camera}
Imaging device where the light passes through a small pinhole and hits the image plane.
Geometrically, the image is obtained by drawing straight rays from the scene to the image plane passing through the pinhole.
\begin{remark}
Larger aperture size of the pinhole results in blurry images (circle of confusion),
while smaller aperture results in sharper images but requires longer exposure time (as less light passes through).
\end{remark}
\begin{remark}
The pinhole camera is a good approximation of the geometry of the image formation mechanism of modern imaging devices.
\end{remark}
\begin{figure}[h]
\begin{subfigure}{.4\textwidth}
\centering
\includegraphics[width=0.8\linewidth]{./img/pinhole.png}
\caption{Pinhole camera model}
\end{subfigure}
\begin{subfigure}{.45\textwidth}
\centering
\includegraphics[width=0.7\linewidth]{./img/pinhole_hole_size.png}
\caption{Images with varying pinhole aperture size}
\end{subfigure}
\end{figure}
\end{description}
\section{Perspective projection}
\marginnote{Perspective projection}
Geometric model of a pinhole camera.\\
\begin{minipage}{0.65\textwidth}
\begin{description}
\setlength\itemsep{0em}
\item[Scene point] $M$ (the object in the real world).
\item[Image point] $m$ (the object in the image).
\item[Image plane] $I$.
\item[Optical center] $C$ (the pinhole).
\item[Image center/piercing point] $c$ (intersection between the optical axis -- the line orthogonal to $I$ passing through $C$ -- and $I$).
\item[Focal length] $f$.
\item[Focal plane] $F$.
\end{description}
\end{minipage}
\begin{minipage}{0.3\textwidth}
\centering
\includegraphics[width=\linewidth]{./img/perspective_projection1.png}
\end{minipage}\\
\begin{minipage}{0.55\textwidth}
\begin{itemize}[leftmargin=*]
\item $u$ and $v$ are the horizontal and vertical axis of the image plane, respectively.
\item $x$ and $y$ are the horizontal and vertical axis of the 3D reference system, respectively,
and form the \textbf{camera reference system}. \marginnote{Camera reference system}
\end{itemize}
\begin{remark}
For the perspective model, the coordinate systems $(U, V)$ and $(X, Y)$ must be parallel.
\end{remark}
\end{minipage}
\begin{minipage}{0.35\textwidth}
\centering
\includegraphics[width=\linewidth]{./img/perspective_projection2.png}
\end{minipage}
\begin{description}
\item[Scene--image mapping] \marginnote{Scene--image mapping}
The equations to map scene points into image points are the following:
\[ u = x \frac{f}{z} \hspace*{3em} v = y \frac{f}{z} \]
\begin{proof}
This is the consequence of the triangle similarity theorems.
\begin{minipage}{0.45\textwidth}
\[
\begin{split}
\frac{u}{x} = -\frac{f}{z} &\iff u = -x \frac{f}{z} \\
\frac{v}{y} = -\frac{f}{z} &\iff v = -y \frac{f}{z}
\end{split}
\]
The minus is needed as the axes are inverted
\end{minipage}
\begin{minipage}{0.50\textwidth}
\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{./img/_perspective_projection_eq_proof.pdf}
\caption{\small Visualization of the horizontal axis. The same holds on the vertical axis.}
\end{figure}
\end{minipage}
By inverting the axis horizontally and vertically (i.e. inverting the sign),
the image plane can be adjusted to have the same orientation of the scene:
\[ u = x \frac{f}{z} \hspace*{3em} v = y \frac{f}{z} \]
\end{proof}
\begin{remark}
The image coordinates are a scaled version of the scene coordinates.
The scaling is inversely proportioned with respect to the depth.
\begin{itemize}
\item The farther the point, the smaller the coordinates.
\item The larger the focal length, the bigger the object is in the image.
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{./img/perspective_projection_proportion.png}
\caption{Coordinate space by varying focal length}
\end{figure}
\end{remark}
\begin{remark}
The perspective projection mapping is not a bijection:
\begin{itemize}
\item A scene point is mapped into a unique image point.
\item An image point is mapped onto a 3D line.
\end{itemize}
Therefore, reconstructing the 3D structure of a single image is an ill-posed problem (i.e. it has multiple solutions).
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{./img/perspective_projection_loss.png}
\caption{Projection from scene and image points}
\end{figure}
\end{remark}
\end{description}
\subsection{Stereo geometry}
\begin{description}
\item[Stereo vision] \marginnote{Stereo vision}
Use multiple images to triangulate the 3D position of an object.
\item[Stereo correspondence] \marginnote{Stereo correspondence}
Given a point $L$ in an image, find the corresponding point $R$ in another image.
Without any assumptions, an oracle is needed to determine the correspondences.
\end{description}
\begin{description}
\item[Standard stereo geometry] \marginnote{Standard stereo geometry}
Given two reference images, the following assumptions must hold:
\begin{itemize}
\item The $X$, $Y$, $Z$ axes are parallel.
\item The cameras that took the two images have the same focal length $f$ (coplanar image planes) and
the images have been taken at the same time.
\item There is a horizontal translation $b$ between the two cameras (baseline).
\item The disparity $d$ is the difference of the $U$ coordinates of the object in the left and right image.
\end{itemize}
\begin{theorem}[Fundamental relationship in stereo vision] \marginnote{Fundamental relationship in stereo vision}
If the assumptions above hold, the following equation holds:
\[ z = b\frac{f}{d} \]
\begin{proof}
Let $P_L = \begin{pmatrix}x_L & y & z\end{pmatrix}$ and $P_R = \begin{pmatrix}x_R & y & z\end{pmatrix}$ be the
coordinates of the object $P$ with respect to the left and right camera reference system, respectively.
Let $p_L = \begin{pmatrix}u_L & v\end{pmatrix}$ and $p_R = \begin{pmatrix}u_R & v\end{pmatrix}$
be the coordinates of the object $P$ in the left and right image plane, respectively.
By assumption, we have that $P_L - P_R = \begin{pmatrix} b & 0 & 0 \end{pmatrix}$, where $b$ is the baseline.
\begin{minipage}{0.6\textwidth}
By the perspective projection equation, we have that:
\[ u_L = x_L\frac{f}{z} \hspace{3em} u_R = x_R\frac{f}{z} \]
Disparity is computed as follows:
\[ d = u_L - u_R = x_L\frac{f}{z} - x_R\frac{f}{z} = b\frac{f}{z} \]
We can therefore obtain the $Z$ coordinate of $P$ as:
\[ z = b\frac{f}{d} \]
\end{minipage}
\begin{minipage}{0.3\textwidth}
\begin{center}
\includegraphics[width=\textwidth]{./img/_standard_stereo_geometry.pdf}
\end{center}
Note: the $Y$/$V$ axes are not in figure.
\end{minipage}\\
\end{proof}
\begin{remark}
Disparity and depth are inversely proportional:
the disparity of two points decreases if the points are farther in depth.
\end{remark}
\end{theorem}
\begin{description}
\item[Stereo matching] \marginnote{Stereo matching}
If the assumptions for standard stereo geometry hold,
to find the object corresponding to $p_L$ in another image,
it is sufficient to search along the horizontal axis of $p_L$ looking for the same colors or patterns.
\begin{figure}[h]
\centering
\includegraphics[width=0.5\textwidth]{./img/stereo_matching.png}
\caption{Example of stereo matching}
\end{figure}
\end{description}
\item[Epipolar geometry] \marginnote{Epipolar geometry}
Approach applied when the two cameras are no longer aligned according to the standard stereo geometry assumption.
Still, the focal lengths and the roto-translation between the two cameras must be known.
Given two images, we can project the epipolar line related to the point $p_L$ in the left plane onto the right plane
to reduce the problem of correspondence search to a single dimension.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{./img/_epipolar_geometry.pdf}
\caption{Example of epipolar geometry}
\end{figure}
\begin{remark}
It is nearly impossible to project horizontal epipolar lines and
searching through oblique lines is awkward and computationally less efficient than straight lines.
\end{remark}
\begin{description}
\item[Rectification] \marginnote{Rectification}
Transformation applied to convert epipolar geometry to a standard stereo geometry.
\begin{figure}[H]
\centering
\begin{subfigure}{0.35\linewidth}
\centering
\includegraphics[width=\linewidth]{./img/rectification_no.png}
\caption{Images before rectification}
\end{subfigure}
\begin{subfigure}{0.35\linewidth}
\centering
\includegraphics[width=\linewidth]{./img/rectification_yes.png}
\caption{Images after rectification}
\end{subfigure}
\end{figure}
\end{description}
\end{description}
\subsection{Ratios and parallelism}
Given a 3D line of length $L$ lying in a plane parallel to the image plane at distance $z$,
then its length $l$ in the image plane is:
\[ l = L\frac{f}{z} \]
In all the other cases (i.e. when the line is not parallel to the image plane),
the ratios of lengths and the parallelism of lines are not preserved.
\begin{figure}[h]
\centering
\includegraphics[width=0.25\textwidth]{./img/_perspective_projection_ratio.pdf}
\caption{Example of not preserved ratios. It holds that $\frac{\overline{AB}}{\overline{BC}} \neq \frac{\overline{ab}}{\overline{bc}}$.}
\end{figure}
\begin{description}
\item[Vanishing point] \marginnote{Vanishing point}
Intersection point of lines that are parallel in the scene but not in the image plane.
\begin{figure}[h]
\centering
\includegraphics[width=0.6\textwidth]{./img/_vanishing_point.pdf}
\caption{Example of vanishing point}
\end{figure}
\end{description}
\section{Lens}
\begin{description}
\item[Depth of field (DOF)] \marginnote{Depth of field (DOF)}
Distance at which a scene point is in focus (i.e. when all its light rays gathered by the imaging device hit the image plane at the same point).
\begin{remark}
Because of the small size of the aperture, a pinhole camera has infinite depth of field
but requires a long exposure time making it only suitable for static scenes.
\end{remark}
\item[Lens] \marginnote{Lens}
A lens gathers more light from the scene point and focuses it on a single image point.
This allows for a smaller exposure time but limits the depth of field (i.e. only a limited range of distances in the image can be in focus at the same time).
\item[Thin lens] \marginnote{Thin lens}
Approximate model for lenses.
\begin{minipage}{0.65\textwidth}
\begin{description}
\setlength\itemsep{0em}
\item[Scene point] $P$ (the object in the real world).
\item[Image point] $p$ (the object in the image).
\item[Object--lens distance] $o$.
\item[Image--lens distance] $i$ (i.e. focal length of the camera).
\item[Center of the lens] $C$.
\item[Focal length of the lens] $f$.
\item[Focal plane/focus of the lens] $F$.
\end{description}
\end{minipage}
\begin{minipage}{0.4\textwidth}
\centering
\includegraphics[width=\textwidth]{./img/_thin_lens.pdf}
\end{minipage}
A thin lens has the following properties:
\begin{itemize}
\item Rays hitting the lens parallel to the optical axis are deflected to pass through the focal plane of the lens $F$.
\item Rays passing through the center of the lens $C$ are undeflected.
\item The following equation holds: \marginnote{Thin lens equation}
\[ \frac{1}{o} + \frac{1}{i} = \frac{1}{f} \]
\end{itemize}
\item[Image formation]
When the image is in focus, the image formation process follows the normal rules of the perspective projection model where:
\begin{itemize}
\item $C$ is the optical center.
\item $i$ is the focal length of the camera.
\end{itemize}
By fixing the focal length of the lens ($f$),
we can determine the distance of the scene point ($o$) or the image point ($i$) required to have the object in focus.
\[ \frac{1}{o}+\frac{1}{i} = \frac{1}{f} \iff o = \frac{if}{i - f} \hspace{3em} \frac{1}{o}+\frac{1}{i} = \frac{1}{f} \iff i = \frac{of}{o - f} \]
\begin{remark}
Points projected in front or behind the image plane will create a circle of confusion (blur).
\begin{figure}[H]
\centering
\begin{subfigure}{0.3\textwidth}
\centering
\includegraphics[width=\textwidth]{./img/thin_lens_formation1.png}
\caption{Image in focus}
\end{subfigure}
\begin{subfigure}{0.3\textwidth}
\centering
\includegraphics[width=0.8\textwidth]{./img/thin_lens_formation2.png}
\caption{Projection behind the image plane}
\end{subfigure}
\begin{subfigure}{0.3\textwidth}
\centering
\includegraphics[width=\textwidth]{./img/thin_lens_formation3.png}
\caption{Projection in front of the image plane}
\end{subfigure}
\end{figure}
\end{remark}
\item[Adjustable diaphragm] \marginnote{Adjustable diaphragm}
Device to control the light gathered by the effective aperture of the lens.
Reducing the aperture will result in less light and an increased depth of field.
\begin{remark}
On a theoretical level, images that are not in focus appear blurred (circles of confusion).
Despite that, if the circle is smaller than the photo-sensing elements (i.e. pixels), it will appear in focus.
\end{remark}
\item[Focusing mechanism] \marginnote{Focusing mechanism}
Allows the lens to translate along the optical axis to increase its distance to the image plane.
At the minimum extension (\Cref{fig:focus_mechanism_min}), we have that:
\[ i = f \text{ and } o = \infty \text{ as the thin lens equation states that } \frac{1}{o} + \frac{1}{i} = \frac{1}{f} \]
By increasing the extension (i.e. increase $i$), we have that the distance to the scene point $o$ decreases.
The maximum extension determines the minimum focusing distance.
\begin{figure}[H]
\centering
\begin{subfigure}{0.4\textwidth}
\centering
\includegraphics[width=0.45\textwidth]{./img/_focus_mechanism1.pdf}
\caption{Minimum extension} \label{fig:focus_mechanism_min}
\end{subfigure}
\begin{subfigure}{0.4\textwidth}
\centering
\includegraphics[width=0.45\textwidth]{./img/_focus_mechanism2.pdf}
\caption{Maximum extension} \label{fig:focus_mechanism_max}
\end{subfigure}
\caption{Extension of a focusing mechanism}
\end{figure}
\end{description}
\section{Image digitalization}
\subsection{Sampling and quantization}
The image plane of a camera converts the received irradiance into electrical signals.
\begin{figure}[h]
\centering
\includegraphics[width=0.6\textwidth]{./img/_digitalization.pdf}
\caption{Image digitalization steps}
\end{figure}
\begin{description}
\item[Sampling] \marginnote{Sampling}
The continuous electrical signal is sampled to produce a $N \times M$ matrix of pixels:
\[
I(x, y) = \begin{pmatrix}
I(0, 0) & \hdots & I(0, M-1) \\
\vdots & \ddots & \vdots \\
I(N-1, 0) & \hdots & I(N-1, M-1) \\
\end{pmatrix}
\]
\item[Quantization] \marginnote{Quantization}
Let $m$ be the number of bits used to encode a pixel.
The value of each pixel is quantized into $2^m$ discrete gray levels.
\begin{remark}
A grayscale image usually uses $8$ bits
An RGB image usually uses $3 \cdot 8$ bits.
\end{remark}
\end{description}
\begin{remark}
The more bits are used for the representation, the higher the quality of the image will be.
\begin{itemize}
\item Sampling with fewer bits will result in a lower resolution (aliasing).
\item Quantization with fewer bits will result in less representable colors.
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{./img/_digitalization_quality.pdf}
\caption{Sampling and quantization using fewer bits}
\end{figure}
\end{remark}
\subsection{Camera sensors}
\begin{description}
\item[Photodetector] \marginnote{Photodetector}
Sensor that, during the exposure time, converts the light into a proportional electrical charge that
will be processed by a circuit and converted into a digital or analog signal.
\begin{figure}[H]
\centering
\includegraphics[width=0.55\textwidth]{./img/_camera_sensors.pdf}
\caption{Components of a camera}
\end{figure}
The two main sensor technologies are:
\begin{descriptionlist}
\item[Charge Coupled Device (CCD)] \marginnote{Charge Coupled Device (CCD)}
Typically produces higher quality images but are more expensive.
\item[Complementary Metal Oxide Semiconductor (CMOS)] \marginnote{Complementary Metal Oxide Semiconductor (CMOS)}
Generally produces lower quality images but is more compact and less expensive.
Each sensor has integrated its own circuitry that allows to read an arbitrary window of the sensors.
\end{descriptionlist}
\item[Color sensors] \marginnote{Color sensors}
CCD and CMOS sensors are sensitive to a wide spectrum of light frequencies (both visible and invisible) but
are unable to sense colors as they produce a single value per pixel.
\begin{figure}[H]
\centering
\includegraphics[width=0.35\textwidth]{./img/sensors_sensitivity.png}
\caption{CCD and CMOS spectral sensitivity}
\end{figure}
\begin{description}
\item[Color Filter Array (CFA)] \marginnote{Color Filter Array (CFA)}
Filter placed in front of a photodetector to allow it to detect colors.
Possible approaches are:
\begin{descriptionlist}
\item[Bayer CFA]
A grid of green, blue, and red filters with the greens being twice as much as the others (the human eye is more sensible to the green range).
To determine the RGB value of each pixel, missing color channels are sampled from neighboring pixels (demosaicking).
\begin{figure}[H]
\centering
\includegraphics[width=0.15\textwidth]{./img/_bayer_cfa.pdf}
\caption{Example of Bayer filter}
\end{figure}
\item[Optical prism]
A prism splits the incoming light into 3 RGB beams, each directed to a different sensor.
It is more expensive than Bayer CFA.
\end{descriptionlist}
\end{description}
\end{description}
\subsection{Metrics}
\begin{description}
\item[Signal to Noise Ratio (SNR)] \marginnote{Signal to Noise Ratio (SNR)}
Quantifies the strength of the actual signal with respect to unwanted noise.
Sources of noise are:
\begin{descriptionlist}
\item[Photon shot noise] Number of photons captured during exposure time.
\item[Elecronic circuitry noise] Generated by the electronics that read the sensors.
\item[Quantization noise] Caused by the digitalization of the image (ADC conversion).
\item[Dark current noise] Random charge caused by thermal excitement.
\end{descriptionlist}
SNR is usually expressed in decibels or bits:
\[ \texttt{SNR}_\text{db} = 20 \cdot \log_{10}(\texttt{SNR}) \hspace{3em} \texttt{SNR}_\text{bit} = \log_{2}(\texttt{SNR}) \]
\item[Dynamic Range (DR)] \marginnote{Dynamic Range (DR)}
Measures the ability of a sensor to capture both the dark and bright structure of the scene.
Let:
\begin{itemize}
\item $E_\text{min}$ be the minimum detectable irradiation. This value depends on the noise.
\item $E_\text{max}$ be the saturation irradiation (i.e. the maximum amount of light that fills the capacity of the photodetector).
\end{itemize}
DR is defined as:
\[ \texttt{DR} = \frac{E_\text{max}}{E_\text{mix}} \]
As with SNR, DR can be expressed in decibels or bits.
\end{description}

View File

@ -0,0 +1,350 @@
\chapter{Instance-level object detection}
\begin{description}
\item[Instance-level object detection] \marginnote{Instance-level object detection}
Given a reference/model image of a specific object,
determine if the object is present in the target image and estimate its pose.
\begin{remark}
This is different from category-level object detection which deals with detecting classes of objects
independent of appearance and pose.
\end{remark}
\end{description}
\section{Template matching}
\marginnote{Template matching}
Slide the model image (template) across the target image and
use a similarity/dissimilarity function with a threshold to determine if a match has been found.
\subsection{Similarity/dissimilarity functions}
Let $I$ be the target image and $T$ the template image of shape $M \times N$.
Possible similarity/dissimilarity functions are:
\begin{descriptionlist}
\item[Pixel-wise intensity differences] \marginnote{Pixel-wise intensity differences}
Squared difference between the intensities of the template image and the patch in the target image:
\[ \texttt{SSD}(i, j) = \sum_{m=0}^{M-1} \sum_{n=0}^{N-1} \big( I(i+m, j+n) - T(m, n) \big)^2 \]
\begin{remark}
\texttt{SSD} is fast but not intensity invariant.
\end{remark}
\item[Sum of absolute differences] \marginnote{Sum of absolute differences}
Difference in absolute value between the intensities of the template image and the patch in the target image:
\[ \texttt{SAD}(i, j) = \sum_{m=0}^{M-1} \sum_{n=0}^{N-1} \big\vert I(i+m, j+n) - T(m, n) \big\vert \]
\begin{remark}
\texttt{SAD} is fast but not intensity invariant.
\end{remark}
\item[Normalized cross-correlation] \marginnote{Normalized cross-correlation}
Cosine similarity between the template image and the target image patch (which are seen as flattened vectors):
\[
\texttt{NCC}(i, j) =
\frac{ \sum\limits_{m=0}\limits^{M-1} \sum\limits_{n=0}\limits^{N-1} \big( I(i+m, j+n) \cdot T(m, n) \big) }
{ \sqrt{\sum\limits_{m=0}\limits^{M-1} \sum\limits_{n=0}\limits^{N-1} I(i+m, j+n)^2} \cdot \sqrt{\sum\limits_{m=0}\limits^{M-1} \sum\limits_{n=0}\limits^{N-1} T(m, n)^2} }
\]
In other words, let $\tilde{I}_{i,j}$ be a $M \times N$ patch of the target image $I$ starting at the coordinates $(i, j)$.
In vector form, $\texttt{NCC}(i, j)$ computes the cosine of the angle $\theta$ between $\tilde{I}_{i,j}$ and $T$.
\[ \texttt{NCC}(i, j) = \frac{\tilde{I}_{i,j} \cdot T}{\Vert \tilde{I}_{i,j} \Vert \cdot \Vert T \Vert} = \cos \theta \]
\begin{remark}
\texttt{NCC} is invariant to a linear intensity change but not to an additive bias.
\end{remark}
\item[Zero-mean normalized cross-correlation] \marginnote{Zero-mean normalized cross-correlation}
Let $\tilde{I}_{i,j}$ be a $M \times N$ patch of $I$ starting at the coordinates $(i, j)$.
Zero-mean normalized cross-correlation subtracts the mean of the template image and the patch of the target image
before computing \texttt{NCC}:
\[ \mu(\tilde{I}_{i,j}) = \frac{1}{MN} \sum_{m=0}^{M-1} \sum_{n=0}^{N-1} I(i+m, j+n) \hspace{3em} \mu(T) = \frac{1}{MN} \sum_{m=0}^{M-1} \sum_{n=0}^{N-1} T(m, n) \]
\[
\texttt{NCC}(i, j) =
\frac{ \sum\limits_{m=0}\limits^{M-1} \sum\limits_{n=0}\limits^{N-1} \Big( \big(I(i+m, j+n) - \mu(\tilde{I}_{i,j})\big) \cdot \big(T(m, n) - \mu(T)\big) \Big) }
{ \sqrt{\sum\limits_{m=0}\limits^{M-1} \sum\limits_{n=0}\limits^{N-1} \big(I(i+m, j+n) - \mu(\tilde{I}_{i,j})\big)^2} \cdot \sqrt{\sum\limits_{m=0}\limits^{M-1} \sum\limits_{n=0}\limits^{N-1} \big(T(m, n) - \mu(T)\big)^2} }
\]
\begin{remark}
\texttt{ZNCC} is invariant to an affine intensity change.
\end{remark}
\end{descriptionlist}
\begin{figure}[H]
\centering
\includegraphics[width=0.95\linewidth]{./img/template_matching_example.png}
\caption{Examples of template matching}
\end{figure}
\section{Shape-based matching}
\marginnote{Shape-based matching}
Edge-based template matching that works as follows:
\begin{enumerate}
\item Use an edge detector to extract a set of control points $\{ P_1, \dots, P_n \}$ in the template image $T$.
\item Compute the gradient normalized to unit vector at each point $P_k$:
\[ \nabla T(P_k) = \begin{pmatrix} \partial_x T(P_k) \\ \partial_y T(P_k) \end{pmatrix} \hspace{2em} \vec{u}_k(P_k) = \frac{\nabla T(P_k)}{\Vert \nabla T(P_k) \Vert} \]
\item Given a patch $\tilde{I}_{i,j}$ of the target image,
compute the gradient normalized to unit vector at the points $\{ \tilde{P}_1(i, y), \dots, \tilde{P}_n(i, y) \}$
corresponding to the control points of the template image:
\[
\nabla \tilde{I}_{i,j}(\tilde{P}_k) = \begin{pmatrix} \partial_x \tilde{I}_{i,j}(\tilde{P}_k) \\ \partial_y \tilde{I}_{i,j}(\tilde{P}_k) \end{pmatrix} \hspace{2em}
\tilde{\vec{u}}_k(\tilde{P}_k) = \frac{\nabla \tilde{I}_{i,j}(\tilde{P}_k)}{\Vert \nabla \tilde{I}_{i,j}(\tilde{P}_k) \Vert}
\]
\item Compute the similarity as the sum of the cosine similarities of each pair of gradients:
\[ S(i, j) = \frac{1}{n} \sum_{k=1}^{n} \vec{u}_k(P_k) \cdot \tilde{\vec{u}}_k(\tilde{P}_k) = \frac{1}{n} \sum_{k=1}^{n} \cos \theta_k \in [-1, 1] \]
$S(i, j) = 1$ when the gradients perfectly match. A minimum threshold $S_\text{min}$ is used to determine if there is a match.
\end{enumerate}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\linewidth]{./img/shape_based_matching.png}
\caption{Example of control points matching}
\end{figure}
\subsection{Invariance to global inversion of contrast polarity}
As an object might appear on a darker or brighter background, more robust similarity functions can be employed:
\begin{description}
\item[Global polarity inversion contrast]
\[ S(i, j) = \frac{1}{n} \left\vert \sum_{k=1}^{n} \vec{u}_k(P_k) \cdot \tilde{\vec{u}}_k(\tilde{P}_k) \right\vert =
\frac{1}{n} \left\vert \sum_{k=1}^{n} \cos \theta_k \right\vert \]
\item[Local polarity inversion contrast]
\[ S(i, j) = \frac{1}{n} \sum_{k=1}^{n} \left\vert \vec{u}_k(P_k) \cdot \tilde{\vec{u}}_k(\tilde{P}_k) \right\vert =
\frac{1}{n} \sum_{k=1}^{n} \left\vert \cos \theta_k \right\vert \]
\begin{remark}
This is the most robust one.
\end{remark}
\end{description}
\section{Hough transform}
Detect objects of a known shape that can be expressed through an analytic equation
by means of a projection from the image space to a parameter space.
\begin{description}
\item[Parameter space] \marginnote{Parameter space}
Euclidean space parametrized on the parameters $\phi$ of an analytic shape $\mathcal{S}_\phi$ (e.g. line, sphere, \dots).
A point $(x, y)$ in the image space is projected into the curve (which also intends lines) that contains the set of parameters $\hat{\phi}$
such that the shape $\mathcal{S}_{\hat{\phi}}$ defined on those parameters passes through $(x, y)$ in the image space.
\begin{remark}
If many curves intersect at $\hat{\phi}$ in the parameter space of a shape $S_\phi$, then, there is high evidence of the fact that
the image points that were projected into those curves are part of the shape $S_{\hat{\phi}}$.
\end{remark}
\begin{example}[Space of straight lines]
Consider the line equation:
\[ \hat{y} - m\hat{x} - c = 0 \]
where $(\hat{x}, \hat{y})$ are fixed while $(m, c)$ vary (in the usual equation, it is the opposite).
This can be seen as a mapping of points $(\hat{x}, \hat{y})$ into the space
of points $(m, c)$ such that the straight line parametrized on $m$ and $c$ passes through $(\hat{x}, \hat{y})$
(i.e. a point in the image space is mapped into a line in the parameter space as infinite lines pass through a point).
For instance, consider two points $p_1$, $p_2$ in the image space and
their projection in the parameter space.
If the two lines intersect at the point $(\tilde{m}, \tilde{c})$,
then the line parametrized on $\tilde{m}$ and $\tilde{c}$ passes through $p_1$ and $p_2$ in the image space.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\linewidth]{./img/hough_line_parameter_space.png}
\end{figure}
\begin{remark}
By projecting $n$ points of the image space, there are at most $\frac{n(n-1)}{2}$ intersections in the parameter space.
\end{remark}
\end{example}
\item[Algorithm] \marginnote{Object detection using Hough transform}
Given an analytic shape that we want to detect,
object detection using the Hough transform works as follows:
\begin{enumerate}
\item Map image points into curves of the parameter space.
\item The parameter space is quantized into $M \times N$ cells and an accumulator array $A$ of the same shape is initialized to $0$.
\item For each cell $(i, j)$ of the discretized grid,
the corresponding cell $A(i, j)$ in the accumulator array counts how many curves lie in that cell (i.e. voting process).
\item Find the local maxima of $A$ and apply a threshold if needed.
The points that were projected into the curves passing through a maximum cell are points belonging to an object of the sought shape.
\end{enumerate}
\begin{remark}
The Hough transform reduces a global detection problem into a local detection in the parameter space.
\end{remark}
\begin{remark}
The Hough transform is usually preceded by an edge detection phase so that the input consists of the edge pixels of the image.
\end{remark}
\begin{remark}
The Hough transform is robust to noise and can detect partially occluded images (with a suitable threshold).
\end{remark}
\end{description}
\subsection{Hough transform for line detection}
\marginnote{Hough transform for line detection}
For line detection, points in the image space are projected into lines of the parameter space.
\begin{figure}[H]
\centering
\includegraphics[width=0.85\linewidth]{./img/hough_line_detection.png}
\caption{Example of line detection}
\end{figure}
In practice, the parametrization on $(m, c)$ of the equation $y-mx-c = 0$ is impractical as $m$ and $c$ have an infinite range.
An alternative approach is to describe straight lines as linear trigonometric equations parametrized on $(\theta, \rho)$:
\[ x \cos \theta + y \sin \theta - \rho = 0 \]
In this form, $\theta \in [ -\frac{\pi}{2}, \frac{\pi}{2} ]$ while $\rho \in [-\rho_\text{max}, \rho_\text{max}]$
where $\rho_\text{max}$ is usually taken of the same size as the diagonal of the image (e.g. for square $N \times N$ images, $\rho_\text{max} = N\sqrt{2}$).
\section{Generalized Hough transform}
Hough transform extended to detect an arbitrary shape.
\subsection{Naive approach}
\begin{description}
\item[Off-line phase] \marginnote{Generalized Hough transform}
Phase in which the model of the template object is built.
Given a template shape, the algorithm works as follows:
\begin{enumerate}
\item Fix a reference point $\vec{y}$ (barycenter). $\vec{y}$ is typically within the shape of the object.
\item For each point $\vec{x}$ at the border $B$ of the object:
\begin{enumerate}
\item Compute its gradient direction $\varphi(\vec{x})$ and discretize it according to a chosen step $\Delta \varphi$.
\item Compute the vector $\vec{r} = \vec{y} - \vec{x}$ as the distance of $\vec{x}$ to the barycenter.
\item Store $\vec{r}$ as a function of $\Delta \varphi$ in a table (R-table).
Note that more than one vector might be associated with the same $\Delta \varphi$.
\end{enumerate}
\end{enumerate}
\begin{example}
\phantom{}\\[0.5em]
\begin{minipage}{0.7\linewidth}
\small
\begin{tabular}{lll}
\toprule
$i$ & $\varphi_i$ & $R_{\varphi_i}$ \\
\midrule
$0$ & $0$ & $\{ \vec{r} \mid \vec{r}=\vec{y}-\vec{x}.\, \forall \vec{x} \in B: \varphi(\vec{x}) = 0 \}$ \\
$1$ & $\Delta\varphi$ & $\{ \vec{r} \mid \vec{r}=\vec{y}-\vec{x}.\, \forall \vec{x} \in B: \varphi(\vec{x}) = \Delta\varphi \}$ \\
$2$ & $2\Delta\varphi$ & $\{ \vec{r} \mid \vec{r}=\vec{y}-\vec{x}.\, \forall \vec{x} \in B: \varphi(\vec{x}) = 2\Delta\varphi \}$ \\
\multicolumn{1}{c}{\vdots} & \multicolumn{1}{c}{\vdots} & \multicolumn{1}{c}{\vdots} \\
\bottomrule
\end{tabular}
\end{minipage}
\begin{minipage}{0.2\linewidth}
\centering
\includegraphics[width=\linewidth]{./img/generalized_hough_offline.png}
\end{minipage}
\end{example}
\item[On-line phase]
Phase in which the object is detected.
Given a $M \times N$ image, the algorithm works as follows:
\begin{enumerate}
\item Find the edges $E$ of the image.
\item Initialize an accumulator array $A$ of the same shape of the image.
\item For each edge pixel $\vec{x} \in E$:
\begin{enumerate}
\item Compute its gradient direction $\varphi(\vec{x})$ discretized to match the step $\Delta \varphi$ of the R-table.
\item For each $\vec{r}_i$ in the corresponding row of the R-table:
\begin{enumerate}
\item Compute an estimate of the barycenter as $\vec{y} = \vec{x} - \vec{r}_i$.
\item Cast a vote in the accumulator array $A[\vec{y}] \texttt{+=} 1$
\end{enumerate}
\end{enumerate}
\item Find the local maxima of the accumulator vector to estimate the barycenters.
The shape can then be visually found by overlaying the template barycenter to the found barycenters.
\end{enumerate}
\end{description}
\begin{remark}
This approach is not rotation and scale invariant.
Therefore, if rotation or scale is changed, the method should try different rotations or scales.
\end{remark}
\subsection{Star model}
\marginnote{Star model}
Generalized Hough transform based on local invariant features.
% \begin{remark}
% Local invariant features usually prune features found along edges.
% \end{remark}
\begin{description}
\item[Off-line phase]
Given a template, its model is obtained as follows:
\begin{enumerate}
\item Detect local invariant features $F = \{ F_1, \dots, F_N \}$ and compute their descriptors.
Each feature $F_i$ is described by the tuple:
\[ F_i = (\vec{P}_i, \varphi_i, S_i, \vec{D}_i) = \text{(position, canonical orientation, scale, descriptor)} \]
\item Compute the position of the barycenter $\vec{P}_C$ as:
\[ \vec{P}_C = \frac{1}{N} \sum_{i=1}^{N} \vec{P}_i \]
\item For each feature $F_i$ compute the joining vector $\vec{V}_i = \vec{P}_C - \vec{P}_i$ as the distance to the barycenter
and add it to its associated tuple to obtain:
\[ F_i = (\vec{P}_i, \varphi_i, S_i, \vec{D}_i, \vec{V}_i) \]
\end{enumerate}
\begin{figure}[H]
\centering
\includegraphics[width=0.2\linewidth]{./img/star_model_offline.png}
\end{figure}
\begin{remark}
The R-table is not needed anymore.
\end{remark}
\item[On-line phase]
Given a target image, detection works as follows:
\begin{enumerate}
\item Extract the local invariant features $\tilde{F} = \{ \tilde{F}_1, \dots, \tilde{F}_M \}$ of the target image.
Each feature $\tilde{F}_i$ is describe by the tuple:
\[ \tilde{F}_i = (\tilde{\vec{P}}_i, \tilde{\varphi}_i, \tilde{S}_i, \tilde{\vec{D}}_i) \]
\item Match the features $\tilde{F}$ of the target image to the features $F$ of the template image through the descriptors.
\item Initialize a 4-dimensional accumulator array. Two dimensions match the image shape.
The other two represent different rotations and scales.
\item For each target feature $\tilde{F}_i = (\tilde{\vec{P}}_i, \tilde{\varphi}_i, \tilde{S}_i, \tilde{\vec{D}}_i)$
with matching template feature $F_j = (\vec{P}_j, \varphi_j, S_j, \vec{D}_j, \vec{V}_j)$:
\begin{enumerate}
\item Align the joining vector $\vec{V}_j$ to the scale and rotation of $\tilde{F}_i$.
Let $\matr{R}(\phi)$ be a $\phi$ degree rotation matrix. The aligned joining vector $\tilde{\vec{V}}_i$ is obtained as:
\[ \Delta \varphi_i = \tilde{\varphi}_i - \varphi_j \hspace{3em} \Delta S_i = \frac{\tilde{S}_i}{S_j} \]
\[ \tilde{\vec{V}}_i = \Delta S_i \cdot \matr{R}(\Delta \varphi_i) \vec{V}_i \]
\item Estimate the barycenter $\tilde{\vec{P}}_{C_i}$ associated to the feature $\tilde{F}_i$ as:
\[ \tilde{\vec{P}}_{C_i} = \tilde{\vec{P}}_i + \tilde{\vec{V}}_i \]
\begin{figure}[H]
\centering
\includegraphics[width=0.55\linewidth]{./img/star_model_online.png}
\end{figure}
\item Cast a vote in the accumulator array $A[\tilde{\vec{P}}_{C_i}, \Delta S_i, \Delta \varphi_i] \texttt{+=} 1$.
\end{enumerate}
\item Find the local maxima of the accumulator vector to estimate the barycenters.
The shape can then be visually found by overlaying the template barycenter to the found barycenters with the proper scaling and rotation.
\begin{figure}[H]
\centering
\includegraphics[width=0.6\linewidth]{./img/star_model_voting.png}
\end{figure}
\end{enumerate}
\end{description}

View File

@ -0,0 +1,539 @@
\chapter{Local features}
\begin{description}
\item[Correspondence points] \marginnote{Correspondence points}
Image points projected from the same 3D point from different views of the scene.
\begin{example}[Homography]
Align two images of the same scene to create a larger image.
Homography requires at least 4 correspondences.
To find them, it does the following:
\begin{itemize}
\item Independently find salient points in the two images.
\item Compute a local description of the salient points.
\item Compare descriptions to find matching points.
\end{itemize}
\end{example}
\item[Local invariant features] \marginnote{Local invariant features}
Find correspondences in three steps:
\begin{descriptionlist}
\item[Detection] \marginnote{Detection}
Find salient points (keypoints).
The detector should have the following properties:
\begin{descriptionlist}
\item[Repeatability] Find the same keypoints across different images.
\item[Saliency] Find keypoints surrounded by informative patterns.
\item[Fast] As it must scan the entire image.
\end{descriptionlist}
\item[Description] \marginnote{Description}
Compute a descriptor for each salient point based on its neighborhood.
A descriptor should have the following properties:
\begin{descriptionlist}
\item[Invariant] Robust to as many transformations as possible (i.e. illumination, weather, scaling, viewpoint, \dots).
\item[Distinctiveness/robustness trade-off] The description should only capture important information around a keypoint and
ignore irrelevant features or noise.
\item[Compactness] The description should be concise.
\end{descriptionlist}
\item[Matching] \marginnote{Matching}
Identify the same descriptor across different images.
\end{descriptionlist}
\end{description}
\begin{remark}
Edges are not good interest points as they are locally ambiguous (i.e. pixels are very similar along the direction of the gradient).
Corners on the other hand are more suited as they have a larger variation along all directions.
\end{remark}
\section{Moravec's corner detector}
\marginnote{Moravec's corner detector}
Given a window $W$ of size $n \times n$,
the cornerness of a pixel $p$ is given by the minimum squared difference between
the intensity of $W$ centered on $p$ and the intensity of $W$ centered on each of its neighbors:
\[ C(p) = \min_{q \in \mathcal{N}(p)} \Vert W(p) - W(q) \Vert^2 \]
After computing the cornerness of each pixel, one can apply thresholding and then NMS to obtain a matrix where $1$ indicates a corner.
\begin{figure}[H]
\centering
\begin{subfigure}{0.3\linewidth}
\includegraphics[width=0.9\linewidth]{./img/_corner_detector_example_flat.pdf}
\caption{Flat region: $C(p)$ is low.}
\end{subfigure}
\begin{subfigure}{0.3\linewidth}
\includegraphics[width=0.8\linewidth]{./img/_corner_detector_example_edge.pdf}
\caption{Edge: $C(p)$ is low.}
\end{subfigure}
\begin{subfigure}{0.3\linewidth}
\includegraphics[width=0.8\linewidth]{./img/_corner_detector_example_corner.pdf}
\caption{Corner: $C(p)$ is high.}
\end{subfigure}
\end{figure}
\begin{remark}
Moravec corner detector is isotropic (i.e. independent of the direction).
\end{remark}
\section{Harris' corner detector}
\subsection{Structure matrix}
Harris' corner detector uses an error function formulated as the continuous version of Moravec's detector and
assumes an infinitesimal shift $(\Delta x, \Delta y)$ of the image:
\[ E(\Delta x, \Delta y) = \sum_{x, y} w(x, y) \big( I(x+\Delta x, y+\Delta y) - I(x, y) \big)^2 \]
where $w(x, y)$ in a window centered on $(x, y)$ and can be seen as a mask with $1$ when the pixel belongs to the window and $0$ otherwise.
By employing the Taylor's series $f(x + \Delta x) = f(x) + f'(x) \Delta x$,
we can expand the intensity difference as:
\[
\begin{split}
I(x+\Delta x, y+\Delta y) - I(x, y) &\approx \big( I(x, y) + \partial_x I(x, y)\Delta x + \partial_y I(x, y)\Delta y \big) - I(x, y) \\
&= \partial_x I(x, y)\Delta x + \partial_y I(x, y)\Delta y
\end{split}
\]
By developing the error function into matrix form, we obtain the following:
\[
\begin{split}
E(\Delta x, \Delta y) &= \sum_{x, y} w(x, y) \big( I(x+\Delta x, y+\Delta y) - I(x, y) \big)^2 \\
&= \sum_{x, y} w(x, y) \big( \partial_x I(x, y)\Delta x + \partial_y I(x, y)\Delta y \big)^2 \\
&= \sum_{x, y} w(x, y) \big( \partial_x^2 I(x, y)\Delta x^2 + 2 \partial_x I(x, y) \partial_y I(x, y) \Delta x \Delta y + \partial_y^2 I(x, y)\Delta y^2 \big) \\
&= \sum_{x, y} w(x, y) \left(
\begin{bmatrix} \Delta x & \Delta y \end{bmatrix}
\begin{bmatrix}
\partial_x^2 I(x, y) & \partial_x I(x, y) \partial_y I(x, y) \\
\partial_x I(x, y) \partial_y I(x, y) & \partial_y^2 I(x, y)
\end{bmatrix}
\begin{bmatrix} \Delta x \\ \Delta y \end{bmatrix}
\right) \\
&= \begin{bmatrix} \Delta x & \Delta y \end{bmatrix}
\begin{bmatrix}
\sum_{x, y} w(x, y) \partial_x^2 I(x, y) & \sum_{x, y} w(x, y) (\partial_x I(x, y) \partial_y I(x, y)) \\
\sum_{x, y} w(x, y) (\partial_x I(x, y) \partial_y I(x, y)) & \sum_{x, y} w(x, y) \partial_y^2 I(x, y)
\end{bmatrix}
\begin{bmatrix} \Delta x \\ \Delta y \end{bmatrix} \\
&= \begin{bmatrix} \Delta x & \Delta y \end{bmatrix}
\matr{M}
\begin{bmatrix} \Delta x \\ \Delta y \end{bmatrix} \\
\end{split}
\]
\begin{description}
\item[Structure matrix] \marginnote{Structure matrix}
Matrix $\matr{M}_w$ that encodes the local structure of the image at the pixels within a window $w$.
\[ \matr{M}_w = \begin{pmatrix}
\sum_{x, y} w(x, y) \partial_x^2 I(x, y) & \sum_{x, y} w(x, y) (\partial_x I(x, y) \partial_y I(x, y)) \\
\sum_{x, y} w(x, y) (\partial_x I(x, y) \partial_y I(x, y)) & \sum_{x, y} w(x, y) \partial_y^2 I(x, y)
\end{pmatrix} \]
$\matr{M}_w$ is real and symmetric, thus it is diagonalizable through an orthogonal matrix $\matr{R}$:
\[ \matr{M}_w = \matr{R} \begin{pmatrix} \lambda_1^{(w)} & 0 \\ 0 & \lambda_2^{(w)} \end{pmatrix} \matr{R}^T \]
$\matr{R}^T$ is the rotation matrix that aligns the image to the eigenvectors of $\matr{M}_w$,
while the eigenvalues remain the same for any rotation of the same patch.
Therefore, the eigenvalues $\lambda_1^{(w)}, \lambda_2^{(w)}$ of $\matr{M}_w$ allow to detect intensity changes along the shift directions:
\[
\begin{split}
E(\Delta x, \Delta y) &= \begin{pmatrix} \Delta x & \Delta y \end{pmatrix}
\begin{pmatrix} \lambda_1^{(w)} & 0 \\ 0 & \lambda_2^{(w)} \end{pmatrix}
\begin{pmatrix} \Delta x \\ \Delta y \end{pmatrix} \\
&= \lambda_1^{(w)} \Delta x^2 + \lambda_2^{(w)} \Delta y^2
\end{split}
\]
\begin{figure}[H]
\centering
\includegraphics[width=0.6\linewidth]{./img/_harris_rotation.pdf}
\caption{Eigenvalues relationship at different regions of an image.}
\end{figure}
\end{description}
\subsection{Algorithm}
\marginnote{Harris' corner detector}
As computing the eigenvalues of $\matr{M}_w$ at each pixel is expensive, a more efficient cornerness function is the following:
\[
\begin{split}
C(x, y) &= \lambda_1^{(w)}\lambda_2^{(w)} - k(\lambda_1^{(w)} + \lambda_2^{(w)})^2 \\
&= \det(\matr{M}_{w(x,y)}) - k \cdot \text{trace}(\matr{M}_{w(x,y)})^2
\end{split}
\]
where $k$ is a hyperparameter (empirically in $[0.04, 0.06]$).
\begin{figure}[H]
\centering
\includegraphics[width=0.5\linewidth]{./img/_harris_efficient.pdf}
\caption{Cornerness at different regions.}
\end{figure}
After computing the cornerness of each pixel, one can apply thresholding and then NMS.
\begin{remark}
The window function $w(x, y)$ in the original work follows a Gaussian distribution.
\end{remark}
\subsection{Properties}
Harris' corner detector enjoys the following properties:
\begin{descriptionlist}
\item[Rotation invariance]
The eigenvalues are invariant to a rotation of the image.
\item[No affine intensity change invariance]
An affine intensity change of a signal consists of a gain factor and the addition of a bias (i.e. $I' = \alpha I + \beta$).
\begin{description}
\item[Invariance to bias]
Harris' detector is invariant to an additive bias ($I' = I + \beta$) as a consequence of the approximate derivative computation:
\[
\partial_x I'(i, j) = I'(i, j+1) - I'(i, j) = (I(i, j+1) + \cancel{\beta}) - (I(i, j) + \cancel{\beta})
\]
\item[No invariance to gain factor]
Harris' detector is not invariant to a gain factor ($I' = \alpha I$) as the multiplicative factor is carried in the derivatives.
\end{description}
\begin{remark}
In other words, Harris' detector is not illumination invariant.
\end{remark}
\item[No scale invariance]
Harris' detector is not scale invariant as the use of a fixed window size makes it impossible to recognize the same features when the image is scaled.
\end{descriptionlist}
\section{Multi-scale feature detector}
% \subsection{Scale invariance}
Depending on the scale, an image may exhibit more or less details.
A naive approach consists of using a smaller window size for images with a smaller scale,
but this is not always able to capture the same features due to the details difference.
\begin{description}
\item[Scale-space] \marginnote{Scale-space}
One-parameter family of images obtained by increasingly smoothing the input image.
\begin{remark}
When smoothing, small details should disappear and no new structures should be introduced.
\end{remark}
\begin{remark}
It is possible to use the same window size when working with scale-space images.
\end{remark}
\begin{description}
\item[Gaussian scale-space] \marginnote{Gaussian scale-space}
Scale-space obtained using Gaussian smoothing:
\[ L(x, y, \sigma) = I(x, y) * G(x, y, \sigma) \]
where $\sigma$ is the standard deviation but also the level of scaling.
\begin{figure}[H]
\centering
\includegraphics[width=0.8\linewidth]{./img/_scale_space_example.pdf}
\caption{Gaussian scale-space example}
\end{figure}
\end{description}
\end{description}
\subsection{Scale-normalized LoG blob detection}
\begin{description}
\item[Scale-normalized Laplacian of Gaussian] \marginnote{Scale-normalized Laplacian of Gaussian}
LoG scaled by a factor of $\sigma^2$:
\[ F(x, y, \sigma) = \sigma^2 \nabla^{(2)} L(x, y, \sigma) = \sigma^2 (I(x, y) * \nabla^{(2)} G(x, y, \sigma)) \]
$\sigma^2$ avoids small derivatives when the scaling ($\sigma$) is large.
\item[Characteristic scale] Scale $\sigma$ that produces a peak in the Laplacian response at a given pixel \cite{slides:scale_normalized_log}.
\item[Algorithm] \marginnote{Scale-normalized LoG blob detection}
Blob (circle) detection using scale-normalized LoG works as follows \cite{slides:scale_normalized_log}:
\begin{enumerate}
\item Create a Gaussian scale-space by applying the scale-normalized Laplacian of Gaussian with different values of $\sigma$.
\item For each pixel, find the characteristic scale and its corresponding Laplacian response across the scale-space (automatic scale selection).
\item Filter out the pixels whose response is lower than a threshold and apply NMS.
\item The remaining pixels are the centers of the blobs.
It can be shown that the radius is given by $r = \sigma\sqrt{2}$.
\end{enumerate}
\end{description}
When detecting a peak, there are two cases:
\begin{descriptionlist}
\item[Maximum] Dark blobs on a light background.
\item[Minimum] Light blobs on a dark background.
\end{descriptionlist}
\begin{figure}[H]
\centering
\includegraphics[width=0.6\linewidth]{./img/LOG_blob_detection_example.png}
\caption{Example of application of the algorithm}
\end{figure}
\begin{remark}
The intuitive idea of the detection algorithm is the following:
\begin{itemize}
\item $F(x, y, \sigma)$ keeps growing for $\sigma$s that capture areas within the blob (i.e. with similar intensity).
\item The Laplacian reaches its peak when its weights capture the entire blob (virtually it detects an edge).
\item After the peak, the LoG filter will also capture intensities outside the blob and therefore decrease.
\end{itemize}
\end{remark}
\begin{remark}
Using different scales creates the effect of searching in a 3D space.
\end{remark}
\begin{remark}
Scale-normalized LoG blob detection is scale and rotation invariant.
\end{remark}
\begin{remark}
It empirically holds that, given two points representing the centers of two blobs,
the ratio between the two characteristic scales is approximately the ratio between the diameters of the two blobs.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\linewidth]{./img/_scaled_log_blob_diameter.pdf}
\caption{
\begin{varwidth}[t]{0.55\linewidth}
Scale-normalized LoG computed on varying $\sigma$.\\
Note that, in the second image, the characteristic scale is
higher as the scale is larger.
\end{varwidth}
}
\end{figure}
\end{remark}
\subsection{Difference of Gaussians blob detection}
\begin{description}
\item[Difference of Gaussians (DoG)] \marginnote{Difference of Gaussians (DoG)}
Approximation of the scale-normalized LoG computed as:
\[
\begin{split}
\texttt{DoG}(x, y, \sigma) &= \big( G(x, y, k\sigma) - G(x, y, \sigma) \big) * I(x, y) \\
&= L(x, y, k\sigma) - L(x, y, \sigma)
\end{split}
\]
\begin{theorem}
It can be proven that the DoG kernel is a scaled version of the LoG kernel:
\[ G(x, y, k\sigma) - G(x, y, \sigma) \approx (k-1)\sigma^2 \nabla^{(2)}G(x, y, \sigma) \]
\begin{remark}
As we are interested in extrema, the scaling factor is irrelevant.
\end{remark}
\end{theorem}
\item[Extrema detection] \marginnote{DoG extrema}
Given three DoG images with scales $\sigma_i$, $\sigma_{i-1}$ and $\sigma_{i+1}$,
a pixel $(x, y, \sigma_i)$ is an extrema (i.e. keypoint) iff:
\begin{itemize}
\item It is an extrema in a $3 \times 3$ patch centered on it (8 pixels as $(x, y, \sigma_i)$ is excluded).
\item It is an extrema in a $3 \times 3$ patch centered on the pixels at $(x, y, \sigma_{i-1})$ and at $(x, y, \sigma_{i+1})$ ($9+9$ pixels).
\end{itemize}
\begin{center}
\includegraphics[width=0.35\linewidth]{./img/_DoG_extrema.pdf}
\end{center}
\item[Algorithm] \marginnote{DoG blob detection}
To detect blob centers (i.e. a DoG extrema), an octave of $s$ DoG images is computed as follows:
\begin{enumerate}
\item Compute a scale-space $L$ of $s+1$ Gaussian smoothed images with $\sigma$ varying by a factor $k = 2^{1/s}$.
As the extrema detection method requires checking the DoG images above and below,
two additional Gaussians (with scales $k^{-1}\sigma$ and $k^{s+1}\sigma$) are computed.
\item The DoG image $\texttt{DoG}(\cdot, \cdot, k^i\sigma)$ is obtained as the difference between the
images $L(\cdot, \cdot, k^{i+1}\sigma)$ and $L(\cdot, \cdot, k^i\sigma)$ of the Gaussian scale-space.
\begin{figure}[H]
\small
\centering
\includegraphics[width=0.6\linewidth]{./img/_DoG_octave.pdf}
\caption{Example of octave computation with $s=4$}
\end{figure}
\item Extrema detection is done as described above across the $s$ DoG images.
\item Points with a weak DoG response can be pruned through thresholding.
Furthermore, it has been observed that strong DoG points along edges are unstable and can be also pruned.
\end{enumerate}
Octaves should be computed using different starting $\sigma$s.
Instead of recomputing the Gaussian scale-space,
it is possible to simply down-sample the already computed Gaussians and compute the DoG images starting from shrunk smoothed images.
\begin{remark}
In the original work, the input image is first enlarged by a factor of 2.
Then, four octaves are computed starting from the enlarged image
(i.e. images of size factor $\times 2$, $\times 1$, $\times \frac{1}{2}$ and $\times \frac{1}{4}$ are considered).
\end{remark}
\begin{remark}
The original work found out that the best hyperparameters are $s=3$ and $\sigma=1.6$.
\end{remark}
\end{description}
\begin{remark}
DoG blob detection is scale and rotation invariant.
\end{remark}
\section{Descriptor}
After finding the keypoints, a descriptor of a keypoint is computed from the pixels within a patch centered on it.
\subsection{DoG descriptor}
\begin{description}
\item[Canonical / Characteristic orientation] \marginnote{Canonical / Characteristic orientation}
Direction along which the magnitudes of the gradients of the neighboring pixels of a keypoint are the highest.
Given a pixel $(x, y)$, its gradient magnitude and direction is computed from the Gaussian smoothed image $L$:
\[
\begin{split}
\vert \nabla L(x, y) \vert &= \sqrt{ \big( L(x+1, y) - L(x-1, y) \big)^2 + \big( L(x, y+1) - L(x, y-1) \big)^2 } \\
\theta_L(x, y) &= \tan^{-1}\left( \frac{L(x, y+1) - L(x, y-1)}{L(x+1, y) - L(x-1, y)} \right)
\end{split}
\]
\begin{description}
\item[Orientation histogram] \marginnote{Orientation histogram}
By dividing the directions into bins (e.g. bins of size $10^\circ$),
it is possible to define for each keypoint a histogram by considering its neighboring pixels within a patch.
For each pixel $(x, y)$ neighboring a keypoint $(x_k, y_k)$, its contribution to the histogram along the direction $\theta_L(x, y)$ is given by:
\[ G_{(x_k, y_k)}(x, y, \frac{3}{2} \sigma_s(x_k, y_k)) \cdot \vert \nabla L(x, y) \vert \]
where $G_{(x_k, y_k)}$ is a Gaussian centered on the keypoint and $\sigma_s(x_k, y_k)$ is the scale of the keypoint.
The characteristic orientation of a keypoint is given by the highest peak of the orientation histogram.
Other peaks that are higher than at least $80\%$ of the main one are also considered characteristic orientations
(i.e. a keypoint might have multiple canonical orientations and, therefore, multiple descriptors).
For a more accurate estimation, a parabola is interpolated on the neighborhood of each peak and
the two bins adjacent to the peak of the parabola are considered.
\begin{figure}[H]
\centering
\includegraphics[width=0.45\linewidth]{./img/_canonical_histogram.pdf}
\caption{Orientation histogram and parabola interpolation}
\end{figure}
\end{description}
\end{description}
\begin{description}
\item[DoG descriptor] \marginnote{DoG descriptor}
Keypoints are found using the DoG detector and the descriptors are computed through patches along the canonical orientations.
\begin{remark}
DoG descriptor is scale and rotation invariant.
\end{remark}
\end{description}
\subsection{Scale invariant feature transform (SIFT) descriptor}
\marginnote{SIFT descriptor}
Given a keypoint, SIFT detector works as follows:
\begin{enumerate}
\item Center on the keypoint a $16 \times 16$ grid divided into $4 \times 4$ regions.
\item Compute for each region its orientation histogram with eight bins (i.e. bins of size $45^\circ$).
The Gaussian weighting function is centered on the keypoint and has $\sigma$ equal to half the grid size.
\item The descriptor is obtained by concatenating the histograms of each region.
This results in a feature vector with $128$ elements ($(4 \cdot 4) \cdot 8$).
\item Normalize the descriptor to unit length. Pixels larger than $0.2$ are saturated and normalized again (for illumination invariance).
\end{enumerate}
\begin{figure}[H]
\centering
\includegraphics[width=0.6\linewidth]{./img/sift.png}
\caption{SIFT detector example}
\end{figure}
\begin{description}
\item[Trilinear interpolation]
Bins are assigned in a soft manner to avoid boundary effects.
The contribution of a pixel is spread between its two adjacent bins weighted by the distance to the bin centers:\\
\begin{minipage}{0.55\linewidth}
\centering
\includegraphics[width=0.6\linewidth]{./img/_sift_interpolation.pdf}
\end{minipage}
\begin{minipage}{0.3\linewidth}
\[
\begin{cases}
\text{weight}_k = 1 - d_k \\
\text{weight}_{k+1} = 1 - d_{k+1} \\
\end{cases}
\]
\end{minipage}
This is done both on the histogram within a region and on the histograms between the four neighboring regions.
\end{description}
\begin{remark}
SIFT descriptor is scale, rotation and affine intensity change invariant.
\end{remark}
\section{Matching}
Matching the keypoints across different views is a nearest-neighbor search problem. \marginnote{Nearest-neighbor search problem}
Given a target image $T$ and a reference image $R$,
we want to match each keypoint in $T$ to the most similar one in $R$ (usually using the Euclidean distance).
\begin{description}
\item[Matching criteria] \marginnote{Matching criteria}
Given the distance $d_\text{NN}$ to the nearest-neighbor of a keypoint of $T$ in $R$,
the match is accepted by respecting one of the following criteria:
\begin{descriptionlist}
\item[Threshold]
Given a threshold $T$, the match is accepted iff:
\[ d_\text{NN} \leq T \]
\item[Ratio of distances]
Given a threshold $T$ and the distance to the second nearest-neighbor $d_\text{NN2}$, the match is accepted iff:
\[ \frac{d_\text{NN}}{d_\text{NN2}} \leq T \]
This method allows to avoid ambiguity if two neighbors are too close.
\begin{figure}[H]
\centering
\begin{subfigure}{0.4\linewidth}
\centering
\includegraphics[width=0.2\linewidth]{./img/_nn_matching_example1.pdf}
\caption{Non ambiguous match}
\end{subfigure}
\begin{subfigure}{0.4\linewidth}
\centering
\includegraphics[width=0.2\linewidth]{./img/_nn_matching_example2.pdf}
\caption{Ambiguous match}
\end{subfigure}
\end{figure}
\end{descriptionlist}
\begin{remark}
It has been empirically shown that a threshold $T=0.8$ allows to reject $90\%$ of wrong matches while missing $5\%$ of correct matches.
\end{remark}
\item[Efficient NN search] \marginnote{Efficient NN search}
As an exhaustive search is inefficient, indexing techniques may be employed.
The main indexing technique applied for feature matching is the k-d tree in the best bin first (BBF) variant.
\begin{remark}
Best bin first is not optimal.
\end{remark}
\end{description}

View File

@ -0,0 +1,462 @@
\chapter{Spatial filtering}
\section{Noise}
The noise added to a pixel $p$ is defined by $n_k(p)$,
where $k$ indicates the time step (i.e. noise changes depending on the moment the image is taken).
It is assumed that $n_k(p)$ is i.i.d and $n_k(p) \sim \mathcal{N}(0, \sigma)$.
The information of a pixel $p$ is therefore defined as:
\[ I_k(p) = \tilde{I}(p) + n_k(p) \]
where $\tilde{I}(p)$ is the real information.
\begin{description}
\item[Temporal mean denoising] \marginnote{Temporal mean denoising}
Averaging $N$ images taken at different time steps.
\[
\begin{split}
O(p) &= \frac{1}{N} \sum_{k=1}^{N} I_k(p) \\
&= \frac{1}{N} \sum_{k=1}^{N} \Big( \tilde{I}(p) + n_k(p) \Big) \\
&= \frac{1}{N} \sum_{k=1}^{N} \tilde{I}(p) + \overbrace{\frac{1}{N} \sum_{k=1}^{N} n_k(p)}^{\mathclap{\text{$\mu = 0$}}} \\
&\approx \tilde{I}(p)
\end{split}
\]
\begin{remark}
As multiple images of the same object are required, this method is only suited for static images.
\end{remark}
\item[Spatial mean denoising] \marginnote{Spatial mean denoising}
Given an image, average across neighboring pixels.
Let $K_p$ be the pixels in a window around $p$ (included):
\[
\begin{split}
O(p) &= \frac{1}{\vert K_p \vert} \sum_{q \in K_p} I(p) \\
&= \frac{1}{\vert K_p \vert} \sum_{q \in K_p} \Big( \tilde{I}(q) + n(q) \Big) \\
&= \frac{1}{\vert K_p \vert} \sum_{q \in K_p} \tilde{I}(q) + \frac{1}{\vert K_p \vert} \sum_{q \in K_p} n(q) \\
&\approx \frac{1}{\vert K_p \vert} \sum_{q \in K_p} \tilde{I}(q)
\end{split}
\]
\begin{remark}
As the average of neighboring pixels is considered, this method is only suited for uniform regions.
\end{remark}
\end{description}
\section{Convolutions}
\subsection{Preliminaries}
\begin{description}
\item[Convolution] \marginnote{Continuous convolution}
Given two functions $f$ and $g$, their 1D convolution is defined as \cite{wiki:1d_convolution}:
\[ (f * g)(t) = \int_{-\infty}^{+\infty} f(\tau)g(t - \tau) \,\text{d}\tau \]
In other words, at each $t$, a convolution can be interpreted as the area under $f(\tau)$
weighted by $g(t - \tau)$ (i.e. $g(\tau)$ flipped w.r.t. the y-axis and with the argument shifted by $t$).
Alternatively, it can be seen as the amount of overlap between $f(\tau)$ and $g(t - \tau)$.
\begin{figure}[h]
\centering
\includegraphics[width=0.4\textwidth]{./img/continuous_convolution_example.png}
\caption{Example of convolution}
\end{figure}
Extended to the 2-dimensional case, the definition becomes:
\[ (f * g)(x, y) = \int_{-\infty}^{+\infty} \int_{-\infty}^{+\infty} f(\alpha, \beta)g(x-\alpha, y-\beta) \,\text{d}\alpha\,\text{d}\beta \]
A convolution enjoys the following properties: \marginnote{Convolution properties}
\begin{descriptionlist}
\item[Associative] $f * (g * h) = (f * g) * h$.
\item[Commutative] $f * g = g * f$.
\item[Distributive w.r.t. sum] $f * (g + h) = f*g + f*h$.
\item[Commutative with differentiation] $(f*g)' = f' * g = f * g'$
\end{descriptionlist}
\item[Dirac delta] \marginnote{Dirac delta}
The Dirac delta "function" $\delta$ is defined as follows \cite{wiki:dirac,book:sonka}:
\[ \forall x \neq 0: \delta(x) = 0 \text{, constrained to } \int_{-\infty}^{+\infty} \delta(x) \,\text{d}x = 1 \]
Extended to the 2-dimensional case, the definition is the following:
\[ \forall (x, y) \neq (0, 0): \delta(x, y) = 0 \text{, constrained to } \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} \delta(x, y) \,\text{d}x\,\text{d}y = 1 \]
\begin{description}
\item[Sifting property] \marginnote{Sifting property}
The following property holds:
\[ \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} f(x, y) \delta(\alpha-x, \beta-y) \,\text{d}x\,\text{d}y = f(\alpha, \beta) \]
\begin{remark}
Exploiting the sifting property, the signal of an image can be expressed through an integral of Dirac deltas
(i.e. a linear combination) \cite{slides:filters,book:sonka}:
\[ i(x, y) = \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} i(\alpha, \beta) \delta(x-\alpha, y-\beta) \,\text{d}\alpha\,\text{d}\beta \]
\end{remark}
\end{description}
\item[Kronecker delta] \marginnote{Kronecker delta}
Discrete version of the Dirac delta \cite{wiki:kronecker}:
\[ \delta(x) = \begin{cases}
0 & \text{if $x \neq 0$} \\
1 & \text{if $x = 0$} \\
\end{cases} \]
Extended to the 2-dimensional case, the definition is the following:
\[ \delta(x, y) = \begin{cases}
0 & \text{if $(x, y) \neq (0, 0)$} \\
1 & \text{if $(x, y) = (0, 0)$} \\
\end{cases} \]
\begin{description}
\item[Sifting property] \marginnote{Sifting property}
The following property holds:
\[ i(x, y) = \sum_{\alpha=-\infty}^{+\infty} \sum_{\beta=-\infty}^{+\infty} i(\alpha, \beta) \delta(x-\alpha, y-\beta) \]
\end{description}
\end{description}
\subsection{Continuous convolutions}
\begin{description}
\item[Image filter] \marginnote{Image filter}
Operator that computes the new intensity of a pixel $p$ based on the intensities of a neighborhood of $p$.
\begin{remark}
Image filters are useful for denoising and sharpening operations.
\end{remark}
\item[Linear translation-equivariant (LTE) operator] \marginnote{LTE operator}
A 2D operator $T\{ \cdot \}$ is denoted as:
\[ T\{ i(x, y) \} = o(x, y) \]
$T\{ i(x, y) \}$ is LTE iff it is:
\begin{descriptionlist}
\item[Linear]
Given two input 2D signals $i(x, y)$, $j(x, y)$ and two constants $\alpha$, $\beta$, it holds that:
\[ T\{ \alpha \cdot i(x, y) + \beta \cdot j(x, y) \} = \alpha T\{ i(x, y) \} + \beta T\{ j(x, y) \} \]
\item[Translation-equivariant]
Given an input 2D signal $i(x, y)$ and two offsets $x_o$, $y_o$, it holds that:
\[ \text{if } T\{ i(x, y) \} = o(x, y) \text{ then } T\{ i(x-x_o, y-y_o) \} = o(x-x_o, y-y_o) \]
\end{descriptionlist}
\begin{description}
\item[Impulse response/Point spread function/Kernel]
Given a 2D operator $T\{ \cdot \}$,
its impulse response, denoted with $h$, is the output of the operator when the input signal is a Dirac delta \cite{slides:filters}:
\[ h(x, y) \triangleq T\{ \delta(x, y) \} \]
\end{description}
\end{description}
\begin{theorem}[LTE operators as convolutions] \marginnote{LTE operators as convolutions}
Applying an LTE operator on an image is equivalent to computing the convolution between the image and the impulse response $h$ of the operator.
\[
\begin{split}
T\{ i(x, y) \} &= \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} i(\alpha, \beta) h(x-\alpha, y-\beta) \,\text{d}\alpha\,\text{d}\beta \\
&= i(x, y) * h(x, y)
\end{split}
\]
In other words, the impulse response allows to compute the output of any input signal through a convolution.
\begin{proof}
Let $i(x, y)$ be an input signal and $T\{ \cdot \}$ be a 2D operator.
We have that:
\begin{align*}
T\{ i(x, y) \}
&= T\left\{ \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} i(\alpha, \beta) \delta(x-\alpha, y-\beta) \,\text{d}\alpha\,\text{d}\beta \right\}
& \text{sifting property} \\
%
&= \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} T\left\{ i(\alpha, \beta) \delta(x-\alpha, y-\beta) \right\} \,\text{d}\alpha\,\text{d}\beta
& \text{linearity of $T\{ \cdot \}$} \\
%
&= \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} i(\alpha, \beta) T\left\{ \delta(x-\alpha, y-\beta) \right\} \,\text{d}\alpha\,\text{d}\beta
& \text{linearity of $T\{ \cdot \}$} \\
%
&= \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} i(\alpha, \beta) h(x-\alpha, y-\beta) \,\text{d}\alpha\,\text{d}\beta
& \text{\small translation-equivariance of $T\{ \cdot \}$} \\
%
&= i(x, y) * h(x, y)
& \text{definition of convolution} \\
\end{align*}
\end{proof}
\end{theorem}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\textwidth]{./img/_convolution_graphical.pdf}
\caption{Visualization of a convolution}
\end{figure}
\begin{description}
\item[Cross-correlation] \marginnote{Cross-correlation}
Given two signals $i(x, y)$ and $h(x, y)$,
their cross-correlation computes their similarity and is defined as follows \cite{wiki:crosscorrelation}:
\[
i(x, y) \circ h(x, y) =
\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} i(\alpha, \beta) h(x+\alpha, y+\beta) \,\text{d}\alpha\,\text{d}\beta =
\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} h(\alpha, \beta) i(\alpha-x, \beta-y) \,\text{d}\alpha\,\text{d}\beta
\]
\[
h(x, y) \circ i(x, y) =
\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} h(\alpha, \beta) i(x+\alpha, y+\beta) \,\text{d}\alpha\,\text{d}\beta =
\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} i(\alpha, \beta) h(\alpha-x, \beta-y) \,\text{d}\alpha\,\text{d}\beta
\]
\begin{remark}
Cross-correlation is not commutative.
\end{remark}
\begin{remark}
The cross-correlation $h \circ i$ is similar to a convolution without flipping the kernel.
If $h$ is an even function (i.e. $h(x, y) = h(-x, -y)$), we have that $h \circ i$ has the same result of a convolution:
\begin{align*}
h(x, y) * i(x, y) &= \int_{-\infty}^{+\infty} \int_{-\infty}^{+\infty} i(\alpha, \beta)h(x-\alpha, y-\beta) \,\text{d}\alpha\,\text{d}\beta \\
&= \int_{-\infty}^{+\infty} \int_{-\infty}^{+\infty} i(\alpha, \beta)h(\alpha-x, \beta-y) \,\text{d}\alpha\,\text{d}\beta
& \parbox[b]{0.25\textwidth}{\raggedleft signs in $h$ swappable for Dirac delta} \\
&= h(x, y) \circ i(x, y)
\end{align*}
\end{remark}
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{./img/crosscorrelation_graphical.png}
\caption{Visualization of cross-correlation}
\end{figure}
\end{description}
\subsection{Discrete convolutions}
\begin{description}
\item[Discrete convolution] \marginnote{Discrete convolution}
Given an input 2D signal $I(i, j)$ and the kernel $H(i, j) = T\{ \delta(i, j) \}$ of a discrete LTE operator (where $\delta(i, j)$ is the Kronecker delta),
a discrete convolution is defined as:
\[ T\{ I(i, j) \} = \sum_{m=-\infty}^{+\infty} \sum_{n=-\infty}^{+\infty} I(m, n)H(i-m, j-n) = O(i, j) \]
In practice, the kernel is finitely defined and is applied to each pixel of the image:
\[ T\{ I(i, j) \} = \sum_{m=-k}^{k} \sum_{n=-k}^{k} K(m, n)I(i-m, j-n) = O(i, j) \]
\begin{example}
For simplicity, a kernel of size 3 is considered.
Given an image $I$ and a kernel $K$, the output $O(1, 1)$ of the pixel $(1, 1)$ is computed as:
\[
\begin{split}
O(1, 1) &= \begin{pmatrix}
I(0, 0) & I(0, 1) & I(0, 2) \\
I(1, 0) & I(1, 1) & I(1, 2) \\
I(2, 0) & I(2, 1) & I(2, 2) \\
\end{pmatrix}
*
\begin{pmatrix}
K(0, 0) & K(0, 1) & K(0, 2) \\
K(1, 0) & K(1, 1) & K(1, 2) \\
K(2, 0) & K(2, 1) & K(2, 2) \\
\end{pmatrix} \\
&= I(0, 0)K(2, 2) + I(0, 1)K(2, 1) + I(0, 2)K(2, 0) + \\
&\,\,\,\,\,+ I(1, 0)K(1, 2) + I(1, 1)K(1, 1) + I(1, 2)K(1, 0) + \\
&\,\,\,\,\,+ I(2, 0)K(0, 2) + I(2, 1)K(0, 1) + I(2, 2)K(0, 0)
\end{split}
\]
Note that by definition, $K$ has to be flipped.
\end{example}
\begin{remark}
In convolutional neural networks, the flip of the learned kernels can be considered implicit.
\end{remark}
\begin{description}
\item[Border handling] \marginnote{Border handling}
Computing the convolution of the pixels at the borders of the image might be an issue as it goes out-of-bounds,
possible solutions are:
\begin{descriptionlist}
\item[Crop] Ignore border pixels on which the convolution overflows.
\item[Pad] Add a padding to the image:
\begin{descriptionlist}
\item[Zero-padding] Add zeros (e.g. $\texttt{000}\vert a \dots d \vert\texttt{000}$).
\item[Replicate] Repeat the bordering pixel (e.g. $\texttt{aaa}\vert a \dots d \vert\texttt{ddd}$).
\item[Reflect] Use the $n$ pixels closest to the border (e.g. $\texttt{cba}\vert abc \dots dfg \vert\texttt{gfd}$).
\item[Reflect\_101] Use the $n$ pixels closest to the border, skipping the first/last one (e.g. $\texttt{dcb}\vert abcd \dots efgh \vert\texttt{gfe}$).
\end{descriptionlist}
\end{descriptionlist}
\end{description}
\end{description}
\subsection{Common linear kernels}
\begin{description}
\item[Mean filter] \marginnote{Mean filter}
LTE operator that computes the intensity of a pixel as the average intensity of the pixels in its neighborhood.
The kernel has the form (example with a $3 \times 3$ kernel):
\[
\begin{pmatrix}
\frac{1}{9} & \frac{1}{9} & \frac{1}{9} \\
\frac{1}{9} & \frac{1}{9} & \frac{1}{9} \\
\frac{1}{9} & \frac{1}{9} & \frac{1}{9} \\
\end{pmatrix}
=
\frac{1}{9} \begin{pmatrix}
1 & 1 & 1 \\
1 & 1 & 1 \\
1 & 1 & 1 \\
\end{pmatrix}
\]
\begin{remark}
The mean filter has a low-pass effect which allows the removal of details from the signal.
This allows for image smoothing and, to some extent, denoising (but adds blur).
\end{remark}
\begin{remark}
As the intensity of a pixel is computed by averaging its neighborhood,
the results for pixels located between low-intensity and high-intensity areas might not be ideal.
\end{remark}
\begin{figure}[H]
\centering
\includegraphics[width=0.85\textwidth]{./img/_mean_filter_example.pdf}
\caption{Example of mean filter application}
\end{figure}
\item[Gaussian filter] \marginnote{Gaussian filter}
LTE operator whose kernel follows a 2D Gaussian distribution with $\mu=0$ and given $\sigma$.
\begin{remark}
The smoothing strength of the filter grows with $\sigma$.
\end{remark}
\begin{figure}[H]
\centering
\includegraphics[width=0.85\textwidth]{./img/_gaussian_filter_example.pdf}
\caption{Example of Gaussian filter application}
\end{figure}
\begin{description}
\item[Sampling]
In practice, the kernel is created by sampling from the wanted Gaussian distribution.
One can notice that a higher $\sigma$ results in a more spread distribution and therefore a larger kernel is more suited,
on the other hand, a smaller $\sigma$ can be represented using a smaller kernel as it is more concentrated around the origin.
As a rule-of-thumb, given $\sigma$, an ideal kernel is of size $(2\lceil 3\sigma \rceil + 1) \times (2\lceil 3\sigma \rceil + 1)$.
\item[Separability]
As a 2D Gaussian $G(x, y)$ can be decomposed into a product of two 1D Gaussians $G(x, y) = G_1(x)G_2(y)$,
it is possible to split the convolution into two 1D convolutions.
\[
\begin{split}
I(x, y) * G(x, y) &= \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} I(\alpha, \beta) G(x-\alpha, y-\beta) \,\text{d}\alpha\,\text{d}\beta \\
&= \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty} I(\alpha, \beta) G_1(x-\alpha)G_2(y-\beta) \,\text{d}\alpha\,\text{d}\beta \\
&= \int_{-\infty}^{+\infty} G_2(y-\beta) \left( \int_{-\infty}^{+\infty} I(\alpha, \beta) G_1(x-\alpha) \,\text{d}\alpha \right) \,\text{d}\beta \\
&= (I(x, y) * G_1(x)) * G_2(y)
\end{split}
\]
\begin{remark}
The speed-up in number-of-operations is linear.
\end{remark}
\end{description}
\end{description}
\subsection{Common non-linear kernels}
\begin{remark}
Linear filters are ineffective when dealing with impulse noise and
have the side effect of blurring the image.
\begin{figure}[H]
\centering
\includegraphics[width=0.85\textwidth]{./img/_impulse_noise_example.pdf}
\caption{Example of impulse noise and denoising with mean filter}
\end{figure}
\end{remark}
\begin{remark}
As they lose linearity, non-linear filters are technically not convolutions anymore.
\end{remark}
\begin{description}
\item[Median filter] \marginnote{Median filter}
The intensity of a pixel is obtained as the median intensity of its neighborhood.
\begin{remark}
Median filters are effective in removing impulse noise (as outliers are excluded) without introducing significant blur.
It also tends to result in sharper edges.
\end{remark}
\begin{remark}
Median filters are not suited for Gaussian noise.
It might be useful to apply a linear filter after a median filter.
\end{remark}
\begin{figure}[H]
\centering
\includegraphics[width=0.85\textwidth]{./img/_median_filter_example.pdf}
\caption{Example of median filter application}
\end{figure}
\item[Bilateral filter] \marginnote{Bilateral filter}
Given two pixels $p$ and $q$, the following can be computed:
\begin{descriptionlist}
\item[Spatial distance] $d_s(p, q) = \Vert p - q \Vert_2$
\item[Range/intensity distance] $d_r(p, q) = \vert \texttt{intensity}(p) - \texttt{intensity}(q) \vert$
\end{descriptionlist}
Given a pixel $p$, its neighborhood $\mathcal{N}(p)$ and the variances $\sigma_s$, $\sigma_r$ of two Gaussians,
the bilateral filter applied on $p$ is computes as follows:
\[
\begin{split}
O(p) &= \sum_{q \in \mathcal{N}(p)} H(p, q) \cdot \texttt{intensity}(q) \\
&\text{where } H(p, q) = \frac{G_{\sigma_s}(d_s(p, q)) G_{\sigma_r}(d_r(p, q))}{\sum_{z \in \mathcal{N}(p)} G_{\sigma_s}(d_s(p, z)) G_{\sigma_r}(d_r(p, z))}
\end{split}
\]
where the denominator of $H$ is a normalization factor.
\begin{remark}
Bilateral filters allow to deal with Gaussian noise without the introduction of blur.
\end{remark}
\begin{remark}
Neighboring pixels with similar intensities result in larger weights in the filter,
while pixels with different intensities (i.e. near an edge) result in smaller weights.
This allows to effectively ignore pixels that belong to a different object from being considered when computing the intensity of a pixel.
\end{remark}
\begin{figure}[H]
\centering
\includegraphics[width=0.9\textwidth]{./img/_bilateral_filter_example.pdf}
\caption{Example of bilateral filter application}
\end{figure}
\item[Non-local means filter] \marginnote{Non-local means filter}
Exploits patches with similar pixels to denoise the image.
\begin{minipage}{0.75\textwidth}
Let:
\begin{itemize}
\item $I$ be the image plane.
\item $\mathcal{N}_i$ be the intensity matrix of a patch centered on the pixel $i$.
\item $S_i$ be a neighborhood of the pixel $i$.
\item $h$ be the bandwidth (a hyperparameter).
\end{itemize}
The intensity of a pixel $p$ is computed as follows:
\[
\begin{split}
O(p) &= \sum_{q \in S_p} w(p, q) \cdot \texttt{intensity}(q) \\
\text{where }& w(p, q) = \frac{1}{Z(p)} e^{-\frac{\Vert \mathcal{N}_p - \mathcal{N}_q \Vert_2^2}{h^2}} \\
& Z(p) = \sum_{q \in I} e^{\frac{\Vert \mathcal{N}_p - \mathcal{N}_q \Vert_2^2}{h^2}}
\end{split}
\]
\end{minipage}
\begin{minipage}{0.25\textwidth}
\centering
\includegraphics[width=\linewidth]{./img/non_local_means_filter.png}
\end{minipage}
Instead of using the full image plane $I$, a neighborhood $S_p$ is used for computational purposes.
$Z(p)$ is a normalization factor.
\end{description}