Comments (6)
I could do a pull request but since I have multiple versions with different behaviors I think that this is more about figuring out which one is best. I should probably do a proper fork so that other can try it.
from flowblade.
Thanks, agreed that adding av.sense property is useful. With 'sense=destination' it really only works as user would expect with the crop filter added, so I made the previous 'sense=source' default as that looks more 'non-buggy'. The workaround of using crop filter prior to adding is such vital piece of information that I'll add it to docs somehow.
I pushed the change in into master.
from flowblade.
You are fast to close :-) so not sure that you will read that.
I was thinking that it could be a good idea to create a new filter instead of adding a sense argument. The old filter one with sense=source could be renamed to "Perspective correct" while the new one with sense=destination could be "Perspective Add".
Also, there are no practical reasons to limit the point to the screen dimension especially when using sense=destination.
And finally, using screen coordinates is not necessarily the best approach. During my experiment, I found that using relative coordinates to each corner makes a lot of sense and using positive directions toward the center is even better.
I made multiple versions with different input and output ranges. The 5th is the one I like the best. It is relative to the corner so setting all points to (0,0) will reset the transformation.
<!-- for some reason avfilter.perspective gives errors:
[filter avfilter.perspective] Unexpected return format
[filter avfilter.perspective] Cannot get frame from buffer sink
if initialized with SCREENSIZE_WIDTH and SCREENSIZE_HEIGHT.
However, if set to these values later it works.
Workaround is that we initialize it with hard coded values
-->
<filter id="avfilter.perspective">
<name>Perspective</name>
<group>Distort</group>
<property name="av.sense" args="editor=combobox exptype=default cbopts=Source:0,Destination:1 displayname=Sense">0</property>
<property name="av.interpolation" args="editor=combobox exptype=default cbopts=Linear:linear,Cubic:cubic displayname=Interpolation">linear</property>
<property name="av.x0" args="range_in=0,SCREENSIZE_WIDTH range_out=0,SCREENSIZE_WIDTH displayname=x0">10</property>
<property name="av.y0" args="range_in=0,SCREENSIZE_HEIGHT range_out=0,SCREENSIZE_HEIGHT displayname=y0">10</property>
<property name="av.x1" args="range_in=0,SCREENSIZE_WIDTH range_out=0,SCREENSIZE_WIDTH displayname=x1">500</property>
<property name="av.y1" args="range_in=0,SCREENSIZE_HEIGHT range_out=0,SCREENSIZE_HEIGHT displayname=y1">0</property>
<property name="av.x2" args="range_in=0,SCREENSIZE_WIDTH range_out=0,SCREENSIZE_WIDTH displayname=x2">0</property>
<property name="av.y2" args="range_in=0,SCREENSIZE_HEIGHT range_out=0,SCREENSIZE_HEIGHT displayname=y2">400</property>
<property name="av.x3" args="range_in=0,SCREENSIZE_WIDTH range_out=0,SCREENSIZE_WIDTH displayname=x3">550</property>
<property name="av.y3" args="range_in=0,SCREENSIZE_HEIGHT range_out=0,SCREENSIZE_HEIGHT displayname=y3">420</property>
</filter>
<!-- Perspective 2 :
- the default sense is 'Destination'
- the input screen size is normalized 1000x1000
- all inputs ranges are 'extended'by 1000 in all directions thus alowing
the 4 points to be located outside the screen
- consequently, the default values (without any visible perspective)
should be
x0=0
y0=0
x1=1000
y1=0
x2=0
y2=1000
x3=1000
y3=1000
-->
<filter id="avfilter.perspective">
<name>Perspective 2</name>
<group>Distort</group>
<property name="av.sense" args="editor=combobox exptype=default cbopts=Source:0,Destination:1 displayname=Sense">1</property>
<property name="av.interpolation" args="editor=combobox exptype=default cbopts=Linear:linear,Cubic:cubic displayname=Interpolation">linear</property>
<property name="av.x0" args="range_in=-1000,2000 range_out=SCREEN33_XMIN,SCREEN33_XMAX displayname=x0">0</property>
<property name="av.y0" args="range_in=-1000,2000 range_out=SCREEN33_YMIN,SCREEN33_YMAX displayname=y0">0</property>
<property name="av.x1" args="range_in=-1000,2000 range_out=SCREEN33_XMIN,SCREEN33_XMAX displayname=x1">500</property>
<property name="av.y1" args="range_in=-1000,2000 range_out=SCREEN33_YMIN,SCREEN33_YMAX displayname=y1">0</property>
<property name="av.x2" args="range_in=-1000,2000 range_out=SCREEN33_XMIN,SCREEN33_XMAX displayname=x2">0</property>
<property name="av.y2" args="range_in=-1000,2000 range_out=SCREEN33_YMIN,SCREEN33_YMAX displayname=y2">300</property>
<property name="av.x3" args="range_in=-1000,2000 range_out=SCREEN33_XMIN,SCREEN33_XMAX displayname=x3">500</property>
<property name="av.y3" args="range_in=-1000,2000 range_out=SCREEN33_YMIN,SCREEN33_YMAX displayname=y3">300</property>
</filter>
<!-- Perspective 3 is similar to Perspective 2 with the following changes:
- the input and output ranges are defined such that the 'default' location of each point corresponds to input (0,0)
- the x,y coordinates of each point are now relative to the corresponding corner point.
- the displayname are changed to dx0, dy0, ... to reflect that.
- the input ranges are all sets to -1000,1000 so the 'default' 0 is nicely centered.
- in practice, that means that the 4 points cannot cross the two opposite sides of the screen.
-->
<filter id="avfilter.perspective">
<name>Perspective 3</name>
<group>Distort</group>
<property name="av.sense" args="editor=combobox exptype=default cbopts=Source:0,Destination:1 displayname=Sense">1</property>
<property name="av.interpolation" args="editor=combobox exptype=default cbopts=Linear:linear,Cubic:cubic displayname=Interpolation">linear</property>
<property name="av.x0" args="range_in=-1000,1000 range_out=SCREEN33_XMIN,SCREENSIZE_WIDTH displayname=dx0">10</property>
<property name="av.y0" args="range_in=-1000,1000 range_out=SCREEN33_YMIN,SCREENSIZE_HEIGHT displayname=dy0">10</property>
<property name="av.x1" args="range_in=-1000,1000 range_out=0,SCREEN33_XMAX displayname=dx1">500</property>
<property name="av.y1" args="range_in=-1000,1000 range_out=SCREEN33_YMIN,SCREENSIZE_HEIGHT displayname=dy1">0</property>
<property name="av.x2" args="range_in=-1000,1000 range_out=SCREEN33_XMIN,SCREENSIZE_WIDTH displayname=dx2">20</property>
<property name="av.y2" args="range_in=-1000,1000 range_out=0,SCREEN33_YMAX displayname=dy2">350</property>
<property name="av.x3" args="range_in=-1000,1000 range_out=0,SCREEN33_XMAX displayname=dx3">400</property>
<property name="av.y3" args="range_in=-1000,1000 range_out=0,SCREEN33_YMAX displayname=dy3">400</property>
</filter>
<!-- Perspective 4 is similar to Perspective 3 with the following changes:
- the input ranges are now using screen coordinates but are still relative to the 4 corner points.
- so setting a point to (0,0) moves it to it corner
-->
<filter id="avfilter.perspective">
<name>Perspective 4</name>
<group>Distort</group>
<property name="av.sense" args="editor=combobox exptype=default cbopts=Source:0,Destination:1 displayname=Sense">1</property>
<property name="av.interpolation" args="editor=combobox exptype=default cbopts=Linear:linear,Cubic:cubic displayname=Interpolation">linear</property>
<property name="av.x0" args="range_in=SCREEN33_XMIN,SCREENSIZE_WIDTH range_out=SCREEN33_XMIN,SCREENSIZE_WIDTH displayname=dx0">0</property>
<property name="av.y0" args="range_in=SCREEN33_YMIN,SCREENSIZE_HEIGHT range_out=SCREEN33_YMIN,SCREENSIZE_HEIGHT displayname=dy0">0</property>
<property name="av.x1" args="range_in=SCREEN33_XMIN,SCREENSIZE_WIDTH range_out=0,SCREEN33_XMAX displayname=dx1">500</property>
<property name="av.y1" args="range_in=SCREEN33_YMIN,SCREENSIZE_HEIGHT range_out=SCREEN33_YMIN,SCREENSIZE_HEIGHT displayname=dy1">0</property>
<property name="av.x2" args="range_in=SCREEN33_XMIN,SCREENSIZE_WIDTH range_out=SCREEN33_XMIN,SCREENSIZE_WIDTH displayname=dx2">0</property>
<property name="av.y2" args="range_in=SCREEN33_YMIN,SCREENSIZE_HEIGHT range_out=0,SCREEN33_YMAX displayname=dy2">350</property>
<property name="av.x3" args="range_in=SCREEN33_XMIN,SCREENSIZE_WIDTH range_out=0,SCREEN33_XMAX displayname=dx3">400</property>
<property name="av.y3" args="range_in=SCREEN33_YMIN,SCREENSIZE_HEIGHT range_out=0,SCREEN33_YMAX displayname=dy3">400</property>
</filter>
<!-- Perspective 5 is similar to Perspective 4 with the following changes:
- The coordinates are still given relative to each corner but with the positive direction toward the center.
- The valid range is extended so that all points can be moved anywere in the 'SCREEN33' area.
-->
<filter id="avfilter.perspective">
<name>Perspective 5</name>
<group>Distort</group>
<property name="av.sense" args="editor=combobox exptype=default cbopts=Source:0,Destination:1 displayname=Sense">1</property>
<property name="av.interpolation" args="editor=combobox exptype=default cbopts=Linear:linear,Cubic:cubic displayname=Interpolation">linear</property>
<property name="av.x0" args="range_in=SCREEN33_XMIN,SCREEN33_XMAX range_out=SCREEN33_XMIN,SCREEN33_XMAX displayname=dx0">0</property>
<property name="av.y0" args="range_in=SCREEN33_YMIN,SCREEN33_YMAX range_out=SCREEN33_YMIN,SCREEN33_YMAX displayname=dy0">0</property>
<property name="av.x1" args="range_in=SCREEN33_XMIN,SCREEN33_XMAX range_out=SCREEN33_XMAX,SCREEN33_XMIN displayname=dx1">500</property>
<property name="av.y1" args="range_in=SCREEN33_YMIN,SCREEN33_YMAX range_out=SCREEN33_YMIN,SCREEN33_YMAX displayname=dy1">0</property>
<property name="av.x2" args="range_in=SCREEN33_XMIN,SCREEN33_XMAX range_out=SCREEN33_XMIN,SCREEN33_XMAX displayname=dx2">0</property>
<property name="av.y2" args="range_in=SCREEN33_YMIN,SCREEN33_YMAX range_out=SCREEN33_YMAX,SCREEN33_YMIN displayname=dy2">350</property>
<property name="av.x3" args="range_in=SCREEN33_XMIN,SCREEN33_XMAX range_out=SCREEN33_XMAX,SCREEN33_XMIN displayname=dx3">400</property>
<property name="av.y3" args="range_in=SCREEN33_YMIN,SCREEN33_YMAX range_out=SCREEN33_YMAX,SCREEN33_YMIN displayname=dy3">400</property>
</filter>
The values SCREEN33_XMIN ... SCREEN33_XMAX are defined a follow in propertyparse.py
def get_args_num_value(val_str):
"""
Returns numerical value for expression in property
args.
"""
try: # attempt int
return int(val_str)
except:
try:# attempt float
return float(val_str)
except:
w = current_sequence().profile.width()
h = current_sequence().profile.height()
# attempt expression
if val_str == SCREENSIZE_WIDTH:
return w
elif val_str == SCREENSIZE_HEIGHT:
return h
# SCREEN33 is a virtual 3x3 screen centered around the image.
# Used for control points outside the visible image in Perspective
elif val_str == "SCREEN33_XMIN":
return -w
elif val_str == "SCREEN33_XMAX":
return 2*w
elif val_str == "SCREEN33_YMIN":
return -h
elif val_str == "SCREEN33_YMAX":
return 2*h
return None
from flowblade.
Ok, I'll reopen. Maybe do pull request, so I'll get all proposed changes in together. I think I can copy-paste from here, but pull request leaves you as the author in git log, and this helps me remember to give attribution when writing release notes and adding you as contributor.
Also, there are no practical reasons to limit the point to the screen dimension especially when using sense=destination.
# SCREEN33 is a virtual 3x3 screen centered around the image.
Ok, I get it. I did a similar trick for cairoaffineblend when I contributed it to frei0r as frei0r requires all params to be in range 0.0-1.0. User being able to place image corners outside of screen area is indeed useful new functionality, so if perspective 5 + propertyparse.py change does that let's put that in. If you prefer I do it, I can do it.
from flowblade.
And of course, there is still the problem of setting a proper default value for the 4 points. If I understand correctly, the issue is mostly because symbols such as SCREENSIZE_WIDTH
and SCREENSIZE_HEIGHT
are not properly interpreted in the value field (only in xml attributes). I can look into it.
from flowblade.
Ok, I'll wait for more input on setting proper default values for the 4 corner points.
from flowblade.
Related Issues (20)
- re: Better Clip Colours HOT 3
- Black preview screen (Arch Linux, flowblade 2.12) HOT 13
- Add Time Remapping feature HOT 5
- Add keyboard and mouse wheel accelerators when editing numerical values HOT 8
- Broken reset in Position Scale HOT 6
- Flathub? what? HOT 3
- How to low preview quality? HOT 1
- Crashes on startup after new install HOT 1
- Better Error Handling? HOT 1
- "Large set of user configurable" [what] in README HOT 2
- Problems with Paths - Possibly Corrupted Project after Upgrade HOT 4
- Ctrl + Z removes entire filter instead of rolling back latest change HOT 4
- Downloadable resources for Fluxity plugins HOT 4
- color adjustment & saturation filters inop HOT 8
- Possible missing python-libusb1 dependency HOT 1
- Black screen on the monitor
- Improve HDPI support HOT 5
- "Motion Tracking Create" not working HOT 2
- Feature Request: Add webp Support to Flowblade HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flowblade.