-
Notifications
You must be signed in to change notification settings - Fork 84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Now reading videos using subprocesses and ffmpeg. #702
Conversation
To test it locally, make sure Also, would be great if you could just sign the CLA for now - currently we have that to protect us from anything regarding issues with copyright in the future. |
|
||
infos = {'duration': duration, 'width': width, 'height': height, 'n_frames': n_frames, 'fps': fps} | ||
|
||
return infos |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
channels_to_back is now roll_channels and menpo images have a as_roll_channels method to replace the now deprecated as_imageio.
Also, add special environment variables for ffmpeg and ffprobe so that the user can update them. Finally, add mpg and mpeg to list of supported formats.
Remove roll_channels as I don't think it's necessary and it's name is confusing when compared to as_rolled_channels.
Makes denormalising easier.
Remove imageio completely from setup.py and conda/meta.yaml and improve the ffmpeg logic a bit. Since we are no longer using imageio this also meant fixing some tests. Also, try and make sure that our pipe handling is more robust.
Use FFMPEG by default
Conflicts: menpo/io/input/video.py menpo/io/test/io_import_test.py
…porter Conflicts: menpo/io/input/video.py menpo/io/test/io_import_test.py
Merge commit from Greg's normalize keyword change
@jabooth - @JeanKossaifi think this is ready now - can you please check it? Also, would be great if you actually loaded some videos. @grigorisg9gr it would also be great if you could check it with some of your videos? |
A dictionary of extensions supported by the FFMPEG importer. | ||
""" | ||
# Need to check this | ||
ffmpeg_exts = ['.avi', '.mp4', '.mpg', '.mpeg', '.wmv', '.mov'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would definitely extend that to include more. E.g. mkv is quite common.
You can find the supported ones with ffmpeg -formats.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can add mkv
, but my major concern is that many of the formats listed by ffmpeg -formats
only work if ffmpeg has been compiled with all of it's extensions - not everything is supported out the box. So, there's a part of me that only wants to support those formats that are very familiar and only add other formats as requested and confirmed that they actually work with our shipped ffmpeg.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
That is also the reason why I didn't add list them in the first place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JeanKossaifi can you add mkv
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@patricksnape @grigorisg9gr Done.
I tested it in a couple of videos. It works ok I believe. Nice work @JeanKossaifi and @patricksnape . Even in some videos of bigger duration it works without consuming much ram, however it might require some time. |
@JeanKossaifi L744/45 in |
@jabooth Please review :) |
MenpoDeprecationWarning) | ||
return self.as_rolled_channels() | ||
|
||
def as_rolled_channels(self, out_dtype=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
completely support deprecating as_imageio
but not sure as_rolled_channels()
is the right name here, and if we are deprecating, might be worth a little discussion on getting it right.
For my money, that name to me doesn't suggest I'm going to get a numpy array back, so I'd assume an Image
is the return type. That then makes me think that maybe menpo images support channels either rolled or not, which is not the case.
My other preference would be to move from channels_rolled
generally to channels_at_front
or channels_at_back
respectfully. Rolling is the procedure to change from one to another, but it isn't clear to the callee what the input and output should be.
Those two thoughts lead me to suggest a name more like .pixels_with_channels_at_back()
or even .pixels_array_with_channels_at_back()
. That's obviously super verbose though, can we try and find something shorter than that that still conveys:
- You are getting back a numpy array only
- The channels on the array are at the back so you can use this array with code that expects that convention
- Re-enfoces that menpo images must therefore always have channels not at the back, but the front.
Thoughts @patricksnape ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, to be fair, I've struggled with the naming convention of this the entire time. There is no standard term for where the channels lie and so everything might seem confusing to someone. Rolling is obviously what you actually do to move the axis. 'back' and 'front' are more obvious, but might be confusing to someone with regards to the 'back/front' of what? 'First' and 'last' axis are more explicit but lend themselves to longer names. It's tough, discoverability is important but super verbose method names for fairly common functions are also undesirable.
.pixels_array_with_channels_at_back()
is definitely too long. I don't think we need to specify array
as we already have the convention that pixels
gives access to the underlying numpy array. So I would vote for .pixels_with_channels_at_back()
.
I can see why the as_
syntax might suggest returning a Menpo object given the definition of similar methods. However, obviously this needs to be a method as it involves a copy. We also need to fix the init_from_rolled_channels
to have consistent naming e.g. init_from_channels_at_back()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally agree with your opening paragraph.
.pixels_array_with_channels_at_back() is definitely too long. I don't think we need to specify array as we already have the convention that pixels gives access to the underlying numpy array.
Yup, had a similar thought with the .pixels
convention already existing
So I would vote for .pixels_with_channels_at_back().
Agreed. Also has the nice benefit that it will appear when tab completing .pixels
, aiding discoverability.
However, obviously this needs to be a method as it involves a copy.
Agreed.
We also need to fix the init_from_rolled_channels to have consistent naming e.g. init_from_channels_at_back().
Yup, agreed. This feels like an overall better solution to a really tricky naming issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about simply rolled_channels_ndarray?
On 6 June 2016 at 13:24, James Booth notifications@github.com wrote:
In menpo/image/base.py
#702 (comment):@@ -2525,17 +2530,38 @@ def pixels_range(self):
def rolled_channels(self): r"""
Deprecated - please use the equivalent `as_rolled_channels` method.
"""
warn('This method is no longer supported and will be removed in a '
'future version of Menpo. '
'Use .as_rolled_channels() instead.',
MenpoDeprecationWarning)
return self.as_rolled_channels()
- def as_rolled_channels(self, out_dtype=None):
Totally agree with your opening paragraph.
.pixels_array_with_channels_at_back() is definitely too long. I don't
think we need to specify array as we already have the convention that
pixels gives access to the underlying numpy array.Yup, had a similar thought with the .pixels convention already existing
So I would vote for .pixels_with_channels_at_back().
Agreed. Also has the nice benefit that it will appear when tab completing
.pixels, aiding discoverability.However, obviously this needs to be a method as it involves a copy.
Agreed.
We also need to fix the init_from_rolled_channels to have consistent
naming e.g. init_from_channels_at_back().Yup, agreed. This feels like an overall better solution to a really tricky
naming issue.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/menpo/menpo/pull/702/files/56bf939db7eb788371c54563876feaaf90bc5a3f#r65880732,
or mute the thread
https://github.com/notifications/unsubscribe/AAy0R5GQgndD5V2PoPxjfutQ2RHyHGhdks5qJBFpgaJpZM4Ine8W
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the discoverability provided with the pixels name to be honest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name .pixels_with_channels_at_back()
seems overly verbose.
What about, instead, making a generic getter function with a default parameter encouraging the behaviour you want (channels at the front), e.g. .pixels_to_array(channels_at_end=False)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JeanKossaifi problem with that getter is that
.pixels_to_array(channels_at_end=False)
is just going to hand you the pixels array which is
.pixels
It's an important convention in menpo that our objects are minimal wrappers with obvious access to the underlying numpy array, so .pixels
is and will remain the supported way of getting hold of the pixel array.
.pixels_with_channels_at_back()
is inline with existing Menpo naming conventions. It might be considered long for a Python method name, but we tend to follow the Apple school of thought on this issue:
It is good to be both clear and brief as possible, but clarity shouldn’t suffer because of brevity
People using Menpo will undoubtedly tab-complete names - why make it harder to discover what a method does in the name of optimising for source code size/typing names without assistance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see your point and if that is the consensus I'll change it to .pixels_with_channels_at_back
.
However, if the point of the object is just to have a thin wrapper around a ndarray representing an image, a .to_array(channels_at_back=False)
would be as coherent.
image.to_array()
has the expected behaviour and image.to_array(channels_at_back=True)
is very clear. The advantage being the possible addition of other optional parameters such as normalise etc. Also, in practice, relying solely on users tab-completing is not very robust and can result in an overly long list. Again, just a suggestion.
In any case, I updated the PR to include the other comments so unless there are other comments, the it should be good to merge once that naming issue is solved :)
for stream in (process.stdout, process.stdin, process.stderr): | ||
if stream: | ||
stream.close() | ||
process.wait() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very nice 👍
@jabooth @patricksnape should be ready to merge:
|
@@ -125,7 +125,7 @@ def init_blank(cls, shape, n_channels=1, fill=0, dtype=np.float, mask=None): | |||
return cls(pixels, copy=False, mask=mask) | |||
|
|||
@classmethod | |||
def init_from_rolled_channels(cls, pixels, mask=None): | |||
def init_from_channels_at_back(cls, pixels, mask=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JeanKossaifi Can we deprecate this rather than just replacing it? So re-add it and deprecate it in the same manner as rolled_channels
above (but obviously referencing init_from_channels_at_back
). The tests are correct though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already what I did, at least from what I see, I think the gittiff is just confusing in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad! Let me check the code out and check 😆
Edit: Confirmed - apologies!
@jabooth Once this finished I am good to go on this. @JeanKossaifi thanks for your hard work! |
@patricksnape looks good to me, thanks so much @JeanKossaifi! +1 once passed. |
Thanks for the comments @jabooth and @patricksnape. Not sure what happened with appveyor here, it does not seem to be a problem in the code? One last thing: currently I made the FFMpegVideoReader return Menpo Image. Or alternatively add an optional parameter convert_to_menpo set to True by default? This is transparent to the end user (if they use the menpo video_importer they would not have to worry about it) and it would allow advanced users to instantiate directly a FFMpegVideoReader to get channels_at_the_back images directly rather than do the conversion twice :) |
I restarted Appveyor - it was a capacity failure on the Anaconda server. I would prefer, if you really want to do that, that you let your class return the numpy arrays and then you do the conversion at the level of the
Note that I haven't actually tried that logic, but I think it illustrates my point. That way you can always instantiate your own |
The FFMpegVideoReader simply returns numpy arrays, the importer initialises the Menpo Image with init_from_channels_at_back.
Done. Completely transparent for the user (does not change a thing for importing videos) and they would have to dig to find out as you mentioned :) |
Now just the long wait for Appveyor and then LGTM. |
No description provided.