Omvendt kartlegging av VR-visningsprojeksjoner

Original English version: http://paulbourke.net/panorama/pimax/

Paul Bourke
oktober 2021

Følgende dokumenterer en øvelse i omvendt utvikling av projeksjonene generert for et VR-headset, spesifikt, og kartlegger dem tilbake til noe mer generelt. I dette tilfellet er projeksjonene som brukes av hodesettet vidvinkelperspektivvisninger, den ønskede remapping er til en halv ekvirektangulær projeksjon for YouTube. Driveren bak dette er å kunne legge ut spill på YouTube (og andre). Bildene skapt av spillet (MicroSoft Flight Simulator) fanges under spilling, teknikkene som er skissert konverterer denne stereoskopiske filmen til en topp-bunn halvt ekvirektangulær stereoskopisk film.

Headsettet det gjelder er Pimax 5K Plus, det er en rekke moduser som støttes og teknikkene her kan brukes på dem alle. Prosessen/pipelinen vil bli illustrert for “small+native”-modusen, perspektivgeometrien som er vist nedenfor for venstre øye, høyre øye er bare en speilversjon av dette. Merk at man må være forsiktig når man tolker spesifikasjonene, i dette tilfellet er det oppgitte horisontale synsfeltet 120,29 grader, men det er hele synsfeltet fra venstre kant av venstre øye til høyre kant av høyre øye. Tilsvarende er FOV for hver halvdel av 60,14 grader og 43,39 grader før avhuggingen roteres med 10 grader.

Det første å legge merke til er at perspektivet frustum er asymmetrisk. For å forenkle kartleggingen vil rammen økes i bredden for å gjøre den om til en symmetrisk avskjæring, det vil si at venstre og høyre kant av avskjæringen er en lik vinkel fra synsretningen. Mengden for å utvide venstre side av rammen (i dette tilfellet) bestemmes ved å beregne forholdet mellom venstre og høyre halvdel av frustum. Dette avhenger av brunfargen på vinklene som vist nedenfor.

I eksemplet her er bildeopptaket kun HD, ideelt sett ville man valgt en høyere oppløsning på 4K. Ved å bruke forholdet over midten av kameraets visningsretning kan det beregnes og dermed mengden som skal forlenges.

Et reelt eksempel presenteres deretter. Nedenfor er en faktisk fanget ramme som sendt til VR-headsettet. Selv om det ser rundt (som et fiskeøye), er det faktisk en perspektivprojeksjon med en sirkulær maske som tilsvarer grensene til headsetlinsen.

Det første trinnet er å beskjære bildene for hvert øye. Dette er bare på grunn av behovet for at venstre og høyre øye skal være inne i (i dette tilfellet) en 1920×1080 fangstramme.

Det følgende er polstret for hvert øye for å danne en symmetrisk avstumning.

Det neste trinnet er å kartlegge hver visning til en 180×180 grader ekvirektangulær (halv ekvirektangulær). Legg merke til at dette også må korrigere for +/-10 graders girkorreksjon som brukes i perspektivprojeksjonen for å håndtere den skråstilte visningen. Hvis alt har fungert riktig kan man sjekke at innhold ved uendelig har null parallakse.

Og til slutt koble dem sammen topp og bunn for det foretrukne YouTube-formatet. Legger merke til at det er andre arrangementer i vanlig bruk, for eksempel venstre-høyre.

Eksemplet som presenteres her er bare ett bilde fra den innspilte filmen. Filmen er transformert ved hjelp av ffmpeg. ffmpeg-skriptet som etterligner stadiene ovenfor er gitt nedenfor, det lager også en eksempelbilderamme på hvert trinn for testformål.

# Crop out the portion of the perspective image
# Scale by a factor of 2 in an attempt to mitigate compression and aliasing effects
ffmpeg -i pi-native-small-fov.mp4 -vf "crop=960:956:0:123,scale=1920:-1,setsar=1:1" left1.mp4
ffmpeg -ss 00:00:00 -i left1.mp4 -vframes 1 -q:v 1 -qmin 1 left1_sample.jpg
ffmpeg -i pi-native-small-fov.mp4 -vf "crop=960:956:960:123,scale=1920:-1,setsar=1:1" right1.mp4
ffmpeg -ss 00:00:00 -i right1.mp4 -vframes 1 -q:v 1 -qmin 1 right1_sample.jpg

# For values of padding note the images above have been scaled by a factor of 2, 2032 = 508*2*2
ffmpeg -i left1.mp4 -vf "pad=2032:ih:ow-iw:0:color=black" left2.mp4
ffmpeg -ss 00:00:00 -i left2.mp4 -vframes 1 -q:v 1 -qmin 1 left2_sample.jpg
ffmpeg -i right1.mp4 -vf "pad=2032:ih:0:0:color=black" right2.mp4
ffmpeg -ss 00:00:00 -i right2.mp4 -vframes 1 -q:v 1 -qmin 1 right2_sample.jpg

# Perform mapping to half an equirectangular (output=he) from a perspective (input=flat)
ffmpeg -i left2.mp4 -vf v360=input=flat:ih_fov=106.8:iv_fov=103.56:h_fov=180:v_fov=180:w=2160:\
	h=2160:yaw=10:output=he left3.mp4
ffmpeg -ss 00:00:00 -i left3.mp4 -vframes 1 -q:v 1 -qmin 1 left3_sample.jpg
ffmpeg -i right2.mp4 -vf v360=input=flat:ih_fov=106.8:iv_fov=103.56:h_fov=180:v_fov=180:w=2160:\
	h=2160:yaw=-10:output=he right3.mp4
ffmpeg -ss 00:00:00 -i right3.mp4 -vframes 1 -q:v 1 -qmin 1 right3_sample.jpg

# Finally combine into top/bottom arrangement
ffmpeg -i left3.mp4 -i right3.mp4 -c:v libx264 -crf 18 -filter_complex vstack left_right.mp4
ffmpeg -ss 00:00:00 -i left_right.mp4 -vframes 1 -q:v 1 -qmin 1 left_right_sample.jpg

I virkeligheten ville man ikke bruke flertrinns-tilnærmingen ovenfor siden bildeforringelse oppstår ved hver filmlagring. I stedet vil man normalt flate dette ut til en enkelt ffmpeg “delt” pipeline der den eneste tapsgivende lagringen skjer på slutten av alle tilordningene. For eksempel:

ffmpeg -i "pi-native-small-fov.mp4" -vf "split[left][right];\
   [left]crop=960:956:0:123,scale=1920:-1,setsar=1:1[left1];\
   [right]crop=960:956:960:123,scale=1920:-1,setsar=1:1[right1];\
   [left1]pad=2032:ih:ow-iw:0:color=black[left2];\
   [right1]pad=2032:ih:0:0:color=black[right2];\
   [left2]v360=input=flat:ih_fov=106.8:iv_fov=103.56:h_fov=180:v_fov=180:w=2160:h=2160:yaw=10:output=he[left3];\
   [right2]v360=input=flat:ih_fov=106.8:iv_fov=103.56:h_fov=180:v_fov=180:w=2160:h=2160:yaw=-10:output=he[right3];\
   [left3][right3]vstack "\
   -c:v libx264 -crf 18 -c:a copy left_right.mp4

Et sammendrag av det ovennevnte for “small-native”-modusen er gitt her: small_native.pdf. Lav oppløsning (1920×1200) fangst.

Den bredeste synsfeltmodusen blir referert til som “large-native”. De ulike verdiene for transformasjonene er gitt her: large_native.pdf. Lav oppløsning (1920×1200) fangst.

Innstillingene for “large-pp”-modus er gitt her: large_pp.pdf. Legger merke til at i dette tilfellet ser det oppgitte vertikale synsfeltet ut til å være feil. Den korrekte verdien (gitt sideforhold for perspektivvisningen) som gir riktig aspekt for sceneobjekter er 115 grader i stedet for 94 grader. 4K (3840×2160) opptak.

Innstillingene for “normal-pp”-modus er gitt her: normal_pp.pdf. 4K (3840×2160) opptak.

Det siste trinnet vil være å legge til de riktige exif-dataene som indikerer oppsettet, man kan bruke exiftool for dette, men det er mange andre valg.