Disparity, Convergence, and Depth (Visual Depth Perception 10)

Manipulate[
nORM[vector_?VectorQ]:=(Sqrt[vector.vector]);
degrees[q_]:=q*180/π;
arcMinutes[q_]:=q*60*180/π;

aimψ[headAimVector_?VectorQ,base_?VectorQ]:=ArcTan[headAimVector[[1]],headAimVector[[2]]];

midPoint[headAimVector_?VectorQ,base_?VectorQ]:=base-aimOffset*interOcular*{headAimVector[[2]],-headAimVector[[1]]};

rightEyeCenter[headAimVector_?VectorQ,base_?VectorQ]:=base+((1/2)-aimOffset)*interOcular*{headAimVector[[2]],-headAimVector[[1]]};

leftEyeCenter[headAimVector_?VectorQ,base_?VectorQ]:=base-((1/2)+aimOffset)*interOcular*{headAimVector[[2]],-headAimVector[[1]]};


rightViewVector[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=fixate-rightEyeCenter[headAimVector, base];

rightφ[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=ArcTan[rightViewVector[headAimVector, fixate, base][[1]],rightViewVector[headAimVector, fixate, base][[2]]];

rightEyeNode[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=rightEyeCenter[headAimVector, base]+nodePercent*eyeRadius*rightViewVector[headAimVector,fixate, base]/nORM[rightViewVector[headAimVector, fixate, base]];

leftViewVector[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=fixate-leftEyeCenter[headAimVector, base];

leftφ[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=ArcTan[leftViewVector[headAimVector, fixate, base][[1]],leftViewVector[headAimVector, fixate, base][[2]]];

leftEyeNode[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=leftEyeCenter[headAimVector, base]+nodePercent*eyeRadius*leftViewVector[headAimVector, fixate, base]/nORM[leftViewVector[headAimVector, fixate, base]];

fixateConvergence[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=(rightφ[headAimVector,fixate,base]-leftφ[headAimVector,fixate,base]);

leftα[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=leftφ[headAimVector,fixate,base]-aimψ[headAimVector,base];
rightα[headAimVector_?VectorQ,fixate_?VectorQ,base_?VectorQ]:=rightφ[headAimVector,fixate,base]-aimψ[headAimVector,base];

rightDistractVector[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=distraction-rightEyeNode[headAimVector,fixate, base];

rightδ[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=ArcTan[rightDistractVector[headAimVector,fixate,distraction,base][[1]],rightDistractVector[headAimVector,fixate,distraction,base][[2]]];

leftDistractVector[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=distraction-leftEyeNode[headAimVector,fixate, base];

leftδ[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=ArcTan[leftDistractVector[headAimVector,fixate,distraction,base][[1]],leftDistractVector[headAimVector,fixate,distraction,base][[2]]];

convergenceDistraction[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=If[Or[Abs[leftφ[headAimVector,fixate, base]-leftδ[headAimVector,fixate, distraction,base]]>π/3.,Abs[rightφ[headAimVector,fixate, base]-rightδ[headAimVector,fixate, distraction,base]]>π/3.],0.0,(rightδ[headAimVector,fixate, distraction,base]-leftδ[headAimVector,fixate, distraction,base])];

rightθ[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=(rightφ[headAimVector,fixate, base]-rightδ[headAimVector,fixate,distraction,base]);

leftθ[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=(leftφ[headAimVector,fixate, base]-leftδ[headAimVector,fixate,distraction,base]);

binocularDisparity[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=If[Or[leftθ[headAimVector,fixate,distraction,base]<-π/2.,leftθ[headAimVector,fixate,distraction,base]>π/3.,rightθ[headAimVector,fixate,distraction,base]<-π/3.,rightθ[headAimVector,fixate,distraction,base]>π/2.],0,(rightθ[headAimVector,fixate,distraction,base]-leftθ[headAimVector,fixate,distraction,base])];

rightθinside[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=rightθ[headAimVector,fixate,distraction,base]+ArcSin[nodePercent*Sin[rightθ[headAimVector,fixate,distraction,base]]];

leftθinside[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=leftθ[headAimVector,fixate,distraction,base]+ArcSin[nodePercent*Sin[leftθ[headAimVector,fixate,distraction,base]]];

retinalDisparity[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=If[Or[leftθ[headAimVector,fixate,distraction,base]<-π/2.,leftθ[headAimVector,fixate,distraction,base]>π/3.,rightθ[headAimVector,fixate,distraction,base]<-π/3.,rightθ[headAimVector,fixate,distraction,base]>π/2.],0,(rightθinside[headAimVector,fixate,distraction,base]-leftθinside[headAimVector,fixate,distraction,base])];



eyePict[eyeCenter_?VectorQ,fixate_?VectorQ]:=Module[{λ,viewVector},viewVector=fixate-eyeCenter;
λ=ArcTan[viewVector[[1]],viewVector[[2]]];
viewVector=viewVector/nORM[viewVector];
Show[{Graphics[{AbsoluteThickness[2],Gray,Circle[eyeCenter,eyeRadius,{λ+.4,2π+λ-.4}]}],Graphics[{Gray,
Circle[eyeCenter+ .8eyeRadius viewVector,.5eyeRadius,{λ-1.5,λ+1.5}]}],
Graphics[{Green,
Disk[eyeCenter+eyeRadius*nodePercent*viewVector,eyeRadius/10]
}]
},AspectRatio->Automatic]];



eyeEdge[θ_]:=eyeRadius*{Cos[θ],Sin[θ]};

inRays[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=Show[{eyePict[leftEyeCenter[headAimVector, base],fixate],eyePict[rightEyeCenter[headAimVector,base],fixate],Graphics[{Red,{Line[{rightEyeNode[headAimVector,fixate,base],rightEyeCenter[headAimVector,base]-eyeRadius*rightViewVector[headAimVector,fixate,base]/nORM[rightViewVector[headAimVector,fixate,base]]}]}}],Graphics[{Red,{Line[{leftEyeNode[headAimVector,fixate,base],leftEyeCenter[headAimVector, base]-eyeRadius*leftViewVector[headAimVector,fixate,base]/nORM[leftViewVector[headAimVector,fixate,base]]}]}}],Graphics[{Blue,{Line[{rightEyeNode[headAimVector,fixate,base],rightEyeCenter[headAimVector,base]+eyeEdge[rightφ[headAimVector,fixate,base]-π-rightθinside[headAimVector,fixate,distraction,base]]}]}}],
Graphics[{Blue,{Line[{leftEyeNode[headAimVector,fixate,base],leftEyeCenter[headAimVector,base]+eyeEdge[leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]]}]}}],
Graphics[{Purple,{Line[{rightEyeCenter[headAimVector,base],rightEyeCenter[headAimVector,base]+eyeEdge[rightφ[headAimVector,fixate,base]-π-rightθinside[headAimVector,fixate,distraction,base]]}]}}],
Graphics[{Purple,{Line[{leftEyeCenter[headAimVector,base],leftEyeCenter[headAimVector,base]+eyeEdge[leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]]}]}}],
Graphics[{Green,{Line[N[{leftEyeCenter[headAimVector, base],rightEyeCenter[headAimVector, base]}]]}}],
min=Min[{leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]-retinalDisparity[headAimVector,fixate,distraction,base],leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]}];
MAX=Max[{leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]-retinalDisparity[headAimVector,fixate,distraction,base],leftφ[headAimVector,fixate,base]-π-leftθinside[headAimVector,fixate,distraction,base]}];
Graphics[{Brown,AbsoluteThickness[3],{Circle[leftEyeCenter[headAimVector, base],eyeRadius,{min,MAX}]}}]
},AspectRatio->Automatic,PlotRange->{{midPoint[headAimVector,base][[1]]-interOcular,midPoint[headAimVector,base][[1]]+interOcular},{midPoint[headAimVector,base][[2]]-interOcular,midPoint[headAimVector,base][[2]]+interOcular}}];


outRays[headAimVector_?VectorQ,fixate_?VectorQ,distraction_?VectorQ,base_?VectorQ]:=Show[{Graphics[{Red,AbsolutePointSize[4],{Point[N[fixate]]}}],Graphics[{Blue,AbsolutePointSize[4],{Point[N[distraction]]}}],Graphics[{Red,{Line[N[{fixate,rightEyeNode[headAimVector,fixate, base]}]]}}],Graphics[{Red,{Line[N[{fixate,leftEyeNode[headAimVector,fixate, base]}]]}}],Graphics[{Blue,{Line[N[{distraction,rightEyeNode[headAimVector,fixate, base]}]]}}],Graphics[{Blue,{Line[N[{distraction,leftEyeNode[headAimVector,fixate, base]}]]}}]
},AspectRatio->Automatic];


(*Real Program Starts Here*)
eyeRadius=1.3;interOcular=6.5;aimOffset=0;
nodePercent=0;base={0,0};
f=fixate[[2]];d=distraction[[2]]-fixate[[2]];
(*fixate={0,f};distraction={0,f+d};*)
aim=0;
headAimVector[aim_]:={Sin[aim π/180],Cos[aim π/180]};
Show[{
inRays[headAimVector[aim],fixate,distraction,base]
,
outRays[headAimVector[aim],fixate,distraction,base]
,
Graphics[{AbsolutePointSize[4],Point[midPoint[headAimVector[aim],base]]}]
,
Graphics[{Red,AbsolutePointSize[4],{Point[fixate],Text[Row[{Style["f",Italic]," = ",f," cm"}],scale{-.15,.4}],Line[{leftEyeNode[headAimVector[aim],fixate,base],fixate}],Line[{rightEyeNode[headAimVector[aim],fixate,base],fixate}],
Circle[fixate,1,{leftφ[headAimVector[aim],fixate,base]+π,rightφ[headAimVector[aim],fixate,base]+π}],Text[Row[{κ,
" = ",Round[arcMinutes[fixateConvergence[headAimVector[aim],fixate,base]]]," min"}],scale{-.15,.3}]}}]
,
Graphics[{Blue,AbsolutePointSize[5],{Point[distraction],Text[Row[{Style["d",Italic]," = ",d," cm"}],scale{-.15,.6}],Line[{leftEyeNode[headAimVector[aim],fixate,base],distraction}],Line[{rightEyeNode[headAimVector[aim],fixate,base],distraction}],Circle[distraction,1,{leftδ[headAimVector[aim],fixate, distraction,base]+π,rightδ[headAimVector[aim],fixate, distraction,base]+π}]}}],
Graphics[{Black,Text[Row[{HoldForm[(i/(2 Tan[κ/2]))]," = ",interOcular/(2 Tan[fixateConvergence[headAimVector[aim],fixate,base]/2])}],scale{.15,.4}]}]
,
Graphics[{Black,Text[Row[{HoldForm[i((Sin[(δ/2)])/(2 Sin[(κ/2)]Sin[((κ-δ)/2)]))]," = ",(interOcular/2)Sin[(1/2)binocularDisparity[headAimVector[aim],fixate,distraction,base]]/(Sin[(1/2)fixateConvergence[headAimVector[aim],fixate,base]]Sin[(1/2)(fixateConvergence[headAimVector[aim],fixate,base]-binocularDisparity[headAimVector[aim],fixate,distraction,base])])}],scale{.2,.6}]}]
,
Graphics[{Magenta,{Text[Row[{δ," = ",Round[N[arcMinutes[binocularDisparity[headAimVector[aim],fixate,distraction,base]]],.1]," min"}],scale{-.15,.5}]}}],
Graphics[{Red,AbsolutePointSize[4],{Point[fixate],Text["F",{-.05scale,f}]}}],
Graphics[{Blue,AbsolutePointSize[4],{Point[distraction],Text["D",{.05scale,f+d}]}}]
},PlotRange->{{-scale,scale}/2.5,{-2,scale}},AspectRatio->Automatic,ImageSize->{400,400}]
,{{fixate,{0,50}},{0,15},{0,100},Locator},
{{distraction,{0,60}},{0,5},{0,110},Locator},
{{scale,64},20,115,Appearance->"Labeled"},TrackedSymbols->Manipulate]

CAPTION

This Demonstration shows binocular disparity together with the convergence angle required for the eyes to fix on F. The angles δ and κ together determine the depth of objects on the y axis.

DETAILS

Binocular disparity has been studied since Euclid, but was popularized by Wheatstone about 150 years ago with the invention of the stereoscope. A stereoscope shows two slightly different images to the separate eyes and gives the scene the appearance of depth. However, disparity alone does not determine depth, as shown in the Demonstration "Binocular Disparity versus Depth (Visual Depth Perception 9)" (see Related Links). To simplify derivations for this Demonstration we take no aim offset and set the nodePercent equal to zero, that is, nodes are (unrealistically) at the center of the eye.

The exact formula for depth when the fixate and distraction are on the y axis (including sign) from B.D.=δ (in radians) for a given fixate distance f is given by the following formula with interocular distance i:

d=f((4 +((((i/f)))^2))/(2 ((i/f)-2 tan(δ/2))))tan(δ/2).

Binocular disparity does not determine depth since it requires the absolute fixate distance f. The value of f could come from a convergence cue since the convergence angle κ of the eyes is related to fixate distance by

f=(i/(2 tan(κ/2))),

so (after simplification) depth from static cues is

d=(i/2)((sin((δ/2)))/(sin((κ/2))sin(((κ-δ)/2)))).

For more information about stereoscopic vision, see the Wikipedia page.

THIS NOTEBOOK IS THE SOURCE CODE FROM

"Disparity, Convergence, and Depth (Visual Depth Perception 10)" from the Wolfram Demonstrations Project
 http://demonstrations.wolfram.com/DisparityConvergenceAndDepthVisualDepthPerception10/

Contributed by: Keith Stroyan

A full-function Wolfram Mathematica system (Version 6 or higher) is required to edit this notebook.
GET WOLFRAM MATHEMATICA »

© Wolfram Demonstrations Project & Contributors   |   Terms of Use   |   Make a new version of this Demonstration »