View Full Version : "Defish" with different map projections
Kisa_AG
16th March 2015, 15:45
I made few functions which make defish with different map projections, like Lambert Cylindrical Equal Area, Mercator and Miller
projections.
These function are based on xyremap, thanks davidhorman for such a powerful filter!
Right now there are two different functions ready.
Both these functions available in ZIP archive attached.
Current version: 1.1
Here is the direct link: https://www.dropbox.com/s/il7g2lh39s3epyo/Defish_Different_Projections_v.1.1.zip?dl=0
#######################
CHANGE LIST:
16/03/2015 v1.0
- First release
17/03/2015 v1.1
- Core plugin (xyremap v0.2) changed to v0.3 due to great speed improvements (up to 40x).
#######################
It's Cylindrical_Equal_Area.avsi and Mercator_Projection.avsi.
The first one makes the following projections depending on the Standard Latitude settings:
0 degrees - Lambert cylindrical equal-area projection (this is my choise, the reason why I decided to make this function)
30 degrees - Behrmann cylindrical equal-area projection
37.383 degrees - Tristan Edwards projection
44.138 degrees - Peters projection
45 degrees - Gall orthographic projection
50 degrees - Balthasart projection
The second one makes Mercator and Miller projections depending on "Miller" settings.
There are special features which helps to find right zoom and crop values to get output picture without black areas around it.
#### Cylindrical_Equal_Area #######
Typical usage:
ConvertToRGB32(matrix="Rec709")
Cylindrical_Equal_Area(FocalLenght=3.5, zoom=0.97, VCropping=54)
ConvertToYV12(matrix="Rec709")
Usage instruction:
1. Input color format must be RGB32
2. Set the desired StandardLatitude_Fi_s (in degrees). For the first time it's better to leave it by default.
Default value is 0 degree, it's Lambert cylindrical equal-area projection.
3. Set FocalLenght and MatrixWidth (in mm). Then you can fine tune it visually, if you want.
Default FocalLenght is 2.77mm and MatrixWidth=6.28mm, these values are for GoPro 3BE.
4. Set zoom=0, open script in VirtualDub and move forward to find the number of frame,
which have no left and right black areas.
5. Set zoom=frame_number_founded/100.
6. Set VCropping=-1, open script in VirtualDub and move forward to find the frame,
which have no top and bottom black areas between cropping lines.
Read the correct cropping value in upper left corner of picture.
7. Set VCropping=cropping value founded.
###################################
#### Mercator_Projection #######
Typical usage:
ConvertToRGB32(matrix="Rec709")
Mercator_Projection(FocalLenght=3.5, zoom=0.97, VCropping=54, Miller=True)
ConvertToYV12(matrix="Rec709")
Usage instruction:
1. Input color format must be RGB32
2. Set the desired projection - Mercator or Miller.
3. Set FocalLenght and MatrixWidth (in mm). Then you can fine tune it visually, if you want.
Default FocalLenght is 2.77mm and MatrixWidth=6.28mm, these values are for GoPro 3BE.
4. Set zoom=0, open script in VirtualDub and move forward to find the number of frame,
which have no left and right black areas.
5. Set zoom=frame_number_founded/100.
6. Set VCropping=-1, open script in VirtualDub and move forward to find the frame,
which have no top and bottom black areas between cropping lines.
Read the correct cropping value in upper left corner of picture.
7. Set VCropping=cropping value founded.
###################################
More info on functions are in ReadMe files inside ZIP archive.
And here are six pictures which shows (I hope so) the advantage of Lambert cylindrical equal-area, Mercator and Miller
projections over the standard defishing.
PS: These Lambert cylindrical equal-area, Miller and Mercator projections are very suitable for defishing of 4:3 frames because
the output frame is very close to 16:9 apect rate and it's not necessary to crop big parts of picture.
PPS: Special thanks to Edgar from MathMap Google group!
His letter about different projections (https://groups.google.com/forum/#!topic/mathmap/9aL2CqC8eDA) saved me a huge
amount of time for formulation and debugging.
wonkey_monkey
16th March 2015, 23:00
You should try your functions with the new version (http://horman.net/avisynth/download/xyremap0.3.zip) of xyremap (new URL, the old version is still at the old URL), and add "static=true" to the parameter list when you call it. You should find it a lot quicker.
Kisa_AG
17th March 2015, 09:26
You should try your functions with the new version (http://horman.net/avisynth/download/xyremap0.3.zip) of xyremap (new URL, the old version is still at the old URL), and add "static=true" to the parameter list when you call it. You should find it a lot quicker.
Yes, it's much, MUCH faster!
Up to 40 times on my GoPro 3BE 2.7K @25p files! Incredebly!
Thnaks, davidhorman!
I've updated functions and changed links in the first post.
bigboss97
24th April 2015, 14:31
I'm attaching an image from my Ricoh Theta camera. Would you be able to give me some advice how I can apply the defish function?
There are 2 "eyes" :-) So I assume the image cannot be flatten as one. My aim is to simulate camera pan 360, i.e. there is always only one part of the image visible.
Thanks
wonkey_monkey
24th April 2015, 15:45
Attachment approval can take some time. You could try an external image host instead.
Kisa_AG
24th April 2015, 15:48
I'm attaching an image from my Ricoh Theta camera. Would you be able to give me some advice how I can apply the defish function?
There are 2 "eyes" :-) So I assume the image cannot be flatten as one. My aim is to simulate camera pan 360, i.e. there is always only one part of the image visible.
Thanks
Hello!
Sorry, I can take a look on it only on monday because I'm skiing in mountains right now.
bigboss97
26th April 2015, 01:46
Sorry, I can take a look on it only on monday because I'm skiing in mountains right now.
Thanks in advance. Have a good time!
Here are some camera information from that image:
F-Number: F2.1
Focal length [mm]: 0.75
35mm focal length [mm]: 6
bigboss97
6th May 2015, 05:12
Sorry, I can take a look on it only on monday because I'm skiing in mountains right now.
Any update?
Kisa_AG
6th May 2015, 08:31
Any update?
Sorry, I have no idea what can be done with it.
It seems to me that photos has been defished during panorama creation.
I would suggest you to take a look on Hugin - panorama creation tool, there are many different projections there for all kind of panorams.
bigboss97
7th May 2015, 02:10
Sorry, I have no idea what can be done with it.
It seems to me that photos has been defished during panorama creation.
I would suggest you to take a look on Hugin - panorama creation tool, there are many different projections there for all kind of panorams.
Thanks.
I'll play around with the defish plug-in first. I love avisynth :-) I've used it for so many different purposes. It's really powerful.
an3k
29th July 2020, 11:19
Please excuse my probably stupid question but can I use your script to "defish" into "Equirectangular" for eg. VR180 videos? What projection (degree) would I have to use? Thanks A LOT!
Hotte
16th March 2021, 19:55
I`d like to use these variants of different defish projections with AVS+. However I did not find a an x64 version of xyremap. Any ideas ?
wonkey_monkey
16th March 2021, 20:04
Give this a try. I changed its name to just Remap so you'll have to edit Kisa_AG's scripts accordingly.
http://horman.net/avisynth/download/Remap.zip
Hotte
16th March 2021, 22:14
Thanks a lot, David.
Unfortunately I am getting only a pure black clip with Miller=false and all parameters on their defaults.
I altered some of the parms but only black is being returned. Input is 4K-fisheye footage that used to work well. Don`t know whats wrong.
I had to remove the static parameter since it does not seem to be supported by remap.
wonkey_monkey
16th March 2021, 23:00
Ah, sorry about that. It's very much a work in progress - clearly only a subset of features are working as they should. You could try replacing any occurences of "PI" with "3.14159265359" and any occurences of "TAU" with "6.28318530718" but I haven't tried the scripts myself so there could be other problems.
Edit: actually the issue may be the use of capital W/H. Try replacing them with w/h.
Hotte
17th March 2021, 08:36
I replaced capital W/H and PI (no TAU) but same blackness. This is the core of the code from Mercator_Projection() where my changes applied. Complex - eh?
Don't want to force, just like this type of projection. My actual intention is a projection where defishing is only being done vertically ("banana doors") and less or not for horizontal lines ("pitfall tables"). I was not able to get this while playing with the parameters of the plugins around.
Since you seem to be a veteran of this matter I`d be happy to receive any other x64-suggestion for how to get there...
Right=remap(x="2 "+f+" * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * 2 ^ "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / sin 2 ^ + sqrt asin 2 / sin * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / sin "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * / atan cos * w 2 / +", y="2 "+f+" * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * 2 ^ "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / sin 2 ^ + sqrt asin 2 / sin * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / sin "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / cos x W 2 / - "+f+" / "+zoom+" / sin * / atan sin * h 2 / +")
Right=(VCropping==-1) ? \
ScriptClip(Right.crop(Width/2,0,0,-0),"drawlines(1,FrameCount,0,current_frame,Width-1,current_frame,lval=255).drawlines(0,FrameCount,Width-1,height-current_frame-1,0, height-current_frame-1, lval=255)") \
: Right.crop(Width/2,VCropping,0,-VCropping)
#Left half of picture
Left=remap(x="2 "+f+" * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * 2 ^ "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / sin 2 ^ + sqrt asin 2 / sin * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / sin "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * / atan 3.14159265359 + cos * w 2 / +", y="2 "+f+" * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * 2 ^ "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / sin 2 ^ + sqrt asin 2 / sin * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / sin "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / ^ 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / ^ * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * / atan 3.14159265359 + sin * h 2 / +")
wonkey_monkey
17th March 2021, 12:32
Since you seem to be a veteran of this matter
Well I did write xyremap/Remap... :D
Try replacing all occurences of " ^ " with " pow ".
Hotte
17th March 2021, 13:48
Ahhhh - there it is!
:thanks:
Do you think the static parameter could contribute to performance ? Any chance to get this done ?
Thank you so much!
wonkey_monkey
17th March 2021, 14:39
I've added static as a parameter. Same link:
http://horman.net/avisynth/download/Remap.zip
You should also get a speed increase (and slightly better quality) by using ConverttoYV24 instead of ConverttoRGB32.
Hotte
17th March 2021, 16:06
Thanks David. Now with YV24 and static reestablished I am getting decent performance.
X64-Remap in conjunction with Kisa_AG's script has brought the alternative projections back to stage.
Great work, thanks guys!
kedautinh12
17th March 2021, 16:12
I've added static as a parameter. Same link:
http://horman.net/avisynth/download/Remap.zip
You should also get a speed increase (and slightly better quality) by using ConverttoYV24 instead of ConverttoRGB32.
Can you add with ver x86??
StainlessS
17th March 2021, 16:17
Can you add with ver x86??
Hear Hear !.
Hotte
17th March 2021, 18:08
I just realized that Mercator_Projection() is running well in both Miller and Mercator mode however Cylindrical_Equal_Area() produces a result that exactly mirrors the bottom half of the picture onto the upper half - all geometrically correct though. Funny but unusable.
I havenīt had this with the x86 version. Could this be an issue in remap ?
wonkey_monkey
17th March 2021, 19:05
I think it's a difference in how asin is implemented, although I don't remember changing it. I don't have the old code to compare it to, though.
In the script string are a couple of instances of " asin sin ". As far as I can tell, these are redundant and can be removed and this should solve the problem. Maybe it was originally meant to solve a sign problem, or something.
You can also replace any instance of " 2 pow " with " ** " as an optimisation.
An x86 version may not be available any time soon. I migrated entirely to x64 some time ago and the calling conventions are different so it's not as simple as just compiling for a different target.
Hotte
17th March 2021, 19:47
YES! You hit the nail on the head. Even more performance increase in both scripts.
So for everybody interested I put it all together, ready to use.
The only thing I saw missing is x64-ScriptClip/DrawLines, but that is not needed if you donīt use variable zoom- or crop-finding modes.
Thanks again for your precious contribution!
x64-Compatible "Cylindrical_Equal_Area_v.1.1.avsi":
Download David's latest remap - see above.
############################## Cylindrical_Equal_Area v.1.1 x64-Version ##############################
function Cylindrical_Equal_Area(clip clp, float "zoom", float "FocalLenght", float "MatrixWidth", float "StandardLatitude_Fi_s", Int "VCropping")
{
############################################
# Cylindrical_Equal_Area function v.1.1 by Kisa_AG, (c)2015.
# ******************** X64 VERSION ***************************
# Made with the help of David Horman see https://forum.doom9.org/showthread.php?t=171922
# ************************************************************
# This function makes picture defishing with Cylindrical equal-area projection.
#
############################################
# Necessary plugins:
# 1. remap davidhorman. http://horman.net/avisynth/download/Remap.zip
# 2. ColorIt by V. C. Mohan. http://www.avisynth.nl/users/vcmohan/ColorIt/DrawLines.html
#
############################################
#
# Typical usage:
# ConvertToRGB32(matrix="Rec709")
# Cylindrical_Equal_Area(FocalLenght=3.5, zoom=0.97, VCropping=54)
# ConvertToYV12(matrix="Rec709")
#
########### Usage scenario:#################
# 1. Input color format must be RGB32
# 2. Set the desired StandardLatitude_Fi_s (in degrees). For the first time it's better to leave it by default.
# Default value is 0 degree, it's Lambert cylindrical equal-area projection.
# 3. Set FocalLenght and MatrixWidth (in mm). Then you can fine tune it visually, if you want.
# Default FocalLenght is 2.77mm and MatrixWidth=6.28mm, these values are for GoPro 3BE.
# 4. Set zoom=0, open script in VirtualDub and move forward to find the number of frame,
# which have no left and right black areas.
# 5. Set zoom=frame_number_founded/100.
# 6. Set VCropping=-1, open script in VirtualDub and move forward to find the frame,
# which have no top and bottom black areas between cropping lines.
# Read the correct cropping value in upper left corner of picture.
# 7. Set VCropping=cropping value founded.
#############################################
zoom = default(zoom, 0.94) # zoom Default
# A Zoom of 1 has no effect. Passing a Zoom of 0 returns an animated version
# where Zoom=current_frame/100 (so if frame 96 looks good, use Zoom=0.96).
VCropping = default(VCropping, 0) # Cropping Default
#############################################
#
# VCropping crops vertical size of picture to remove black areas. So it changes the aspect ratio of picture.
# A VCropping of 0 has no effect. Passing a VCropping of -1 returns an animated version
# where VCropping=current_frame+1 (so if frame 95 looks good, use VCropping=96).
# Cropping line width is 1 pixel, the cropped picture will be strictly between the upper and lower lines.
# Pixels "behind the line" are NOT included into final picture.
# For convinience the correct VCropping values for the final clip is shown in upper left corner of picture.
#
#############################################
FocalLenght = default(FocalLenght, 2.77) # FocalLenght Default - GoPro 3 BE
MatrixWidth = default(MatrixWidth, 6.28) # MatrixWidth Default - GoPro 3 BE
StandardLatitude_Fi_s = default(StandardLatitude_Fi_s, 0.0) # StandardLatitude_Fi_s Default - Lambert cylindrical equal-area projection
#############################################
#
# StandardLatitude_Fi_s means Standard Latitude for Special cases
# of cylindrical equal-area projections are summarized in the following table (Maling 1993):
#
# 0 degrees - Lambert cylindrical equal-area projection (this is my choise, the reason why I decided to make this function)
# 30 degrees - Behrmann cylindrical equal-area projection
# 37.383 degrees - Tristan Edwards projection
# 44.138 degrees - Peters projection
# 45 degrees - Gall orthographic projection
# 50 degrees - Balthasart projection
#
#############################################
static_sign=(zoom==0) ? false : true
Zoom=(Zoom==0) ? "n 0.01 *" : string(Zoom)
clp
f = width*FocalLenght/MatrixWidth
fs = String(StandardLatitude_Fi_s*3.14159265/180)
f = String(f)
#Right half of picture
Right=remap(x="2 "+f+" * "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / asin cos 1 "+fs+" cos / x w 2 / - * "+f+" "+zoom+" * / sin * ** "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / ** + sqrt asin 2 / sin * "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / asin cos 1 "+fs+" cos / x w 2 / - * "+f+" "+zoom+" * / sin * / atan cos * w 2 / +", y="2 "+f+" * "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / asin cos 1 "+fs+" cos / x w 2 / - * "+f+" "+zoom+" * / sin * ** "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / ** + sqrt asin 2 / sin * "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / asin cos 1 "+fs+" cos / x w 2 / - * "+f+" "+zoom+" * / sin * / atan sin * h 2 / +", static=static_sign)
Right=(VCropping==-1) ? \
ScriptClip(Right.crop(Width/2,0,0,-0),"drawlines(1,FrameCount,0,current_frame,Width-1,current_frame,lval=255).drawlines(0,FrameCount,Width-1,Height-current_frame-1,0, Height-current_frame-1, lval=255)") \
: Right.crop(Width/2,VCropping,0,-VCropping)
#Left half of picture
Left=remap(x="2 "+f+" * "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / asin cos 1 "+fs+" cos / x w 2 / - * "+f+" "+zoom+" * / sin * ** "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / ** + sqrt asin 2 / sin * "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / asin cos 1 "+fs+" cos / x w 2 / - * "+f+" "+zoom+" * / sin * / atan 3.14159265359 + cos * w 2 / +", y="2 "+f+" * "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / asin cos 1 "+fs+" cos / x w 2 / - * "+f+" "+zoom+" * / sin * ** "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / ** + sqrt asin 2 / sin * "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / "+fs+" cos y h 2 / - * "+f+" "+zoom+" * / asin cos 1 "+fs+" cos / x w 2 / - * "+f+" "+zoom+" * / sin * / atan 3.14159265359 + sin * h 2 / +", static=static_sign)
Left=(VCropping==-1) ? \
ScriptClip(Left.crop(0,0,-Width/2,-0), """drawlines(1,FrameCount,0,current_frame,Width-1,current_frame,lval=255).drawlines(0,FrameCount,Width-1,Height-current_frame-1,0, Height-current_frame-1, lval=255).Subtitle("Crop="+String(current_frame+1))""") \
: Left.crop(0,VCropping,-Width/2,-VCropping)
stackhorizontal(Left,Right)
}
######################################################################################################
And this is the revised "Mercator_Projection_v.1.1.avsi":
############################## Mercator_Projection v.1.1 x64-Version ##############################
function Mercator_Projection(clip clp, float "zoom", float "FocalLenght", float "MatrixWidth", bool "Miller", Int "VCropping")
{
############################################
# Mercator_Projection v.1.1 by Kisa_AG, (c)2015.
# ******************** X64 VERSION ***************************
# Made with the help of David Horman see https://forum.doom9.org/showthread.php?t=171922
# ************************************************************
# This function makes picture defishing with Mercator or Miller Projection (when bool "Miller"=True).
#
############################################
# Necessary plugins:
# 1. remap davidhorman. http://horman.net/avisynth/download/Remap.zip
# 2. ColorIt by V. C. Mohan. http://www.avisynth.nl/users/vcmohan/ColorIt/DrawLines.html
#
############################################
#
# Typical usage:
# ConvertToRGB32(matrix="Rec709")
# Mercator_Projection(FocalLenght=3.5, zoom=0.97, VCropping=54, Miller=True)
# ConvertToYV12(matrix="Rec709")
#
########### Usage scenario:#################
# 1. Input color format must be RGB32
# 2. Set the desired projection - Mercator or Miller.
# 3. Set FocalLenght and MatrixWidth (in mm). Then you can fine tune it visually, if you want.
# Default FocalLenght is 2.77mm and MatrixWidth=6.28mm, this values are for GoPro 3BE.
# 4. Set zoom=0, open script in VirtualDub and move forward to find the number of frame,
# which have no left and right black areas.
# 5. Set zoom=frame_number_founded/100.
# 6. Set VCropping=-1, open script in VirtualDub and move forward to find the frame,
# which have no top and bottom black areas between cropping lines.
# Read the correct cropping value in upper left corner of picture.
# 7. Set VCropping=cropping value founded.
#############################################
zoom = default(zoom, 0.94) # zoom Default
# A Zoom of 1 has no effect. Passing a Zoom of 0 returns an animated version
# where Zoom=current_frame/100 (so if frame 96 looks good, use Zoom=0.96).
VCropping = default(VCropping, 0) # Cropping Default
#############################################
#
# VCropping crops vertical size of picture to remove black areas. So it changes the aspect ratio of picture.
# A VCropping of 0 has no effect. Passing a VCropping of -1 returns an animated version
# where VCropping=current_frame+1 (so if frame 95 looks good, use VCropping=96).
# Cropping line width is 1 pixel, the cropped picture will be strictly between the upper and lower lines.
# Pixels "behind the line" are NOT included into final picture.
# For convinience the correct VCropping values for the final clip is shown in upper left corner of picture.
#
#############################################
FocalLenght = default(FocalLenght, 2.77) # FocalLenght Default - GoPro 3 BE
MatrixWidth = default(MatrixWidth, 6.28) # MatrixWidth Default - GoPro 3 BE
Miller = default(Miller, "False") # Miller Default False - use Mercator projection
#############################################
#
# The Miller Cylindrical projection is derived from the Mercator projection;
# parallels are spaced from the Equator by calculating the distance on the Mercator for a parallel
# at 80% of the true latitude and dividing the result by 0.8.
# The result is that the two projections are almost identical near the Equator.
# http://www.mathworks.com/help/map/millercylindricalprojection.html
#
#############################################
static_sign=(zoom==0) ? false : true
Zoom=(Zoom==0) ? "n 0.01 *" : string(Zoom)
clp
f = width*FocalLenght/MatrixWidth
exp=String(2.71828182846)
f = String(f)
MK=(Miller==True) ? String(0.8) : String(1)
# Miller coeficient: if it's 1 then it's Mercator projection, if it's 0.8 then it's Miller Projection
#Right half of picture
Right=remap(x="2 "+f+" * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * ** "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / sin ** + sqrt asin 2 / sin * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / sin "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * / atan cos * w 2 / +", y="2 "+f+" * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * ** "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / sin ** + sqrt asin 2 / sin * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / sin "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * / atan sin * h 2 / +", static=static_sign)
Right=(VCropping==-1) ? \
ScriptClip(Right.crop(Width/2,0,0,-0),"drawlines(1,FrameCount,0,current_frame,Width-1,current_frame,lval=255).drawlines(0,FrameCount,Width-1,height-current_frame-1,0, height-current_frame-1, lval=255)") \
: Right.crop(Width/2,VCropping,0,-VCropping)
#Left half of picture
Left=remap(x="2 "+f+" * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * ** "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / sin ** + sqrt asin 2 / sin * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / sin "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * / atan 3.14159265359 + cos * w 2 / +", y="2 "+f+" * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * ** "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / sin ** + sqrt asin 2 / sin * "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / sin "+exp+" 2 "+MK+" * y h 2 / - * "+f+" "+zoom+" * / pow 1 - 2 "+exp+" "+MK+" y h 2 / - * "+f+" "+zoom+" * / pow * / atan "+MK+" / cos x w 2 / - "+f+" / "+zoom+" / sin * / atan 3.14159265359 + sin * h 2 / +", static=static_sign)
Left=(VCropping==-1) ? \
ScriptClip(Left.crop(0,0,-Width/2,-0), """drawlines(1,FrameCount,0,current_frame,Width-1,current_frame,lval=255).drawlines(0,FrameCount,Width-1,height-current_frame-1,0, height-current_frame-1, lval=255).Subtitle("Crop="+String(current_frame+1))""") \
: Left.crop(0,VCropping,-Width/2,-VCropping)
stackhorizontal(Left,Right)
}
######################################################################################################
wonkey_monkey
17th March 2021, 20:20
You can precompute frequently used values by calculating and storing them with code in the frame*, row, and pixel strings. Quick example:
*frame is not relevant for these projection mappings because nothing changes on a per frame basis.
Example:
Remap(\
x = "x y 10 / + x sin +",\
y = "y x sin +"\
)
"y 10 /" can be calculated once per row and stored in the variable Y:
Remap(\
row = "y 10 / @Y^",\
x = "x Y + x sin +",\
y = "y x sin +"\
)
while "x sin", being used in both x and y strings, can be calculated once per pixel instead of twice.
Remap(\
row = "y 10 / @Y^",\
pixel = "x sin @S^",\
x = "x Y + S +",\
y = "y S +"\
)
I haven't tested these but they should work.
I can see other ways to optimise this which I'll outline shortly.
wonkey_monkey
17th March 2021, 22:10
Here's an optimised Mercator projection in one expression without requiring two halves - this should increase loading speed and be at least double fps:
Whole = remap(\
clip = "
1 "+f+" "+zoom+" * / @Z^
",\
row = "
"+MK+" y h 2 / - * Z * @M^
"+exp+" 2 M * pow 1 - 2 "+exp+" M pow * / atan "+MK+" / sincos @F^ @G^
",\
pixel = "
2 "+f+" * F x w 2 / - Z * sin * ** G ** + sqrt asin 2 / sin * @A^
G F x w 2 / - Z * sin * / atan sincos @C^ @S^
",\
x="A C x w 2 / < ?: neg . * w 2 / +",\
y="A S x w 2 / < ?: neg . * h 2 / +",\
static=static_sign\
)
Notes:
The clip string is evaluated once. It's used here to generate a zoom constant but this could equally have been done in the Avisynth script
sincos calculates both the sine and cosine of the value on the top of the stack and puts them both on the stack (the cosine will be on top)
"x w 2 / < ?: neg ." means "If x < w/2 then("?:") make the top value negative (. = endif). This replaces the "pi +" bit that differentiates the Left and Right clips - intead of rotating the angle by 180 degrees before taking sine or cosine, it negates the result after taking the sine/cosine.
wonkey_monkey
17th March 2021, 23:11
Optimised Cylindrical Equal Area:
Whole = remap(\
clip = "
1 "+f+" "+zoom+" * / @Z
1 "+fs+" cos @T / @I
* @R^
",\
row = "
T y h 2 / - * Z * @F asin cos @A^
",\
pixel = "
F A x w 2 / - R * sin * @Q / atan sincos @C^ @S^
2 "+f+" * Q ** F ** + sqrt asin 2 / sin * @B^
",\
x = "B C x w 2 / < ?: neg . * w 2 / +",\
y = "B S x w 2 / < ?: neg . * h 2 / +",\
static=static_sign\
)
Hotte
25th March 2021, 09:30
Sorry, I have been offline for a couple of days and I wanted to make sure that I have tested your new approach before commenting.
Excellent!
Being not experienced with development It had some small difficulties with the integration of the code. I have now implemented Mercator (and Miller) and compared results against KISAs code. You will find the full code below.
Results are pretty similar, but - and that is a big advantage of the new code: Input format = output format with the new code. The old script's produced a video that was some 10% wider than input which had to be cropped afterwards. This is not case with the new code.
Performance is also better, I would say some 20% faster or so but I did not go into details. I was using a geometrically perfectly aligned short 4K clip of a large shelf filmed with a Samyang 7.5 mft fisheye on a Panasonic G9. The surrounding code of course could have falsified the performance impression. EDIT:Did some retesting on performance: The old script is a tad faster (some 5%) than the new one, nothing to worry about.
The VCropping parameter does not seem to work anymore or have I overseen sth ? I found it quite useful, but I can achieve the same with some Resizing/Cropping.
What I have not quite understood ist the meaning of FocalLenght vs. MatrixWidth. I found that certain combinations of both lead to the ever same results but to no new perspective. I mean one compensates the other somehow, so there would be no need for two parameters. Is that true ?
So thank you very much. I will be using this.
This is my full testing code for Mercator/Miller. I have not yet tested CEA but will do at a later stage. For sure this code could be cleaned up and brought into a final version.
############################## Mercator_Projection v.1.1 ##############################
function Mercator_Projection2(clip clp, float "zoom", float "FocalLenght", float "MatrixWidth", bool "Miller", Int "VCropping")
{
############################################
# Mercator_Projection v.1.1 by Kisa_AG, (c)2015.
# ******************** X64 VERSION ***************************
# Made with the help of David Horman see https://forum.doom9.org/showthread.php?t=171922
# ************************************************************
# This function makes picture defishing with Mercator or Miller Projection (when bool "Miller"=True).
#
############################################
# Necessary plugins:
# 1. remap davidhorman. http://horman.net/avisynth/download/Remap.zip
# 2. ColorIt by V. C. Mohan. http://www.avisynth.nl/users/vcmohan/ColorIt/DrawLines.html
#
############################################
#
# Typical usage:
# ConvertToRGB32(matrix="Rec709")
# Mercator_Projection(FocalLenght=3.5, zoom=0.97, VCropping=54, Miller=True)
# ConvertToYV12(matrix="Rec709")
#
########### Usage scenario:#################
# 1. Input color format must be RGB32
# 2. Set the desired projection - Mercator or Miller.
# 3. Set FocalLenght and MatrixWidth (in mm). Then you can fine tune it visually, if you want.
# Default FocalLenght is 2.77mm and MatrixWidth=6.28mm, this values are for GoPro 3BE.
# 4. Set zoom=0, open script in VirtualDub and move forward to find the number of frame,
# which have no left and right black areas.
# 5. Set zoom=frame_number_founded/100.
# 6. Set VCropping=-1, open script in VirtualDub and move forward to find the frame,
# which have no top and bottom black areas between cropping lines.
# Read the correct cropping value in upper left corner of picture.
# 7. Set VCropping=cropping value founded.
#############################################
zoom = default(zoom, 0.94) # zoom Default
# A Zoom of 1 has no effect. Passing a Zoom of 0 returns an animated version
# where Zoom=current_frame/100 (so if frame 96 looks good, use Zoom=0.96).
VCropping = default(VCropping, 0) # Cropping Default
#############################################
#
# VCropping crops vertical size of picture to remove black areas. So it changes the aspect ratio of picture.
# A VCropping of 0 has no effect. Passing a VCropping of -1 returns an animated version
# where VCropping=current_frame+1 (so if frame 95 looks good, use VCropping=96).
# Cropping line width is 1 pixel, the cropped picture will be strictly between the upper and lower lines.
# Pixels "behind the line" are NOT included into final picture.
# For convinience the correct VCropping values for the final clip is shown in upper left corner of picture.
#
#############################################
FocalLenght = default(FocalLenght, 2.77) # FocalLenght Default - GoPro 3 BE
MatrixWidth = default(MatrixWidth, 6.28) # MatrixWidth Default - GoPro 3 BE
Miller = default(Miller, "False") # Miller Default False - use Mercator projection
#############################################
#
# The Miller Cylindrical projection is derived from the Mercator projection;
# parallels are spaced from the Equator by calculating the distance on the Mercator for a parallel
# at 80% of the true latitude and dividing the result by 0.8.
# The result is that the two projections are almost identical near the Equator.
# http://www.mathworks.com/help/map/millercylindricalprojection.html
#
#############################################
static_sign=(zoom==0) ? false : true
Zoom=(Zoom==0) ? "n 0.01 *" : string(Zoom)
clp
f = width*FocalLenght/MatrixWidth
exp=String(2.71828182846)
f = String(f)
MK=(Miller==True) ? String(0.8) : String(1)
# Miller coeficient: if it's 1 then it's Mercator projection, if it's 0.8 then it's Miller Projection
remap(\
clip = "
1 "+f+" "+zoom+" * / @Z^
",\
row = "
"+MK+" y h 2 / - * Z * @M^
"+exp+" 2 M * pow 1 - 2 "+exp+" M pow * / atan "+MK+" / sincos @F^ @G^
",\
pixel = "
2 "+f+" * F x w 2 / - Z * sin * ** G ** + sqrt asin 2 / sin * @A^
G F x w 2 / - Z * sin * / atan sincos @C^ @S^
",\
x="A C x w 2 / < ?: neg . * w 2 / +",\
y="A S x w 2 / < ?: neg . * h 2 / +",\
static=static_sign\
)
}
######################################################################################################
Hotte
25th March 2021, 18:35
Just also tried out Cylindrical Equal Area (CEA) and ended up with an Error "RPN compile failed: Stack underflow near ... line 99" which is the 2nd last line with the bracket.
Probably a simple transcription error caused by myself. But still I am not able to cope with it. So it would be most kind if you could have a look into it:
############################## Cylindrical_Equal_Area v.1.1 ##############################
function Cylindrical_Equal_Area(clip clp, float "zoom", float "FocalLenght", float "MatrixWidth", float "StandardLatitude_Fi_s", Int "VCropping")
{
############################################
# Cylindrical_Equal_Area function v.1.1 by Kisa_AG, (c)2015.
# ******************** X64 VERSION ***************************
# Made with the help of David Horman see https://forum.doom9.org/showthread.php?t=171922
# ************************************************************
# This function makes picture defishing with Cylindrical equal-area projection.
#
############################################
# Necessary plugins:
# 1. remap davidhorman. http://horman.net/avisynth/download/Remap.zip
# 2. ColorIt by V. C. Mohan. http://www.avisynth.nl/users/vcmohan/ColorIt/DrawLines.html
#
############################################
#
# Typical usage:
# ConvertToRGB32(matrix="Rec709")
# Cylindrical_Equal_Area(FocalLenght=3.5, zoom=0.97, VCropping=54)
# ConvertToYV12(matrix="Rec709")
#
########### Usage scenario:#################
# 1. Input color format must be RGB32
# 2. Set the desired StandardLatitude_Fi_s (in degrees). For the first time it's better to leave it by default.
# Default value is 0 degree, it's Lambert cylindrical equal-area projection.
# 3. Set FocalLenght and MatrixWidth (in mm). Then you can fine tune it visually, if you want.
# Default FocalLenght is 2.77mm and MatrixWidth=6.28mm, these values are for GoPro 3BE.
# 4. Set zoom=0, open script in VirtualDub and move forward to find the number of frame,
# which have no left and right black areas.
# 5. Set zoom=frame_number_founded/100.
# 6. Set VCropping=-1, open script in VirtualDub and move forward to find the frame,
# which have no top and bottom black areas between cropping lines.
# Read the correct cropping value in upper left corner of picture.
# 7. Set VCropping=cropping value founded.
#############################################
zoom = default(zoom, 0.94) # zoom Default
# A Zoom of 1 has no effect. Passing a Zoom of 0 returns an animated version
# where Zoom=current_frame/100 (so if frame 96 looks good, use Zoom=0.96).
VCropping = default(VCropping, 0) # Cropping Default
#############################################
#
# VCropping crops vertical size of picture to remove black areas. So it changes the aspect ratio of picture.
# A VCropping of 0 has no effect. Passing a VCropping of -1 returns an animated version
# where VCropping=current_frame+1 (so if frame 95 looks good, use VCropping=96).
# Cropping line width is 1 pixel, the cropped picture will be strictly between the upper and lower lines.
# Pixels "behind the line" are NOT included into final picture.
# For convinience the correct VCropping values for the final clip is shown in upper left corner of picture.
#
#############################################
FocalLenght = default(FocalLenght, 2.77) # FocalLenght Default - GoPro 3 BE
MatrixWidth = default(MatrixWidth, 6.28) # MatrixWidth Default - GoPro 3 BE
StandardLatitude_Fi_s = default(StandardLatitude_Fi_s, 0.0) # StandardLatitude_Fi_s Default - Lambert cylindrical equal-area projection
#############################################
#
# StandardLatitude_Fi_s means Standard Latitude for Special cases
# of cylindrical equal-area projections are summarized in the following table (Maling 1993):
#
# 0 degrees - Lambert cylindrical equal-area projection (this is my choise, the reason why I decided to make this function)
# 30 degrees - Behrmann cylindrical equal-area projection
# 37.383 degrees - Tristan Edwards projection
# 44.138 degrees - Peters projection
# 45 degrees - Gall orthographic projection
# 50 degrees - Balthasart projection
#
#############################################
static_sign=(zoom==0) ? false : true
Zoom=(Zoom==0) ? "n 0.01 *" : string(Zoom)
clp
f = width*FocalLenght/MatrixWidth
fs = String(StandardLatitude_Fi_s*3.14159265/180)
f = String(f)
remap(\
clip = "
1 "+f+" "+zoom+" * / @Z
1 "+fs+" cos @T / @I
* @R^
",\
row = "
T y h 2 / - * Z * @F asin cos @A^
",\
pixel = "
F A x w 2 / - R * sin * @Q^ / atan sincos @C^ @S^
2 "+f+" * Q ** F ** + sqrt asin 2 / sin * @B^
",\
x = "B C x w 2 / < ?: neg . * w 2 / +",\
y = "B S x w 2 / < ?: neg . * h 2 / +",\
static=static_sign\
)
}
wonkey_monkey
25th March 2021, 20:29
My fault, I edited in an untested optimsation. Change:
@Q^
to
@Q
PS FocalLenght is misspelled
Hotte
25th March 2021, 21:57
Works! Thank you so much!!!
Hotte
29th April 2021, 08:18
David, just a quick question,
This script does not complain about HBD-Input nor YUV444. I remember an RGB restriction and also 8-bit. Wer were also talking about YV24.
Also I am frequently using the defish plugin in an x64 version.
Which of these are able to deal with what ?
Thanks.
wonkey_monkey
29th April 2021, 19:42
Defish is restricted to RGB32. Remap's only restriction (if I remember correctly) is that it can't handle undersampled chroma (YV411, YV420, YV422).
Hotte
30th April 2021, 08:15
Defish is restricted to RGB32.
Thanks David. To have that ported to HBD would be heart's desire. As far as I know there is no HBD fisherman working in the avs+ ocean. Still the script above might soothe the pain a bit....
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.