Closed komakai closed 3 years ago
@alalek Would it be possible to upgrade the cmake on the Mac test machines to version 3.16 ? Otherwise we get caught by this issue https://gitlab.kitware.com/cmake/cmake/issues/19699 (this would only be required for the Objective-C/Swift wrapper support - other builds could still work with the older cmake)
Installed CMake 3.17.1 on macosx-2
build worker.
Currently build fails on:
build-armv7-iphoneos/lib/Release/OpenCV.framework/Headers/ArrayUtil.h:9:1: error: unknown type name 'NSMutableArray'
Installed CMake 3.17.1 on macosx-2 build worker.
Thanks! All errors and warnings should be fixed now.
@alalek the build is OK now - currently it is failing on the packaging stage because I have changed the framework name from opencv2 to OpenCV. There are two reasons I wanted to make this change, firstly because the 2 on the end doesn't make a lot of sense (current version is actually 4 but I don't see any real reason to have the version in the framework name). Second reason is to copy the capitalization of other common Mac/iOS frameworks like OpenGL, OpenCL, OpenAL. If you are OK with the change please let me know how to proceed so that the packaging stage can pass. If not it's no problem to change the name back to the old name.
I just enabled full pipeline to avoid surprises on nightly validation. I'm OK with renaming in general, we just need to update infrastructure scripts (perhaps after infra shutdown during next week).
@vpisarev Please take a look on renaming process and high-level overview of this PR.
we just need to update infrastructure scripts (perhaps after infra shutdown during next week).
Great - could we also add new tasks to run the test scripts I've added? The command lines to run the tests are output at the end of the macOS and iOS build scripts
@alalek I have another PR ready with auto-generation of documentation here: https://github.com/komakai/opencv/tree/objc-binding-doc but since we're still waiting to update the build scripts maybe I can just merge it in here?
(For info the generated docs will look like this: http://xtravision.stars.ne.jp/opencv-objc-doc-test/docs/index.html )
@komakai, thank you for the contribution! And sorry for very long delay with the review. I've just started it, but hopefully, I can do it reasonably fast.
I have some first questions about your patch.
I see that the big part of your patch consists of manually written wrappers for some basic OpenCV data types, such as Point, Rect, Mat, etc. – overall it's more than 100 files in opencv/modules/core/misc/objc/common. I wonder whether it's possible to generate most of these wrappers on-fly as a custom build step and put somewhere to CMAKE_BUILD_DIR?
More general question about data structures. I see that Swift has tuple data type. In Python we just use tuple for points, rectangles and other such structures. Whether it makes sense to follow this approach with Swift?
Can you please put description somewhere (maybe here) on how to run the regression tests. I generated OpenCV.framework successfully and it seems to have objc bindings built-in. How do I use the run_tests.py script properly?
@vpisarev thanks for your questions!
I wonder whether it's possible to generate most of these wrappers on-fly as a custom build step
I mostly just copied the way the Java wrapper works - which also has a larger number of hand-coded classes. I have had a look at the hand-coded classes and found a few that aren't actually needed {Int,Float,Double}Out (I found a way to do handle out parameters without these special wrappers) and some others that are all very similar {Int,Float,Double}{n} which could be easily generated. I'll try and add a commit to reduce the number of manually coded classes in the next week or so.
I see that Swift has tuple data type.
Unfortunately we have to bridge to Swift via Objective-C which does not have tuple support. I plan at some point to generate Swift extensions to handle cases where there is a more natural Swift way of doing things - so I'll look at using tuples when I'm doing that.
How do I use the run_tests.py script properly?
If you get it to build successfully then you should see a line like this at the end of the build output:
To run tests call:
./opencv/platforms/osx/run_tests.py --framework_dir=/Users/gpayne/ContribNew/mactest25 /Users/gpayne/ContribNew/mactest25/build/build-x86_64-macosx/modules/objc/test
the --framework_dir parameter should point to the folder in which the built framework is located. The /Users/gpayne/ContribNew/mactest25/build/build-x86_64-macosx/modules/objc/test
refers to a folder that is created during the build that contains the actual tests themselves, a CMakeLists.txt
file for generating the Xcode test project and some dummy files needed to get the test project to build successfully.
Hope that helps - let me know if you have any more questions
@komakai, thank you! I ran the tests successfully. It looks like only core and imgproc are covered; which is fine for the first pull request, of course. I think, it would be nice to reduce this data types wrapper code, especially since you already working on it. Then the pull request can be merged, I think
@vpisarev Regarding manual basic data types please take a look on Java bindings. Example. Perhaps ObjC bindings are based on this approach. Number of basic data types is limited, so it should not be a real problem with scalability.
I see that Swift has tuple data type. In Python we just use tuple for points, rectangles and other such structures.
Current Python practice shows that "tuple everywhere" approach is very error prone without any reliable controls or checks. Also this approach requires heavy logic on bindings side.
@alalek, I think, I agree on the second item. Using specialized types is more safe. When you work with Python for a very long time, you start thinking in terms of tuples, but with languages like Swift, where structures are pretty efficient, it's better to use them.
On the first item. Well, of course, it's the implementation detail. I just thought that if we need to extend the types somehow, e.g. for some future versions of Swift, it could be more convenient to do it in the single place, in the script, rather than edit 100+ files manually. But you are right, it can wait.
So, let's make buildbot "all-green" and then it can be merged
@alalek thanks for your comments! I think there may still be some use for Swift tuples - but let's look at that later. @vpisarev thanks for approving! I have two more commits I want to push
@komakai Great Job!
Is it necessary to change framework name (opencv2 => OpenCV
)?
Usually it is used for automatic handling of include names (OpenCV uses includes in this form "opencv2/core.hpp"). So changing framework name would break already existed Users code (which we can't fix).
Apple guidelines: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Tasks/IncludingFrameworks.html
Related code in the patch:
import <OpenCV/OpenCV.h>
Migration on OpenCV.framework
can be done if @vpisarev approves this.
But probably we should do this "breaking change" for the next major release (OpenCV 5.0).
For current release series OpenCV 4.x I would suggest to keep previous behavior by default (and enable new one through flag - like inverse variant of legacy_build
).
opencv.hpp
is deprecated header.
It is better to include used modules directly (similar to C++ code without extra changes).
samples/swift/ios/FaceDetection/FaceDetection/lbpcascade_frontalface.xml
Do we need to make a copy of this file?
@komakai, I agree with @alalek, we should postpone renaming opencv2 => OpenCV till the next release, at least, otherwise it will break C++/Objective C++ apps that use the framework.
On the planned commits:
one will remove IntOut/FloatOut/DoubleOut classes yes, you are welcome to.
one to add wrappers for calib3d, dnn, ml, photo and video modules (to match the coverage of the Java wrapper) depending on how much time it will take. OpenCV 4.4 code freeze is around June 9th, and we will probably need 1-2 days to review the new changes.
@alalek @vpisarev Regarding postponing the name change 👍 @vpisarev the new out parameter handling and the extra wrappers are already merged @alalek the samples really need to be self contained - having a link to a file somewhere outside the sample directory would be really troublesome I think
Latest changes:
Still to do:
OpenCV 4.4 code freeze is around June 9th
OK - understood I will make the above changes in plenty of time for the 4.4 code freeze
OK - should be ready to go now.
Latest commits:
- changed the default framework name back to opencv2
- fixed iOS Swift samples
- fixed randomly failing test
- added converter functions to same level as the Java Converter util class
@alalek About including "opencv.hpp":
On Apple platforms, because of the Detected Apple 'NO' macro definition, it can cause conflicts
problem, it turns out you basically have to pull in all of OpenCV before you include any Apple headers. Including "opencv.hpp" is the best way to do this so I have left that part as is.
@komakai, I checked it on my machine – compiles fine and the tests ran successfully. I see, however, that the patch produces several warnings in iOS build. Could you please look at it?
Warning note:
warning: 'finalize' is deprecated CV_DEPRECATED_EXTERNAL
Please ensure that __OPENCV_BUILD=1
definition is passed to bindings compiler.
Latest changes:
__OPENCV_BUILD=1
to the build flags@vpisarev For the documentation generation can you install Jazzy on the build machine?
gem install jazzy
Reference: https://github.com/realm/jazzy
Then I'll make one more commit to fix the remaining warning and we should be good
@komakai, I've installed jazzy and successfully built the docs. It looks great, sometimes better than the "native" C++ documentation!
The only two complaints I have (or rather ideas for possible improvements in the future updates) are:
In any case, it's definitely good to go. Just, please, resolve the problems with iOS builder in order to squeeze this patch into OpenCV 4.4
@vpisarev I checked why the search feature wasn't working on Jazzy - turns out it is not currently supported for the default theme. I have created a PR against Jazzy that fixes this here: https://github.com/realm/jazzy/pull/1201 Unfortunately in Objective-C and Swift there is no real way to differentiate between Modules and Classes. What I can do is generate documentation comments at the top of each class of the form "This class belongs to the XXX module" and at the top of each module of the form "The XXX module is comprised of classes AAA, BBB, CCC, ...". That should make it easier to navigate between classes in the same module. (This would be a separate PR later) @alalek Looks like all builds are finally passing - hopefully we're good to go now
I updated the documentation at http://xtravision.stars.ne.jp/opencv-objc-doc-test/docs/index.html to show what it will look like with the search feature working
Observed on Mac Mini with OSX 10.14, Xcode 10.0.1.10010046 and CMake 3.15
@alalek can you test again with the latest commit on the above configuration? If it works then we can lower the required cmake version to 3.15
@komakai Changed iOS builder. This patch builds on mentioned configuration (please ignore BUILD_PRECOMMIT
change - it is not needed)
@alalek @vpisarev Awesome - thanks for your help in getting this merged. Now we just need to tell everyone about it and get them using it!
@komakai, thank you too for the excellent work! I think, it will be one of the major highlights of OpenCV 4.4 release! We will put it to the ChangeLog and the release announce
@komakai this looks like a legendary feature and like something I've been trying to find for over a year. I'm not sure if I missed it somewhere but are there docs on how to use this? I currently have a project using a bridging header between swift and objC but I am struggling to make expose data from objC to Swift (currently opencv vector data types). Will this by chance help with that?
@ianboru Since this is not in an official release yet you will need to make a build to get started like ./opencv/platforms/ios/build_framework.py my_build
then take the opencv2.framework from the output directory and copy to your project. There is some preview documentation here:
http://xtravision.stars.ne.jp/opencv-objc-doc-test/docs/index.html
Also you can take a look at the samples in samples/swift
to help you get started.
If you find there is something you want to do that the current Swift integration doesn't allow you to do, please create an issue and I'll see about adding support for it
I published an article here to explain what this contribution is about: https://medium.com/@gilespayne/opencv-4-4-lands-with-out-of-the-box-support-for-swift-and-objective-c-cdf3904066f1 @alalek @vpisarev any chance you could link to the article from the 4.4 release page?
@komakai Added link to ObjC entry here: https://github.com/opencv/opencv/wiki/ChangeLog#version440 Also you may want to add that link into the description of initial PR (17165).
@komakai @alalek who is responsible for the cocoapods ? https://cocoapods.org/pods/OpenCV https://cocoapods.org/pods/OpenCV2 Is there an official one? Would love to see 4.4.0 somewhere there. (and i dont want to create yet another opencv pod package).
@komakai Thank you for your great work! Now I'm enjoying swifty OpenCV programming!! (which was my long-cherished wish!)
By the way, do you have any plans to add data()
method which exposes cv::Mat::data
(https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#a4d33bed1c850265370d2af0ff02e1564) for ObjC/Swift APIs like below?
(Example pseudo code for additional data method in opencv/modules/core/misc/objc/common/Mat.mm)
- (NSData*)data {
return [NSData dataWithBytes: _nativePtr->data length: length-here];
}
Because of there is the convenience Mat<->UIImage conversion method like MatToUIImage
(https://github.com/opencv/opencv/blob/master/modules/imgcodecs/src/ios_conversions.mm) only for iOS build but not for OSX(macOS) build (for NSImage/CGImage), I'm struggling to get a data pointer when trying to convert Mat to CGImage or NSImage. (Conventional iOS MatToUIImage
uses cv::Mat::data in ObjectiveC++ context, but I want to get a data pointer also in swift API for creating CGImage from Mat.)
If you do not have plans to add the above feature in the near future, may I try to create a PR? (But I'm still wondering what is the right way to modify gen_objc.py
for adding NSData*.) I would be grateful if you could consider it.
@mtfrctl Please try the following: https://gist.github.com/komakai/c48fcd738b87e28a482ee34a8f9bdcc9
@mtfrctl Or you can use this trick to create an NSImage:
Imgcodecs.imwrite(filename: "/Users/gilespayne/Temp/temp.jpg", img: mat)
imageView.image = NSImage(contentsOfFile: "/Users/gilespayne/Temp/temp.jpg")
@kobetski Thank you for both ways you have suggested. Due to throughput issues, the former one is more suitable for my purposes than the latter one. I was able to confirm that the CGImage can be generated properly using the pointer obtained by your code! Thank you again.
@mtfrctl if you share your code for creating a CGImage from the raw Mat data then I will try to add Mat <-> NSImage extension functions
@komakai Thank you for your kindness! This time I tried to submit a PR here https://github.com/opencv/opencv/pull/18547. I would be grateful if you could check it. 🙇♂️
Is it possible to generate Swift binding for opencv_contrib modules?
@AlvarHHM please check out: https://github.com/opencv/opencv/pull/17882 https://github.com/opencv/opencv_contrib/pull/2609 (these PRs just missed the 4.4 release - should be in the 4.5 release)
Is there any easier method to access or set the element inside Mat? using put and get are very cumbersome.
Thank you
@AlvarHHM
When a Mat is printed in the console, why does it only show meta-data instead of printing out the Mat's data like in C++?
Maybe print(mat.dump())
does what you need
Is there any easier method to access or set the element inside Mat? using put and get are very cumbersome.
It would be possible to implement Swift subscript operators so you could do something like mat[row, col]
Not really sure what you are trying to do - but if you explore the OpenCV APIs a bit, very often you will find functions that allow you to do what you want, operating directly on a Mat
rather than pulling data out with a get
and putting back modified data with a set
Not really sure what you are trying to do - but if you explore the OpenCV APIs a bit, very often you will find functions that allow you to do what you want, operating directly on a
Mat
rather than pulling data out with aget
and putting back modified data with aset
In my case, I am trying to parse the result of some neural network. Of course, I can do it in c++ with mat.at<double>(i,j)
or with pointer, but it would be nice if the swift binding could match.
Of course, I can do it in c++ with mat.at
(i,j) or with pointer, but it would be nice if the swift binding could match.
I see - would something like this https://github.com/komakai/opencv/commit/f251aaf3d0227e6544bc0f1987016334ca822bcb do what you want?
Pull Request Readiness Checklist
This Pull Request solves #17164
This Pull-Request consists:
New build options: “legacy_build” - if specified will build the old opencv2 framework without the Objective-C/Swift wrapper as if this pull request never existed “framework_name” - defaults to OpenCV (to match the capitalization of other popular Apple frameworks like OpenGL,OpenAI etc) but can be set to an arbitrary value (for example opencv2 for backwards compatibility)
More details here regarding the motivation for this contribution: https://medium.com/@gilespayne/opencv-4-4-lands-with-out-of-the-box-support-for-swift-and-objective-c-cdf3904066f1
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request