ningwebbeginner

i'ni'tea

要显示太多修改。

为保证性能只显示 29 of 29+ 个文件。

  1 +.idea
  2 +DS_Store
  3 +examples/build
  4 +cmake-build-debug
  1 +cmake_minimum_required(VERSION 3.17)
  2 +project(RobustVideoMatting.lite.ai.toolkit)
  3 +
  4 +set(CMAKE_CXX_STANDARD 11)
  5 +
  6 +# setting up lite.ai.toolkit
  7 +set(LITE_AI_DIR ${CMAKE_SOURCE_DIR}/lite.ai.toolkit)
  8 +set(LITE_AI_INCLUDE_DIR ${LITE_AI_DIR}/include)
  9 +set(LITE_AI_LIBRARY_DIR ${LITE_AI_DIR}/lib)
  10 +include_directories(${LITE_AI_INCLUDE_DIR})
  11 +link_directories(${LITE_AI_LIBRARY_DIR})
  12 +
  13 +#set(OpenCV_LIBS
  14 + # opencv_highgui
  15 + # opencv_core
  16 + # opencv_imgcodecs
  17 + # opencv_imgproc
  18 + # opencv_video
  19 + # opencv_videoio
  20 + # )
  21 +set(OpenCV_LIBS
  22 + opencv_world4110d
  23 + opencv_world4110
  24 + )
  25 +# add your executable
  26 +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/examples/build)
  27 +
  28 +file(GLOB ALL_LIBS ${LITE_AI_LIBRARY_DIR}/*dll)
  29 +file(INSTALL ${ALL_LIBS} DESTINATION ${EXECUTABLE_OUTPUT_PATH})
  30 +
  31 +add_executable(lite_rvm examples/test_lite_rvm.cpp)
  32 +target_link_libraries(lite_rvm
  33 + lite.ai.toolkit
  34 + onnxruntime
  35 + # MNN # need, if built lite.ai.toolkit with ENABLE_MNN=ON, default OFF
  36 + # ncnn # need, if built lite.ai.toolkit with ENABLE_NCNN=ON, default OFF
  37 + # TNN # need, if built lite.ai.toolkit with ENABLE_TNN=ON, default OFF
  38 + ${OpenCV_LIBS}) # link lite.ai.toolkit & other libs.
  1 + GNU GENERAL PUBLIC LICENSE
  2 + Version 3, 29 June 2007
  3 +
  4 + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
  5 + Everyone is permitted to copy and distribute verbatim copies
  6 + of this license document, but changing it is not allowed.
  7 +
  8 + Preamble
  9 +
  10 + The GNU General Public License is a free, copyleft license for
  11 +software and other kinds of works.
  12 +
  13 + The licenses for most software and other practical works are designed
  14 +to take away your freedom to share and change the works. By contrast,
  15 +the GNU General Public License is intended to guarantee your freedom to
  16 +share and change all versions of a program--to make sure it remains free
  17 +software for all its users. We, the Free Software Foundation, use the
  18 +GNU General Public License for most of our software; it applies also to
  19 +any other work released this way by its authors. You can apply it to
  20 +your programs, too.
  21 +
  22 + When we speak of free software, we are referring to freedom, not
  23 +price. Our General Public Licenses are designed to make sure that you
  24 +have the freedom to distribute copies of free software (and charge for
  25 +them if you wish), that you receive source code or can get it if you
  26 +want it, that you can change the software or use pieces of it in new
  27 +free programs, and that you know you can do these things.
  28 +
  29 + To protect your rights, we need to prevent others from denying you
  30 +these rights or asking you to surrender the rights. Therefore, you have
  31 +certain responsibilities if you distribute copies of the software, or if
  32 +you modify it: responsibilities to respect the freedom of others.
  33 +
  34 + For example, if you distribute copies of such a program, whether
  35 +gratis or for a fee, you must pass on to the recipients the same
  36 +freedoms that you received. You must make sure that they, too, receive
  37 +or can get the source code. And you must show them these terms so they
  38 +know their rights.
  39 +
  40 + Developers that use the GNU GPL protect your rights with two steps:
  41 +(1) assert copyright on the software, and (2) offer you this License
  42 +giving you legal permission to copy, distribute and/or modify it.
  43 +
  44 + For the developers' and authors' protection, the GPL clearly explains
  45 +that there is no warranty for this free software. For both users' and
  46 +authors' sake, the GPL requires that modified versions be marked as
  47 +changed, so that their problems will not be attributed erroneously to
  48 +authors of previous versions.
  49 +
  50 + Some devices are designed to deny users access to install or run
  51 +modified versions of the software inside them, although the manufacturer
  52 +can do so. This is fundamentally incompatible with the aim of
  53 +protecting users' freedom to change the software. The systematic
  54 +pattern of such abuse occurs in the area of products for individuals to
  55 +use, which is precisely where it is most unacceptable. Therefore, we
  56 +have designed this version of the GPL to prohibit the practice for those
  57 +products. If such problems arise substantially in other domains, we
  58 +stand ready to extend this provision to those domains in future versions
  59 +of the GPL, as needed to protect the freedom of users.
  60 +
  61 + Finally, every program is threatened constantly by software patents.
  62 +States should not allow patents to restrict development and use of
  63 +software on general-purpose computers, but in those that do, we wish to
  64 +avoid the special danger that patents applied to a free program could
  65 +make it effectively proprietary. To prevent this, the GPL assures that
  66 +patents cannot be used to render the program non-free.
  67 +
  68 + The precise terms and conditions for copying, distribution and
  69 +modification follow.
  70 +
  71 + TERMS AND CONDITIONS
  72 +
  73 + 0. Definitions.
  74 +
  75 + "This License" refers to version 3 of the GNU General Public License.
  76 +
  77 + "Copyright" also means copyright-like laws that apply to other kinds of
  78 +works, such as semiconductor masks.
  79 +
  80 + "The Program" refers to any copyrightable work licensed under this
  81 +License. Each licensee is addressed as "you". "Licensees" and
  82 +"recipients" may be individuals or organizations.
  83 +
  84 + To "modify" a work means to copy from or adapt all or part of the work
  85 +in a fashion requiring copyright permission, other than the making of an
  86 +exact copy. The resulting work is called a "modified version" of the
  87 +earlier work or a work "based on" the earlier work.
  88 +
  89 + A "covered work" means either the unmodified Program or a work based
  90 +on the Program.
  91 +
  92 + To "propagate" a work means to do anything with it that, without
  93 +permission, would make you directly or secondarily liable for
  94 +infringement under applicable copyright law, except executing it on a
  95 +computer or modifying a private copy. Propagation includes copying,
  96 +distribution (with or without modification), making available to the
  97 +public, and in some countries other activities as well.
  98 +
  99 + To "convey" a work means any kind of propagation that enables other
  100 +parties to make or receive copies. Mere interaction with a user through
  101 +a computer network, with no transfer of a copy, is not conveying.
  102 +
  103 + An interactive user interface displays "Appropriate Legal Notices"
  104 +to the extent that it includes a convenient and prominently visible
  105 +feature that (1) displays an appropriate copyright notice, and (2)
  106 +tells the user that there is no warranty for the work (except to the
  107 +extent that warranties are provided), that licensees may convey the
  108 +work under this License, and how to view a copy of this License. If
  109 +the interface presents a list of user commands or options, such as a
  110 +menu, a prominent item in the list meets this criterion.
  111 +
  112 + 1. Source Code.
  113 +
  114 + The "source code" for a work means the preferred form of the work
  115 +for making modifications to it. "Object code" means any non-source
  116 +form of a work.
  117 +
  118 + A "Standard Interface" means an interface that either is an official
  119 +standard defined by a recognized standards body, or, in the case of
  120 +interfaces specified for a particular programming language, one that
  121 +is widely used among developers working in that language.
  122 +
  123 + The "System Libraries" of an executable work include anything, other
  124 +than the work as a whole, that (a) is included in the normal form of
  125 +packaging a Major Component, but which is not part of that Major
  126 +Component, and (b) serves only to enable use of the work with that
  127 +Major Component, or to implement a Standard Interface for which an
  128 +implementation is available to the public in source code form. A
  129 +"Major Component", in this context, means a major essential component
  130 +(kernel, window system, and so on) of the specific operating system
  131 +(if any) on which the executable work runs, or a compiler used to
  132 +produce the work, or an object code interpreter used to run it.
  133 +
  134 + The "Corresponding Source" for a work in object code form means all
  135 +the source code needed to generate, install, and (for an executable
  136 +work) run the object code and to modify the work, including scripts to
  137 +control those activities. However, it does not include the work's
  138 +System Libraries, or general-purpose tools or generally available free
  139 +programs which are used unmodified in performing those activities but
  140 +which are not part of the work. For example, Corresponding Source
  141 +includes interface definition files associated with source files for
  142 +the work, and the source code for shared libraries and dynamically
  143 +linked subprograms that the work is specifically designed to require,
  144 +such as by intimate data communication or control flow between those
  145 +subprograms and other parts of the work.
  146 +
  147 + The Corresponding Source need not include anything that users
  148 +can regenerate automatically from other parts of the Corresponding
  149 +Source.
  150 +
  151 + The Corresponding Source for a work in source code form is that
  152 +same work.
  153 +
  154 + 2. Basic Permissions.
  155 +
  156 + All rights granted under this License are granted for the term of
  157 +copyright on the Program, and are irrevocable provided the stated
  158 +conditions are met. This License explicitly affirms your unlimited
  159 +permission to run the unmodified Program. The output from running a
  160 +covered work is covered by this License only if the output, given its
  161 +content, constitutes a covered work. This License acknowledges your
  162 +rights of fair use or other equivalent, as provided by copyright law.
  163 +
  164 + You may make, run and propagate covered works that you do not
  165 +convey, without conditions so long as your license otherwise remains
  166 +in force. You may convey covered works to others for the sole purpose
  167 +of having them make modifications exclusively for you, or provide you
  168 +with facilities for running those works, provided that you comply with
  169 +the terms of this License in conveying all material for which you do
  170 +not control copyright. Those thus making or running the covered works
  171 +for you must do so exclusively on your behalf, under your direction
  172 +and control, on terms that prohibit them from making any copies of
  173 +your copyrighted material outside their relationship with you.
  174 +
  175 + Conveying under any other circumstances is permitted solely under
  176 +the conditions stated below. Sublicensing is not allowed; section 10
  177 +makes it unnecessary.
  178 +
  179 + 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
  180 +
  181 + No covered work shall be deemed part of an effective technological
  182 +measure under any applicable law fulfilling obligations under article
  183 +11 of the WIPO copyright treaty adopted on 20 December 1996, or
  184 +similar laws prohibiting or restricting circumvention of such
  185 +measures.
  186 +
  187 + When you convey a covered work, you waive any legal power to forbid
  188 +circumvention of technological measures to the extent such circumvention
  189 +is effected by exercising rights under this License with respect to
  190 +the covered work, and you disclaim any intention to limit operation or
  191 +modification of the work as a means of enforcing, against the work's
  192 +users, your or third parties' legal rights to forbid circumvention of
  193 +technological measures.
  194 +
  195 + 4. Conveying Verbatim Copies.
  196 +
  197 + You may convey verbatim copies of the Program's source code as you
  198 +receive it, in any medium, provided that you conspicuously and
  199 +appropriately publish on each copy an appropriate copyright notice;
  200 +keep intact all notices stating that this License and any
  201 +non-permissive terms added in accord with section 7 apply to the code;
  202 +keep intact all notices of the absence of any warranty; and give all
  203 +recipients a copy of this License along with the Program.
  204 +
  205 + You may charge any price or no price for each copy that you convey,
  206 +and you may offer support or warranty protection for a fee.
  207 +
  208 + 5. Conveying Modified Source Versions.
  209 +
  210 + You may convey a work based on the Program, or the modifications to
  211 +produce it from the Program, in the form of source code under the
  212 +terms of section 4, provided that you also meet all of these conditions:
  213 +
  214 + a) The work must carry prominent notices stating that you modified
  215 + it, and giving a relevant date.
  216 +
  217 + b) The work must carry prominent notices stating that it is
  218 + released under this License and any conditions added under section
  219 + 7. This requirement modifies the requirement in section 4 to
  220 + "keep intact all notices".
  221 +
  222 + c) You must license the entire work, as a whole, under this
  223 + License to anyone who comes into possession of a copy. This
  224 + License will therefore apply, along with any applicable section 7
  225 + additional terms, to the whole of the work, and all its parts,
  226 + regardless of how they are packaged. This License gives no
  227 + permission to license the work in any other way, but it does not
  228 + invalidate such permission if you have separately received it.
  229 +
  230 + d) If the work has interactive user interfaces, each must display
  231 + Appropriate Legal Notices; however, if the Program has interactive
  232 + interfaces that do not display Appropriate Legal Notices, your
  233 + work need not make them do so.
  234 +
  235 + A compilation of a covered work with other separate and independent
  236 +works, which are not by their nature extensions of the covered work,
  237 +and which are not combined with it such as to form a larger program,
  238 +in or on a volume of a storage or distribution medium, is called an
  239 +"aggregate" if the compilation and its resulting copyright are not
  240 +used to limit the access or legal rights of the compilation's users
  241 +beyond what the individual works permit. Inclusion of a covered work
  242 +in an aggregate does not cause this License to apply to the other
  243 +parts of the aggregate.
  244 +
  245 + 6. Conveying Non-Source Forms.
  246 +
  247 + You may convey a covered work in object code form under the terms
  248 +of sections 4 and 5, provided that you also convey the
  249 +machine-readable Corresponding Source under the terms of this License,
  250 +in one of these ways:
  251 +
  252 + a) Convey the object code in, or embodied in, a physical product
  253 + (including a physical distribution medium), accompanied by the
  254 + Corresponding Source fixed on a durable physical medium
  255 + customarily used for software interchange.
  256 +
  257 + b) Convey the object code in, or embodied in, a physical product
  258 + (including a physical distribution medium), accompanied by a
  259 + written offer, valid for at least three years and valid for as
  260 + long as you offer spare parts or customer support for that product
  261 + model, to give anyone who possesses the object code either (1) a
  262 + copy of the Corresponding Source for all the software in the
  263 + product that is covered by this License, on a durable physical
  264 + medium customarily used for software interchange, for a price no
  265 + more than your reasonable cost of physically performing this
  266 + conveying of source, or (2) access to copy the
  267 + Corresponding Source from a network server at no charge.
  268 +
  269 + c) Convey individual copies of the object code with a copy of the
  270 + written offer to provide the Corresponding Source. This
  271 + alternative is allowed only occasionally and noncommercially, and
  272 + only if you received the object code with such an offer, in accord
  273 + with subsection 6b.
  274 +
  275 + d) Convey the object code by offering access from a designated
  276 + place (gratis or for a charge), and offer equivalent access to the
  277 + Corresponding Source in the same way through the same place at no
  278 + further charge. You need not require recipients to copy the
  279 + Corresponding Source along with the object code. If the place to
  280 + copy the object code is a network server, the Corresponding Source
  281 + may be on a different server (operated by you or a third party)
  282 + that supports equivalent copying facilities, provided you maintain
  283 + clear directions next to the object code saying where to find the
  284 + Corresponding Source. Regardless of what server hosts the
  285 + Corresponding Source, you remain obligated to ensure that it is
  286 + available for as long as needed to satisfy these requirements.
  287 +
  288 + e) Convey the object code using peer-to-peer transmission, provided
  289 + you inform other peers where the object code and Corresponding
  290 + Source of the work are being offered to the general public at no
  291 + charge under subsection 6d.
  292 +
  293 + A separable portion of the object code, whose source code is excluded
  294 +from the Corresponding Source as a System Library, need not be
  295 +included in conveying the object code work.
  296 +
  297 + A "User Product" is either (1) a "consumer product", which means any
  298 +tangible personal property which is normally used for personal, family,
  299 +or household purposes, or (2) anything designed or sold for incorporation
  300 +into a dwelling. In determining whether a product is a consumer product,
  301 +doubtful cases shall be resolved in favor of coverage. For a particular
  302 +product received by a particular user, "normally used" refers to a
  303 +typical or common use of that class of product, regardless of the status
  304 +of the particular user or of the way in which the particular user
  305 +actually uses, or expects or is expected to use, the product. A product
  306 +is a consumer product regardless of whether the product has substantial
  307 +commercial, industrial or non-consumer uses, unless such uses represent
  308 +the only significant mode of use of the product.
  309 +
  310 + "Installation Information" for a User Product means any methods,
  311 +procedures, authorization keys, or other information required to install
  312 +and execute modified versions of a covered work in that User Product from
  313 +a modified version of its Corresponding Source. The information must
  314 +suffice to ensure that the continued functioning of the modified object
  315 +code is in no case prevented or interfered with solely because
  316 +modification has been made.
  317 +
  318 + If you convey an object code work under this section in, or with, or
  319 +specifically for use in, a User Product, and the conveying occurs as
  320 +part of a transaction in which the right of possession and use of the
  321 +User Product is transferred to the recipient in perpetuity or for a
  322 +fixed term (regardless of how the transaction is characterized), the
  323 +Corresponding Source conveyed under this section must be accompanied
  324 +by the Installation Information. But this requirement does not apply
  325 +if neither you nor any third party retains the ability to install
  326 +modified object code on the User Product (for example, the work has
  327 +been installed in ROM).
  328 +
  329 + The requirement to provide Installation Information does not include a
  330 +requirement to continue to provide support service, warranty, or updates
  331 +for a work that has been modified or installed by the recipient, or for
  332 +the User Product in which it has been modified or installed. Access to a
  333 +network may be denied when the modification itself materially and
  334 +adversely affects the operation of the network or violates the rules and
  335 +protocols for communication across the network.
  336 +
  337 + Corresponding Source conveyed, and Installation Information provided,
  338 +in accord with this section must be in a format that is publicly
  339 +documented (and with an implementation available to the public in
  340 +source code form), and must require no special password or key for
  341 +unpacking, reading or copying.
  342 +
  343 + 7. Additional Terms.
  344 +
  345 + "Additional permissions" are terms that supplement the terms of this
  346 +License by making exceptions from one or more of its conditions.
  347 +Additional permissions that are applicable to the entire Program shall
  348 +be treated as though they were included in this License, to the extent
  349 +that they are valid under applicable law. If additional permissions
  350 +apply only to part of the Program, that part may be used separately
  351 +under those permissions, but the entire Program remains governed by
  352 +this License without regard to the additional permissions.
  353 +
  354 + When you convey a copy of a covered work, you may at your option
  355 +remove any additional permissions from that copy, or from any part of
  356 +it. (Additional permissions may be written to require their own
  357 +removal in certain cases when you modify the work.) You may place
  358 +additional permissions on material, added by you to a covered work,
  359 +for which you have or can give appropriate copyright permission.
  360 +
  361 + Notwithstanding any other provision of this License, for material you
  362 +add to a covered work, you may (if authorized by the copyright holders of
  363 +that material) supplement the terms of this License with terms:
  364 +
  365 + a) Disclaiming warranty or limiting liability differently from the
  366 + terms of sections 15 and 16 of this License; or
  367 +
  368 + b) Requiring preservation of specified reasonable legal notices or
  369 + author attributions in that material or in the Appropriate Legal
  370 + Notices displayed by works containing it; or
  371 +
  372 + c) Prohibiting misrepresentation of the origin of that material, or
  373 + requiring that modified versions of such material be marked in
  374 + reasonable ways as different from the original version; or
  375 +
  376 + d) Limiting the use for publicity purposes of names of licensors or
  377 + authors of the material; or
  378 +
  379 + e) Declining to grant rights under trademark law for use of some
  380 + trade names, trademarks, or service marks; or
  381 +
  382 + f) Requiring indemnification of licensors and authors of that
  383 + material by anyone who conveys the material (or modified versions of
  384 + it) with contractual assumptions of liability to the recipient, for
  385 + any liability that these contractual assumptions directly impose on
  386 + those licensors and authors.
  387 +
  388 + All other non-permissive additional terms are considered "further
  389 +restrictions" within the meaning of section 10. If the Program as you
  390 +received it, or any part of it, contains a notice stating that it is
  391 +governed by this License along with a term that is a further
  392 +restriction, you may remove that term. If a license document contains
  393 +a further restriction but permits relicensing or conveying under this
  394 +License, you may add to a covered work material governed by the terms
  395 +of that license document, provided that the further restriction does
  396 +not survive such relicensing or conveying.
  397 +
  398 + If you add terms to a covered work in accord with this section, you
  399 +must place, in the relevant source files, a statement of the
  400 +additional terms that apply to those files, or a notice indicating
  401 +where to find the applicable terms.
  402 +
  403 + Additional terms, permissive or non-permissive, may be stated in the
  404 +form of a separately written license, or stated as exceptions;
  405 +the above requirements apply either way.
  406 +
  407 + 8. Termination.
  408 +
  409 + You may not propagate or modify a covered work except as expressly
  410 +provided under this License. Any attempt otherwise to propagate or
  411 +modify it is void, and will automatically terminate your rights under
  412 +this License (including any patent licenses granted under the third
  413 +paragraph of section 11).
  414 +
  415 + However, if you cease all violation of this License, then your
  416 +license from a particular copyright holder is reinstated (a)
  417 +provisionally, unless and until the copyright holder explicitly and
  418 +finally terminates your license, and (b) permanently, if the copyright
  419 +holder fails to notify you of the violation by some reasonable means
  420 +prior to 60 days after the cessation.
  421 +
  422 + Moreover, your license from a particular copyright holder is
  423 +reinstated permanently if the copyright holder notifies you of the
  424 +violation by some reasonable means, this is the first time you have
  425 +received notice of violation of this License (for any work) from that
  426 +copyright holder, and you cure the violation prior to 30 days after
  427 +your receipt of the notice.
  428 +
  429 + Termination of your rights under this section does not terminate the
  430 +licenses of parties who have received copies or rights from you under
  431 +this License. If your rights have been terminated and not permanently
  432 +reinstated, you do not qualify to receive new licenses for the same
  433 +material under section 10.
  434 +
  435 + 9. Acceptance Not Required for Having Copies.
  436 +
  437 + You are not required to accept this License in order to receive or
  438 +run a copy of the Program. Ancillary propagation of a covered work
  439 +occurring solely as a consequence of using peer-to-peer transmission
  440 +to receive a copy likewise does not require acceptance. However,
  441 +nothing other than this License grants you permission to propagate or
  442 +modify any covered work. These actions infringe copyright if you do
  443 +not accept this License. Therefore, by modifying or propagating a
  444 +covered work, you indicate your acceptance of this License to do so.
  445 +
  446 + 10. Automatic Licensing of Downstream Recipients.
  447 +
  448 + Each time you convey a covered work, the recipient automatically
  449 +receives a license from the original licensors, to run, modify and
  450 +propagate that work, subject to this License. You are not responsible
  451 +for enforcing compliance by third parties with this License.
  452 +
  453 + An "entity transaction" is a transaction transferring control of an
  454 +organization, or substantially all assets of one, or subdividing an
  455 +organization, or merging organizations. If propagation of a covered
  456 +work results from an entity transaction, each party to that
  457 +transaction who receives a copy of the work also receives whatever
  458 +licenses to the work the party's predecessor in interest had or could
  459 +give under the previous paragraph, plus a right to possession of the
  460 +Corresponding Source of the work from the predecessor in interest, if
  461 +the predecessor has it or can get it with reasonable efforts.
  462 +
  463 + You may not impose any further restrictions on the exercise of the
  464 +rights granted or affirmed under this License. For example, you may
  465 +not impose a license fee, royalty, or other charge for exercise of
  466 +rights granted under this License, and you may not initiate litigation
  467 +(including a cross-claim or counterclaim in a lawsuit) alleging that
  468 +any patent claim is infringed by making, using, selling, offering for
  469 +sale, or importing the Program or any portion of it.
  470 +
  471 + 11. Patents.
  472 +
  473 + A "contributor" is a copyright holder who authorizes use under this
  474 +License of the Program or a work on which the Program is based. The
  475 +work thus licensed is called the contributor's "contributor version".
  476 +
  477 + A contributor's "essential patent claims" are all patent claims
  478 +owned or controlled by the contributor, whether already acquired or
  479 +hereafter acquired, that would be infringed by some manner, permitted
  480 +by this License, of making, using, or selling its contributor version,
  481 +but do not include claims that would be infringed only as a
  482 +consequence of further modification of the contributor version. For
  483 +purposes of this definition, "control" includes the right to grant
  484 +patent sublicenses in a manner consistent with the requirements of
  485 +this License.
  486 +
  487 + Each contributor grants you a non-exclusive, worldwide, royalty-free
  488 +patent license under the contributor's essential patent claims, to
  489 +make, use, sell, offer for sale, import and otherwise run, modify and
  490 +propagate the contents of its contributor version.
  491 +
  492 + In the following three paragraphs, a "patent license" is any express
  493 +agreement or commitment, however denominated, not to enforce a patent
  494 +(such as an express permission to practice a patent or covenant not to
  495 +sue for patent infringement). To "grant" such a patent license to a
  496 +party means to make such an agreement or commitment not to enforce a
  497 +patent against the party.
  498 +
  499 + If you convey a covered work, knowingly relying on a patent license,
  500 +and the Corresponding Source of the work is not available for anyone
  501 +to copy, free of charge and under the terms of this License, through a
  502 +publicly available network server or other readily accessible means,
  503 +then you must either (1) cause the Corresponding Source to be so
  504 +available, or (2) arrange to deprive yourself of the benefit of the
  505 +patent license for this particular work, or (3) arrange, in a manner
  506 +consistent with the requirements of this License, to extend the patent
  507 +license to downstream recipients. "Knowingly relying" means you have
  508 +actual knowledge that, but for the patent license, your conveying the
  509 +covered work in a country, or your recipient's use of the covered work
  510 +in a country, would infringe one or more identifiable patents in that
  511 +country that you have reason to believe are valid.
  512 +
  513 + If, pursuant to or in connection with a single transaction or
  514 +arrangement, you convey, or propagate by procuring conveyance of, a
  515 +covered work, and grant a patent license to some of the parties
  516 +receiving the covered work authorizing them to use, propagate, modify
  517 +or convey a specific copy of the covered work, then the patent license
  518 +you grant is automatically extended to all recipients of the covered
  519 +work and works based on it.
  520 +
  521 + A patent license is "discriminatory" if it does not include within
  522 +the scope of its coverage, prohibits the exercise of, or is
  523 +conditioned on the non-exercise of one or more of the rights that are
  524 +specifically granted under this License. You may not convey a covered
  525 +work if you are a party to an arrangement with a third party that is
  526 +in the business of distributing software, under which you make payment
  527 +to the third party based on the extent of your activity of conveying
  528 +the work, and under which the third party grants, to any of the
  529 +parties who would receive the covered work from you, a discriminatory
  530 +patent license (a) in connection with copies of the covered work
  531 +conveyed by you (or copies made from those copies), or (b) primarily
  532 +for and in connection with specific products or compilations that
  533 +contain the covered work, unless you entered into that arrangement,
  534 +or that patent license was granted, prior to 28 March 2007.
  535 +
  536 + Nothing in this License shall be construed as excluding or limiting
  537 +any implied license or other defenses to infringement that may
  538 +otherwise be available to you under applicable patent law.
  539 +
  540 + 12. No Surrender of Others' Freedom.
  541 +
  542 + If conditions are imposed on you (whether by court order, agreement or
  543 +otherwise) that contradict the conditions of this License, they do not
  544 +excuse you from the conditions of this License. If you cannot convey a
  545 +covered work so as to satisfy simultaneously your obligations under this
  546 +License and any other pertinent obligations, then as a consequence you may
  547 +not convey it at all. For example, if you agree to terms that obligate you
  548 +to collect a royalty for further conveying from those to whom you convey
  549 +the Program, the only way you could satisfy both those terms and this
  550 +License would be to refrain entirely from conveying the Program.
  551 +
  552 + 13. Use with the GNU Affero General Public License.
  553 +
  554 + Notwithstanding any other provision of this License, you have
  555 +permission to link or combine any covered work with a work licensed
  556 +under version 3 of the GNU Affero General Public License into a single
  557 +combined work, and to convey the resulting work. The terms of this
  558 +License will continue to apply to the part which is the covered work,
  559 +but the special requirements of the GNU Affero General Public License,
  560 +section 13, concerning interaction through a network will apply to the
  561 +combination as such.
  562 +
  563 + 14. Revised Versions of this License.
  564 +
  565 + The Free Software Foundation may publish revised and/or new versions of
  566 +the GNU General Public License from time to time. Such new versions will
  567 +be similar in spirit to the present version, but may differ in detail to
  568 +address new problems or concerns.
  569 +
  570 + Each version is given a distinguishing version number. If the
  571 +Program specifies that a certain numbered version of the GNU General
  572 +Public License "or any later version" applies to it, you have the
  573 +option of following the terms and conditions either of that numbered
  574 +version or of any later version published by the Free Software
  575 +Foundation. If the Program does not specify a version number of the
  576 +GNU General Public License, you may choose any version ever published
  577 +by the Free Software Foundation.
  578 +
  579 + If the Program specifies that a proxy can decide which future
  580 +versions of the GNU General Public License can be used, that proxy's
  581 +public statement of acceptance of a version permanently authorizes you
  582 +to choose that version for the Program.
  583 +
  584 + Later license versions may give you additional or different
  585 +permissions. However, no additional obligations are imposed on any
  586 +author or copyright holder as a result of your choosing to follow a
  587 +later version.
  588 +
  589 + 15. Disclaimer of Warranty.
  590 +
  591 + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
  592 +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
  593 +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
  594 +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
  595 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  596 +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
  597 +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
  598 +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  599 +
  600 + 16. Limitation of Liability.
  601 +
  602 + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  603 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
  604 +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
  605 +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
  606 +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
  607 +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
  608 +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
  609 +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
  610 +SUCH DAMAGES.
  611 +
  612 + 17. Interpretation of Sections 15 and 16.
  613 +
  614 + If the disclaimer of warranty and limitation of liability provided
  615 +above cannot be given local legal effect according to their terms,
  616 +reviewing courts shall apply local law that most closely approximates
  617 +an absolute waiver of all civil liability in connection with the
  618 +Program, unless a warranty or assumption of liability accompanies a
  619 +copy of the Program in return for a fee.
  620 +
  621 + END OF TERMS AND CONDITIONS
  622 +
  623 + How to Apply These Terms to Your New Programs
  624 +
  625 + If you develop a new program, and you want it to be of the greatest
  626 +possible use to the public, the best way to achieve this is to make it
  627 +free software which everyone can redistribute and change under these terms.
  628 +
  629 + To do so, attach the following notices to the program. It is safest
  630 +to attach them to the start of each source file to most effectively
  631 +state the exclusion of warranty; and each file should have at least
  632 +the "copyright" line and a pointer to where the full notice is found.
  633 +
  634 + <one line to give the program's name and a brief idea of what it does.>
  635 + Copyright (C) <year> <name of author>
  636 +
  637 + This program is free software: you can redistribute it and/or modify
  638 + it under the terms of the GNU General Public License as published by
  639 + the Free Software Foundation, either version 3 of the License, or
  640 + (at your option) any later version.
  641 +
  642 + This program is distributed in the hope that it will be useful,
  643 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  644 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  645 + GNU General Public License for more details.
  646 +
  647 + You should have received a copy of the GNU General Public License
  648 + along with this program. If not, see <https://www.gnu.org/licenses/>.
  649 +
  650 +Also add information on how to contact you by electronic and paper mail.
  651 +
  652 + If the program does terminal interaction, make it output a short
  653 +notice like this when it starts in an interactive mode:
  654 +
  655 + <program> Copyright (C) <year> <name of author>
  656 + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
  657 + This is free software, and you are welcome to redistribute it
  658 + under certain conditions; type `show c' for details.
  659 +
  660 +The hypothetical commands `show w' and `show c' should show the appropriate
  661 +parts of the General Public License. Of course, your program's commands
  662 +might be different; for a GUI interface, you would use an "about box".
  663 +
  664 + You should also get your employer (if you work as a programmer) or school,
  665 +if any, to sign a "copyright disclaimer" for the program, if necessary.
  666 +For more information on this, and how to apply and follow the GNU GPL, see
  667 +<https://www.gnu.org/licenses/>.
  668 +
  669 + The GNU General Public License does not permit incorporating your program
  670 +into proprietary programs. If your program is a subroutine library, you
  671 +may consider it more useful to permit linking proprietary applications with
  672 +the library. If this is what you want to do, use the GNU Lesser General
  673 +Public License instead of this License. But first, please read
  674 +<https://www.gnu.org/licenses/why-not-lgpl.html>.
  1 +## RVM Inference
  2 +<div align='left'>
  3 + <img src=https://img.shields.io/github/stars/DefTruth/RobustVideoMatting.lite.ai.toolkit.svg?style=social >
  4 + <img src=https://img.shields.io/github/forks/DefTruth/RobustVideoMatting.lite.ai.toolkit.svg?style=social >
  5 + <img src=https://img.shields.io/github/watchers/DefTruth/RobustVideoMatting.lite.ai.toolkit.svg?style=social>
  6 +</div>
  7 +
  8 +## News 👇👇
  9 +Most of my time now is focused on **LLM/VLM** Inference. Please check 📖[Awesome-LLM-Inference](https://github.com/DefTruth/Awesome-LLM-Inference) ![](https://img.shields.io/github/stars/DefTruth/Awesome-LLM-Inference.svg?style=social), 📖[Awesome-SD-Inference](https://github.com/DefTruth/Awesome-SD-Inference) ![](https://img.shields.io/github/stars/DefTruth/Awesome-SD-Inference.svg?style=social) and 📖[CUDA-Learn-Notes](https://github.com/DefTruth/CUDA-Learn-Notes) ![](https://img.shields.io/github/stars/DefTruth/CUDA-Learn-Notes.svg?style=social) for more details.
  10 +
  11 +## 1. 简介
  12 +使用Lite.AI.ToolKit C++工具箱来跑RobustVideoMatting的一些案例(https://github.com/DefTruth/lite.ai.toolkit) ,ONNXRuntime、MNN、NCNN和TNN四个版本。
  13 +
  14 +<div align='center'>
  15 + <img src='resources/interviewi.gif' height="80px" width="160px">
  16 + <img src='resources/interview.gif' height="80px" width="160px">
  17 + <img src='resources/dance3i.gif' height="80px" width="160px">
  18 + <img src='resources/dance3.gif' height="80px" width="160px">
  19 + <br>
  20 + <img src='resources/teslai.gif' height="80px" width="160px">
  21 + <img src='resources/tesla.gif' height="80px" width="160px">
  22 + <img src='resources/b5i.gif' height="80px" width="160px">
  23 + <img src='resources/b5.gif' height="80px" width="160px">
  24 +</div>
  25 +
  26 +若是有用,❤️不妨给个⭐️🌟支持一下吧~ 🙃🤪🍀
  27 +
  28 +## 2. C++版本源码
  29 +
  30 +RobustVideoMatting C++ 版本的源码包含ONNXRuntime、MNN、NCNN和TNN四个版本,可以在 [lite.ai.toolkit](https://github.com/DefTruth/lite.ai.toolkit) 工具箱中找到。本项目主要介绍如何基于 [lite.ai.toolkit](https://github.com/DefTruth/lite.ai.toolkit) 工具箱,直接使用RobustVideoMatting实现视频抠图和图片抠图。需要说明的是,本项目是基于MacOS下编译的 [liblite.ai.toolkit.v0.1.0.dylib](https://github.com/DefTruth/RobustVideoMatting.lite.ai.toolkit/blob/main/lite.ai.toolkit/lib) 来实现的,对于使用MacOS的用户,可以直接下载本项目包含的*liblite.ai.toolkit.v0.1.0*动态库和其他依赖库进行使用。而非MacOS用户,则需要从[lite.ai.toolkit](https://github.com/DefTruth/lite.ai.toolkit) 中下载源码进行编译。[lite.ai.toolkit](https://github.com/DefTruth/lite.ai.toolkit) c++工具箱目前包含70+流行的开源模型。
  31 + * [rvm.cpp](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/ort/cv/rvm.cpp)
  32 + * [rvm.h](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/ort/cv/rvm.h)
  33 + * [mnn_rvm.cpp](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/mnn/cv/mnn_rvm.cpp)
  34 + * [mnn_rvm.h](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/mnn/cv/mnn_rvm.h)
  35 + * [ncnn_rvm.cpp](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/ncnn/cv/ncnn_rvm.cpp)
  36 + * [ncnn_rvm.h](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/ncnn/cv/ncnn_rvm.h)
  37 + * [tnn_rvm.cpp](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/tnn/cv/tnn_rvm.cpp)
  38 + * [tnn_rvm.h](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/tnn/cv/tnn_rvm.h)
  39 +
  40 +NCNN版本的测试没有通过,转换的模型可能有问题,这里先放出代码。这里案例使用的接口是默认版本,即ONNXRuntime. 目前ONNXRuntime、MNN和TNN版本均已测试通过。
  41 +
  42 +## 3. 模型文件
  43 +
  44 +### 3.1 ONNX模型文件
  45 +可以从我提供的链接下载 ([Baidu Drive](https://pan.baidu.com/s/1elUGcx7CZkkjEoYhTMwTRQ) code: 8gin) , 也可以从 [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) 官方仓库下载。
  46 +
  47 +| Class | Pretrained ONNX Files | Rename or Converted From (Repo) | Size |
  48 +| :---------------------------------: | :-------------------: | :-------------------------------------------------------: | :---: |
  49 +| *lite::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32.onnx | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  50 +| *lite::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp16.onnx | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 7.2Mb |
  51 +| *lite::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32.onnx | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  52 +| *lite::cv::matting::RobustVideoMatting* | rvm_resnet50_fp16.onnx | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 100Mb |
  53 +
  54 +### 3.2 MNN模型文件
  55 +可以从我提供的链接下载 ([Baidu Drive](https://pan.baidu.com/s/1KyO-bCYUv6qPq2M8BH_Okg) code: 9v63)
  56 +
  57 +| Class | Pretrained MNN Files | Rename or Converted From (Repo) | Size |
  58 +| :---------------------------------: | :-------------------: | :-------------------------------------------------------: | :---: |
  59 +| *lite::mnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32.mnn | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  60 +| *lite::mnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-480-480.mnn | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  61 +| *lite::mnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-480-640.mnn | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  62 +| *lite::mnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-640-480.mnn | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  63 +| *lite::mnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-1080-1920.mnn | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  64 +| *lite::mnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32.mnn | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  65 +| *lite::mnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-480-480.mnn | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  66 +| *lite::mnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-480-640.mnn | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  67 +| *lite::mnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-640-480.mnn | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  68 +| *lite::mnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-1080-1920.mnn | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  69 +
  70 +### 3.3 NCNN模型文件
  71 +可以从我提供的链接下载 ([Baidu Drive](https://pan.baidu.com/s/1hlnqyNsFbMseGFWscgVhgQ) code: sc7f)
  72 +
  73 +| Class | Pretrained NCNN Files | Rename or Converted From (Repo) | Size |
  74 +| :---------------------------------: | :-------------------: | :-------------------------------------------------------: | :---: |
  75 +| *lite::ncnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-opt.param&bin | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  76 +| *lite::ncnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-480-480-opt.param&bin | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  77 +| *lite::ncnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-480-640-opt.param&bin | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  78 +| *lite::ncnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-640-480-opt.param&bin | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  79 +| *lite::ncnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-1080-1920-opt.param&bin | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  80 +| *lite::ncnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-opt.param&bin | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  81 +| *lite::ncnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-480-480-opt.param&bin | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  82 +| *lite::ncnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-480-640-opt.param&bin | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  83 +| *lite::ncnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-640-480-opt.param&bin | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  84 +| *lite::ncnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-1080-1920-opt.param&bin | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  85 +
  86 +### 3.4 TNN模型文件
  87 +可以从我提供的链接下载 ([Baidu Drive](https://pan.baidu.com/s/1lvM2YKyUbEc5HKVtqITpcw) code: 6o6k)
  88 +
  89 +| Class | Pretrained TNN Files | Rename or Converted From (Repo) | Size |
  90 +| :---------------------------------: | :-------------------: | :-------------------------------------------------------: | :---: |
  91 +| *lite::tnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-480-480-sim.tnnproto&tnnmodel | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  92 +| *lite::tnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-480-640-sim.tnnproto&tnnmodel | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  93 +| *lite::tnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-640-480-sim.tnnproto&tnnmodel | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  94 +| *lite::tnn::cv::matting::RobustVideoMatting* | rvm_mobilenetv3_fp32-1080-1920-sim.tnnproto&tnnmodel | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 14Mb |
  95 +| *lite::tnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-480-480-sim.tnnproto&tnnmodel | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  96 +| *lite::tnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-480-640-sim.tnnproto&tnnmodel | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  97 +| *lite::tnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-640-480-sim.tnnproto&tnnmodel | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  98 +| *lite::tnn::cv::matting::RobustVideoMatting* | rvm_resnet50_fp32-1080-1920-sim.tnnproto&tnnmodel | [RobustVideoMatting](https://github.com/PeterL1n/RobustVideoMatting) | 50Mb |
  99 +
  100 +
  101 +## 4. 接口文档
  102 +
  103 +[lite.ai.toolkit](https://github.com/DefTruth/lite.ai.toolkit) 中,RobustVideoMatting的实现类为:
  104 +
  105 +```c++
  106 +class LITE_EXPORTS lite::cv::matting::RobustVideoMatting;
  107 +class LITE_EXPORTS lite::mnn::cv::matting::RobustVideoMatting;
  108 +class LITE_EXPORTS lite::tnn::cv::matting::RobustVideoMatting;
  109 +class LITE_EXPORTS lite::ncnn::cv::matting::RobustVideoMatting;
  110 +```
  111 +
  112 +该类型目前包含两个公共接口,分别是`detect`和`detect_video`,前者用于图像抠图,后者用于视频抠图。不同推理引擎的实现,接口基本相同。TNN、MNN和NCNN版本的接口不含downsample_ratio,因为转换时,我是按照静态维度转换的,并且在转换模型时固定了一个合适的downsample_ratio,不需要再推理时再设置。具体区别可以跳转到c++实现的源码查看。
  113 +```c++
  114 + /**
  115 + * Image Matting Using RVM(https://github.com/PeterL1n/RobustVideoMatting)
  116 + * @param mat: cv::Mat BGR HWC
  117 + * @param content: types::MattingContent to catch the detected results.
  118 + * @param downsample_ratio: 0.25 by default.
  119 + * See https://github.com/PeterL1n/RobustVideoMatting/blob/master/documentation/inference_zh_Hans.md
  120 + */
  121 + void detect(const cv::Mat &mat, types::MattingContent &content,
  122 + float downsample_ratio = 0.25f);
  123 + /**
  124 + * Video Matting Using RVM(https://github.com/PeterL1n/RobustVideoMatting)
  125 + * @param video_path: eg. xxx/xxx/input.mp4
  126 + * @param output_path: eg. xxx/xxx/output.mp4
  127 + * @param contents: vector of MattingContent to catch the detected results.
  128 + * @param save_contents: false by default, whether to save MattingContent.
  129 + * @param downsample_ratio: 0.25 by default.
  130 + * See https://github.com/PeterL1n/RobustVideoMatting/blob/master/documentation/inference_zh_Hans.md
  131 + * @param writer_fps: FPS for VideoWriter, 20 by default.
  132 + */
  133 + void detect_video(const std::string &video_path,
  134 + const std::string &output_path,
  135 + std::vector<types::MattingContent> &contents,
  136 + bool save_contents = false,
  137 + float downsample_ratio = 0.25f,
  138 + unsigned int writer_fps = 20);
  139 +```
  140 +
  141 +* `detect`接口输入参数说明:
  142 + * mat: cv::Mat BGR格式图像
  143 + * content: types::MattingContent类型,用来保存检测的结果,包含类型为cv::Mat的三个成员,分别是
  144 + * `fgr_mat`: `cv::Mat (H,W,C=3) BGR` 格式,值范围为0~255 的 `CV_8UC3`, 用于保存估计的前景
  145 + * `pha_mat`:` cv::Mat (H,W,C=1)` 值范围为0.~1.的 `CV_32FC1`, 用于保存估计的alpha(matte)值
  146 + * `merge_mat`: `cv::Mat (H,W,C=3) BGR` 格式,值范围为0~255 的 `CV_8UC3`, 用于保存根据pha融合前景背景的合成图像
  147 + * `flag`: bool 类型标志位,表示是否检测成功
  148 + * downsample_ratio: float,下采样比率,默认0.25f,值的设置可以参考[官方文档](https://github.com/PeterL1n/RobustVideoMatting/blob/master/documentation/inference_zh_Hans.md) , 如下:
  149 +
  150 + | 分辨率 | 人像 | 全身 |
  151 + | ------------- | ------------- | -------------- |
  152 + | <= 512x512 | 1 | 1 |
  153 + | 1280x720 | 0.375 | 0.6 |
  154 + | 1920x1080 | 0.25 | 0.4 |
  155 + | 3840x2160 | 0.125 | 0.2 |
  156 +
  157 + 模型在内部将高分辨率输入缩小做初步的处理,然后再放大做细分处理。 建议设置 `downsample_ratio` 使缩小后的分辨率维持在 256 到 512 像素之间. 例如,`1920x1080` 的输入用 `downsample_ratio=0.25`,缩小后的分辨率 `480x270` 在 256 到 512 像素之间。 根据视频内容调整 `downsample_ratio`。若视频是上身人像,低 `downsample_ratio` 足矣。若视频是全身像,建议尝试更高的 `downsample_ratio`。但注意,过高的 `downsample_ratio` 反而会降低效果。
  158 +
  159 +
  160 +* `detect_video`接口输入参数说明:
  161 + * video_path: string, 输入的视频路径
  162 + * output_path: string, 输出的视频路径
  163 + * contents:MattingContent类型的vector,用来保存每帧检测的结果
  164 + * save_contents:bool,是否保存每一帧的结果,默认false。当分辨率很大时,保存所有的结果将会占用非常多内存
  165 + * downsample_ratio: float,下采样比率,默认0.25f,同上。
  166 + * writer_fps:int 视频写出的帧率,默认20
  167 +
  168 +## 5. 使用案例
  169 +这里测试使用的是mobilenetv3版本的rvm模型,如果你使用resnet50版本的模型,将会得到更高精度的结果。
  170 +
  171 +### 5.1 图像抠图案例
  172 +
  173 +```c++
  174 +#include "lite/lite.h"
  175 +
  176 +// Image Matting Interface
  177 +static void test_image()
  178 +{
  179 + std::string onnx_path = "../hub/onnx/cv/rvm_mobilenetv3_fp32.onnx";
  180 + std::string img_path = "../examples/lite/resources/test.jpg";
  181 + std::string save_fgr_path = "../logs/test_lite_rvm_fgr.jpg";
  182 + std::string save_pha_path = "../logs/test_rvm_pha.jpg";
  183 + std::string save_merge_path = "../logs/test_lite_rvm_merge.jpg";
  184 +
  185 + auto *rvm = new lite::matting::RobustVideoMatting(onnx_path, 16); // 16 threads
  186 + lite::types::MattingContent content;
  187 + cv::Mat img_bgr = cv::imread(img_path);
  188 +
  189 + // 1. image matting.
  190 + rvm->detect(img_bgr, content, 0.25f);
  191 +
  192 + if (content.flag)
  193 + {
  194 + if (!content.fgr_mat.empty()) cv::imwrite(save_fgr_path, content.fgr_mat); // 预测的前景fgr
  195 + if (!content.pha_mat.empty()) cv::imwrite(save_pha_path, content.pha_mat * 255.); // 预测的前景pha
  196 + if (!content.merge_mat.empty()) cv::imwrite(save_merge_path, content.merge_mat); // 合成图
  197 + }
  198 +
  199 + delete rvm;
  200 +}
  201 +
  202 +```
  203 +* 输出结果为: (依次为原图、预测的pha、预测的前景fgr、合成图)
  204 +
  205 +<div align='center'>
  206 + <img src='resources/test.jpg' height="160px" width="160px">
  207 + <img src='resources/test_rvm_pha.jpg' height="160px" width="160px">
  208 + <img src='resources/test_rvm_fgr.jpg' height="160px" width="160px">
  209 + <img src='resources/test_rvm_merge.jpg' height="160px" width="160px">
  210 +</div>
  211 +
  212 +### 5.2 视频抠图案例
  213 +
  214 +#### 5.2.1 ONNXRuntime版本
  215 +```c++
  216 +
  217 +#include "lite/lite.h"
  218 +
  219 +// Video Matting Interface
  220 +static void test_video()
  221 +{
  222 + std::string onnx_path = "../hub/onnx/cv/rvm_mobilenetv3_fp32.onnx";
  223 + std::string video_path = "../examples/lite/resources/tesla.mp4";
  224 + std::string output_path = "../logs/tesla_onnx.mp4";
  225 +
  226 + auto *rvm = new lite::cv::matting::RobustVideoMatting(onnx_path, 16); // 16 threads
  227 + std::vector<lite::types::MattingContent> contents;
  228 +
  229 + // 1. video matting.
  230 + rvm->detect_video(video_path, output_path, contents, false, 0.4f);
  231 +
  232 + delete rvm;
  233 +}
  234 +
  235 +```
  236 +
  237 +#### 5.2.2 MNN版本
  238 +```c++
  239 +static void test_mnn()
  240 +{
  241 +#ifdef ENABLE_MNN
  242 + std::string mnn_path = "../hub/mnn/cv/rvm_mobilenetv3_fp32-480-640.mnn";
  243 + std::string video_path = "../examples/lite/resources/tesla.mp4";
  244 + std::string output_path = "../logs/tesla_mnn.mp4";
  245 +
  246 + auto *rvm = new lite::mnn::cv::matting::RobustVideoMatting(mnn_path, 16, 0); // 16 threads
  247 + std::vector<lite::types::MattingContent> contents;
  248 +
  249 + // 1. video matting.
  250 + rvm->detect_video(video_path, output_path, contents, false);
  251 +
  252 + delete rvm;
  253 +#endif
  254 +}
  255 +```
  256 +#### 5.2.3 TNN版本
  257 +```C++
  258 +static void test_tnn()
  259 +{
  260 +#ifdef ENABLE_TNN
  261 +
  262 + std::string proto_path = "../hub/tnn/cv/rvm_mobilenetv3_fp32-480-480-sim.opt.tnnproto";
  263 + std::string model_path = "../hub/tnn/cv/rvm_mobilenetv3_fp32-480-480-sim.opt.tnnmodel";
  264 + std::string video_path = "../examples/lite/resources/test_lite_rvm_1.mp4";
  265 + std::string output_path = "../logs/test_lite_rvm_1_tnn.mp4";
  266 +
  267 + auto *rvm = new lite::tnn::cv::matting::RobustVideoMatting(
  268 + proto_path, model_path, 16); // 16 threads
  269 + std::vector<lite::types::MattingContent> contents;
  270 +
  271 + // 1. video matting.
  272 + rvm->detect_video(video_path, output_path, contents, false);
  273 +
  274 + delete rvm;
  275 +#endif
  276 +}
  277 +```
  278 +
  279 +* 输出结果为:
  280 +
  281 +<div align='center'>
  282 + <img src='resources/interviewi.gif' height="80px" width="160px">
  283 + <img src='resources/interview.gif' height="80px" width="160px">
  284 + <img src='resources/dance3i.gif' height="80px" width="160px">
  285 + <img src='resources/dance3.gif' height="80px" width="160px">
  286 + <br>
  287 + <img src='resources/teslai.gif' height="80px" width="160px">
  288 + <img src='resources/tesla.gif' height="80px" width="160px">
  289 + <img src='resources/b5i.gif' height="80px" width="160px">
  290 + <img src='resources/b5.gif' height="80px" width="160px">
  291 +</div>
  292 +
  293 +## 6. 编译运行
  294 +在MacOS下可以直接编译运行本项目,无需下载其他依赖库。其他系统则需要从[lite.ai.toolkit](https://github.com/DefTruth/lite.ai.toolkit) 中下载源码先编译*lite.ai.toolkit.v0.1.0*动态库。
  295 +```shell
  296 +git clone --depth=1 https://github.com/DefTruth/RobustVideoMatting.lite.ai.toolkit.git
  297 +cd RobustVideoMatting.lite.ai.toolkit
  298 +sh ./build.sh
  299 +```
  300 +* CMakeLists.txt设置
  301 +```cmake
  302 +cmake_minimum_required(VERSION 3.17)
  303 +project(RobustVideoMatting.lite.ai.toolkit)
  304 +
  305 +set(CMAKE_CXX_STANDARD 11)
  306 +
  307 +# setting up lite.ai.toolkit
  308 +set(LITE_AI_DIR ${CMAKE_SOURCE_DIR}/lite.ai.toolkit)
  309 +set(LITE_AI_INCLUDE_DIR ${LITE_AI_DIR}/include)
  310 +set(LITE_AI_LIBRARY_DIR ${LITE_AI_DIR}/lib)
  311 +include_directories(${LITE_AI_INCLUDE_DIR})
  312 +link_directories(${LITE_AI_LIBRARY_DIR})
  313 +
  314 +set(OpenCV_LIBS
  315 + opencv_highgui
  316 + opencv_core
  317 + opencv_imgcodecs
  318 + opencv_imgproc
  319 + opencv_video
  320 + opencv_videoio
  321 + )
  322 +# add your executable
  323 +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/examples/build)
  324 +
  325 +add_executable(lite_rvm examples/test_lite_rvm.cpp)
  326 +target_link_libraries(lite_rvm
  327 + lite.ai.toolkit
  328 + onnxruntime
  329 + MNN # need, if built lite.ai.toolkit with ENABLE_MNN=ON, default OFF
  330 + ncnn # need, if built lite.ai.toolkit with ENABLE_NCNN=ON, default OFF
  331 + TNN # need, if built lite.ai.toolkit with ENABLE_TNN=ON, default OFF
  332 + ${OpenCV_LIBS}) # link lite.ai.toolkit & other libs.
  333 +```
  334 +
  335 +
  336 +* building && testing information:
  337 +```shell
  338 +-- Generating done
  339 +-- Build files have been written to: /Users/xxx/Desktop/xxx/RobustVideoMatting.lite.ai.toolkit/examples/build
  340 +[ 50%] Building CXX object CMakeFiles/lite_rvm.dir/examples/test_lite_rvm.cpp.o
  341 +[100%] Linking CXX executable lite_rvm
  342 +[100%] Built target lite_rvm
  343 +Testing Start ...
  344 +Load ../hub/onnx/cv/rvm_mobilenetv3_fp32.onnx done!
  345 +write done! 1/774 done!
  346 +write done! 2/774 done!
  347 +write done! 3/774 done!
  348 +write done! 4/774 done!
  349 +write done! 5/774 done!
  350 +write done! 6/774 done!
  351 +...
  352 +write done! 724/774 done!
  353 +Testing Successful !
  354 +```
  355 +
  356 +![](resources/teslab.gif)
  1 +#!/bin/bash
  2 +if [ ! -d ./examples/build ]; then
  3 + mkdir ./examples/build
  4 +else
  5 + rm -rf ./examples/build/*
  6 +fi
  7 +
  8 +cd ./examples/build && cmake \
  9 + -DCMAKE_BUILD_TYPE=Realese\
  10 + -DINCLUDE_OPENCV=ON\
  11 + -DENABLE_MNN=OFF\
  12 + -DENABLE_NCNN=OFF\
  13 + -DENABLE_TNN=OFF\
  14 + ../.. && make -j1
  15 +echo "Testing Start ..."
  16 +./lite_rvm
  17 +echo "Testing Successful !"
  1 +rvm_resnet50_fp16.onnx
  2 +rvm_resnet50_fp32.onnx
  3 +rvm_mobilenetv3_fp16.onnx
This file is too large to display.
  1 +*.mp4
  2 +*.jpg
  1 +asianboss2.mp4
  2 +b5.mp4
  3 +dance3.mp4
This file is too large to display.
不能预览此文件类型
不能预览此文件类型
不能预览此文件类型
  1 +//
  2 +// Created by DefTruth on 2021/9/20.
  3 +//
  4 +
  5 +#include "lite/lite.h"
  6 +
  7 +// Video Matting Interface
  8 +static void test_video()
  9 +{
  10 + std::string onnx_path = "../hub/onnx/cv/rvm_mobilenetv3_fp32.onnx";
  11 + std::string video_path = "../resources/interview.mp4";
  12 + std::string output_path = "../logs/interview_onnx.mp4";
  13 +
  14 + auto *rvm = new lite::cv::matting::RobustVideoMatting(onnx_path, 16); // 16 threads
  15 + std::vector<lite::types::MattingContent> contents;
  16 +
  17 + // 1. video matting.
  18 + rvm->detect_video(video_path, output_path, contents, false, 0.25f);
  19 +
  20 + delete rvm;
  21 +}
  22 +
  23 +
  24 +// Image Matting Interface
  25 +static void test_image()
  26 +{
  27 + std::string onnx_path = "../hub/onnx/cv/rvm_mobilenetv3_fp32.onnx";
  28 + std::string img_path = "../resources/test.jpg";
  29 + std::string img_path_2 = "../resources/test2.png";
  30 + std::string save_fgr_path = "../logs/test_rvm_fgr.jpg";
  31 + std::string save_pha_path = "../logs/test_rvm_pha.jpg";
  32 + std::string save_merge_path = "../logs/test_rvm_merge.jpg";
  33 + std::string save_fgr_path_2 = "../logs/test_rvm_fgr_2.jpg";
  34 + std::string save_pha_path_2 = "../logs/test_rvm_pha_2.jpg";
  35 + std::string save_merge_path_2 = "../logs/test_rvm_merge_2.jpg";
  36 +
  37 +
  38 + auto *rvm = new lite::cv::matting::RobustVideoMatting(onnx_path, 16); // 16 threads
  39 + lite::types::MattingContent content, content_2;
  40 + cv::Mat img_bgr = cv::imread(img_path);
  41 + cv::Mat img_bgr_2 = cv::imread(img_path_2);
  42 +
  43 + // 1. image matting.
  44 + rvm->detect(img_bgr, content, 0.25f);
  45 +
  46 + rvm->detect(img_bgr_2, content_2, 0.25f);
  47 +
  48 + if (content.flag)
  49 + {
  50 + if (!content.fgr_mat.empty()) cv::imwrite(save_fgr_path, content.fgr_mat);
  51 + if (!content.pha_mat.empty()) cv::imwrite(save_pha_path, content.pha_mat * 255.);
  52 + if (!content.merge_mat.empty()) cv::imwrite(save_merge_path, content.merge_mat);
  53 + std::cout << "Saved " << save_merge_path << "\n";
  54 + }
  55 +
  56 + if (content_2.flag)
  57 + {
  58 + if (!content_2.fgr_mat.empty()) cv::imwrite(save_fgr_path_2, content_2.fgr_mat);
  59 + if (!content_2.pha_mat.empty()) cv::imwrite(save_pha_path_2, content_2.pha_mat * 255.);
  60 + if (!content_2.merge_mat.empty()) cv::imwrite(save_merge_path_2, content_2.merge_mat);
  61 + std::cout << "Saved " << save_merge_path_2 << "\n";
  62 + }
  63 +
  64 + delete rvm;
  65 +}
  66 +
  67 +
  68 +static void test_rvm()
  69 +{
  70 + test_video();
  71 + test_image();
  72 +}
  73 +
  74 +int main(__unused int argc, __unused char *argv[])
  75 +{
  76 + test_rvm();
  77 + return 0;
  78 +}
  1 +//
  2 +// AutoTime.hpp
  3 +// MNN
  4 +//
  5 +// Created by MNN on 2018/07/27.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +
  9 +#ifndef AutoTime_hpp
  10 +#define AutoTime_hpp
  11 +
  12 +#include <stdint.h>
  13 +#include <stdio.h>
  14 +#include <MNN/MNNDefine.h>
  15 +
  16 +namespace MNN {
  17 +
  18 +class MNN_PUBLIC Timer {
  19 +public:
  20 + Timer();
  21 + ~Timer();
  22 + Timer(const Timer&) = delete;
  23 + Timer(const Timer&&) = delete;
  24 + Timer& operator=(const Timer&) = delete;
  25 + Timer& operator=(const Timer&&) = delete;
  26 +
  27 + // reset timer
  28 + void reset();
  29 + // get duration (us) from init or latest reset.
  30 + uint64_t durationInUs();
  31 +
  32 +protected:
  33 + uint64_t mLastResetTime;
  34 +};
  35 +
  36 +/** time tracing util. prints duration between init and deinit. */
  37 +class MNN_PUBLIC AutoTime : Timer {
  38 +public:
  39 + AutoTime(int line, const char* func);
  40 + ~AutoTime();
  41 + AutoTime(const AutoTime&) = delete;
  42 + AutoTime(const AutoTime&&) = delete;
  43 + AutoTime& operator=(const AutoTime&) = delete;
  44 + AutoTime& operator=(const AutoTime&&) = delete;
  45 +
  46 +private:
  47 + int mLine;
  48 + char* mName;
  49 +};
  50 +} // namespace MNN
  51 +
  52 +#ifdef MNN_OPEN_TIME_TRACE
  53 +#define AUTOTIME MNN::AutoTime ___t(__LINE__, __func__)
  54 +#else
  55 +#define AUTOTIME
  56 +#endif
  57 +
  58 +#endif /* AutoTime_hpp */
  1 +//
  2 +// ErrorCode.hpp
  3 +// MNN
  4 +//
  5 +// Created by MNN on 2018/09/18.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +
  9 +#ifndef ErrorCode_h
  10 +#define ErrorCode_h
  11 +
  12 +namespace MNN {
  13 +enum ErrorCode {
  14 +#ifdef NO_ERROR
  15 +#undef NO_ERROR
  16 +#endif // NO_ERROR
  17 + NO_ERROR = 0,
  18 + OUT_OF_MEMORY = 1,
  19 + NOT_SUPPORT = 2,
  20 + COMPUTE_SIZE_ERROR = 3,
  21 + NO_EXECUTION = 4,
  22 + INVALID_VALUE = 5,
  23 +
  24 + // User error
  25 + INPUT_DATA_ERROR = 10,
  26 + CALL_BACK_STOP = 11,
  27 +
  28 + // Op Resize Error
  29 + TENSOR_NOT_SUPPORT = 20,
  30 + TENSOR_NEED_DIVIDE = 21,
  31 +};
  32 +} // namespace MNN
  33 +
  34 +#endif /* ErrorCode_h */
  1 +#ifndef HALIDE_HALIDERUNTIME_H
  2 +#define HALIDE_HALIDERUNTIME_H
  3 +
  4 +#include <stddef.h>
  5 +#include <stdint.h>
  6 +#include <stdbool.h>
  7 +
  8 +#ifdef __cplusplus
  9 +extern "C" {
  10 +#endif
  11 +
  12 +// Note that you should not use "inline" along with HALIDE_ALWAYS_INLINE;
  13 +// it is not necessary, and may produce warnings for some build configurations.
  14 +#ifdef _MSC_VER
  15 +#define HALIDE_ALWAYS_INLINE __forceinline
  16 +#define HALIDE_NEVER_INLINE __declspec(noinline)
  17 +#else
  18 +#define HALIDE_ALWAYS_INLINE __attribute__((always_inline)) inline
  19 +#define HALIDE_NEVER_INLINE __attribute__((noinline))
  20 +#endif
  21 +
  22 +/** \file
  23 + *
  24 + * This file declares the routines used by Halide internally in its
  25 + * runtime. On platforms that support weak linking, these can be
  26 + * replaced with user-defined versions by defining an extern "C"
  27 + * function with the same name and signature.
  28 + *
  29 + * When doing Just In Time (JIT) compilation methods on the Func being
  30 + * compiled must be called instead. The corresponding methods are
  31 + * documented below.
  32 + *
  33 + * All of these functions take a "void *user_context" parameter as their
  34 + * first argument; if the Halide kernel that calls back to any of these
  35 + * functions has been compiled with the UserContext feature set on its Target,
  36 + * then the value of that pointer passed from the code that calls the
  37 + * Halide kernel is piped through to the function.
  38 + *
  39 + * Some of these are also useful to call when using the default
  40 + * implementation. E.g. halide_shutdown_thread_pool.
  41 + *
  42 + * Note that even on platforms with weak linking, some linker setups
  43 + * may not respect the override you provide. E.g. if the override is
  44 + * in a shared library and the halide object files are linked directly
  45 + * into the output, the builtin versions of the runtime functions will
  46 + * be called. See your linker documentation for more details. On
  47 + * Linux, LD_DYNAMIC_WEAK=1 may help.
  48 + *
  49 + */
  50 +
  51 +// Forward-declare to suppress warnings if compiling as C.
  52 +struct halide_buffer_t;
  53 +
  54 +/** Types in the halide type system. They can be ints, unsigned ints,
  55 + * or floats (of various bit-widths), or a handle (which is always 64-bits).
  56 + * Note that the int/uint/float values do not imply a specific bit width
  57 + * (the bit width is expected to be encoded in a separate value).
  58 + */
  59 +typedef enum halide_type_code_t
  60 +{
  61 + halide_type_int = 0, //!< signed integers
  62 + halide_type_uint = 1, //!< unsigned integers
  63 + halide_type_float = 2, //!< floating point numbers
  64 + halide_type_handle = 3 //!< opaque pointer type (void *)
  65 +} halide_type_code_t;
  66 +
  67 +// Note that while __attribute__ can go before or after the declaration,
  68 +// __declspec apparently is only allowed before.
  69 +#ifndef HALIDE_ATTRIBUTE_ALIGN
  70 + #ifdef _MSC_VER
  71 + #define HALIDE_ATTRIBUTE_ALIGN(x) __declspec(align(x))
  72 + #else
  73 + #define HALIDE_ATTRIBUTE_ALIGN(x) __attribute__((aligned(x)))
  74 + #endif
  75 +#endif
  76 +
  77 +/** A runtime tag for a type in the halide type system. Can be ints,
  78 + * unsigned ints, or floats of various bit-widths (the 'bits'
  79 + * field). Can also be vectors of the same (by setting the 'lanes'
  80 + * field to something larger than one). This struct should be
  81 + * exactly 32-bits in size. */
  82 +struct halide_type_t {
  83 + /** The basic type code: signed integer, unsigned integer, or floating point. */
  84 +#if __cplusplus >= 201103L
  85 + HALIDE_ATTRIBUTE_ALIGN(1) halide_type_code_t code; // halide_type_code_t
  86 +#else
  87 + HALIDE_ATTRIBUTE_ALIGN(1) uint8_t code; // halide_type_code_t
  88 +#endif
  89 +
  90 + /** The number of bits of precision of a single scalar value of this type. */
  91 + HALIDE_ATTRIBUTE_ALIGN(1) uint8_t bits;
  92 +
  93 + /** How many elements in a vector. This is 1 for scalar types. */
  94 + HALIDE_ATTRIBUTE_ALIGN(2) uint16_t lanes;
  95 +
  96 +#ifdef __cplusplus
  97 + /** Construct a runtime representation of a Halide type from:
  98 + * code: The fundamental type from an enum.
  99 + * bits: The bit size of one element.
  100 + * lanes: The number of vector elements in the type. */
  101 + HALIDE_ALWAYS_INLINE halide_type_t(halide_type_code_t code, uint8_t bits, uint16_t lanes = 1)
  102 + : code(code), bits(bits), lanes(lanes) {
  103 + }
  104 +
  105 + /** Default constructor is required e.g. to declare halide_trace_event
  106 + * instances. */
  107 + HALIDE_ALWAYS_INLINE halide_type_t() : code((halide_type_code_t)0), bits(0), lanes(0) {}
  108 +
  109 + /** Compare two types for equality. */
  110 + HALIDE_ALWAYS_INLINE bool operator==(const halide_type_t &other) const {
  111 + return (code == other.code &&
  112 + bits == other.bits &&
  113 + lanes == other.lanes);
  114 + }
  115 +
  116 + HALIDE_ALWAYS_INLINE bool operator!=(const halide_type_t &other) const {
  117 + return !(*this == other);
  118 + }
  119 +
  120 + /** Size in bytes for a single element, even if width is not 1, of this type. */
  121 + HALIDE_ALWAYS_INLINE int bytes() const { return (bits + 7) / 8; }
  122 +#endif
  123 +};
  124 +
  125 +/** An opaque struct containing per-GPU API implementations of the
  126 + * device functions. */
  127 +struct halide_device_interface_impl_t;
  128 +
  129 +/** Each GPU API provides a halide_device_interface_t struct pointing
  130 + * to the code that manages device allocations. You can access these
  131 + * functions directly from the struct member function pointers, or by
  132 + * calling the functions declared below. Note that the global
  133 + * functions are not available when using Halide as a JIT compiler.
  134 + * If you are using raw halide_buffer_t in that context you must use
  135 + * the function pointers in the device_interface struct.
  136 + *
  137 + * The function pointers below are currently the same for every GPU
  138 + * API; only the impl field varies. These top-level functions do the
  139 + * bookkeeping that is common across all GPU APIs, and then dispatch
  140 + * to more API-specific functions via another set of function pointers
  141 + * hidden inside the impl field.
  142 + */
  143 +struct halide_device_interface_t {
  144 + int (*device_malloc)(void *user_context, struct halide_buffer_t *buf,
  145 + const struct halide_device_interface_t *device_interface);
  146 + int (*device_free)(void *user_context, struct halide_buffer_t *buf);
  147 + int (*device_sync)(void *user_context, struct halide_buffer_t *buf);
  148 + void (*device_release)(void *user_context,
  149 + const struct halide_device_interface_t *device_interface);
  150 + int (*copy_to_host)(void *user_context, struct halide_buffer_t *buf);
  151 + int (*copy_to_device)(void *user_context, struct halide_buffer_t *buf,
  152 + const struct halide_device_interface_t *device_interface);
  153 + int (*device_and_host_malloc)(void *user_context, struct halide_buffer_t *buf,
  154 + const struct halide_device_interface_t *device_interface);
  155 + int (*device_and_host_free)(void *user_context, struct halide_buffer_t *buf);
  156 + int (*buffer_copy)(void *user_context, struct halide_buffer_t *src,
  157 + const struct halide_device_interface_t *dst_device_interface, struct halide_buffer_t *dst);
  158 + int (*device_crop)(void *user_context, const struct halide_buffer_t *src,
  159 + struct halide_buffer_t *dst);
  160 + int (*device_release_crop)(void *user_context, struct halide_buffer_t *buf);
  161 + int (*wrap_native)(void *user_context, struct halide_buffer_t *buf, uint64_t handle,
  162 + const struct halide_device_interface_t *device_interface);
  163 + int (*detach_native)(void *user_context, struct halide_buffer_t *buf);
  164 + const struct halide_device_interface_impl_t *impl;
  165 +};
  166 +
  167 +typedef struct halide_dimension_t {
  168 + int32_t min, extent, stride;
  169 +
  170 + // Per-dimension flags. None are defined yet (This is reserved for future use).
  171 + uint32_t flags;
  172 +
  173 +#ifdef __cplusplus
  174 + HALIDE_ALWAYS_INLINE halide_dimension_t() : min(0), extent(0), stride(0), flags(0) {}
  175 + HALIDE_ALWAYS_INLINE halide_dimension_t(int32_t m, int32_t e, int32_t s, uint32_t f = 0) :
  176 + min(m), extent(e), stride(s), flags(f) {}
  177 +
  178 + HALIDE_ALWAYS_INLINE bool operator==(const halide_dimension_t &other) const {
  179 + return (min == other.min) &&
  180 + (extent == other.extent) &&
  181 + (stride == other.stride) &&
  182 + (flags == other.flags);
  183 + }
  184 +
  185 + HALIDE_ALWAYS_INLINE bool operator!=(const halide_dimension_t &other) const {
  186 + return !(*this == other);
  187 + }
  188 +#endif
  189 +} halide_dimension_t;
  190 +
  191 +#ifdef __cplusplus
  192 +} // extern "C"
  193 +#endif
  194 +
  195 +typedef enum {halide_buffer_flag_host_dirty = 1,
  196 + halide_buffer_flag_device_dirty = 2} halide_buffer_flags;
  197 +
  198 +/**
  199 + * The raw representation of an image passed around by generated
  200 + * Halide code. It includes some stuff to track whether the image is
  201 + * not actually in main memory, but instead on a device (like a
  202 + * GPU). For a more convenient C++ wrapper, use Halide::Buffer<T>. */
  203 +typedef struct halide_buffer_t {
  204 + /** A device-handle for e.g. GPU memory used to back this buffer. */
  205 + uint64_t device;
  206 +
  207 + /** The interface used to interpret the above handle. */
  208 + const struct halide_device_interface_t *device_interface;
  209 +
  210 + /** A pointer to the start of the data in main memory. In terms of
  211 + * the Halide coordinate system, this is the address of the min
  212 + * coordinates (defined below). */
  213 + uint8_t* host;
  214 +
  215 + /** flags with various meanings. */
  216 + uint64_t flags;
  217 +
  218 + /** The type of each buffer element. */
  219 + struct halide_type_t type;
  220 +
  221 + /** The dimensionality of the buffer. */
  222 + int32_t dimensions;
  223 +
  224 + /** The shape of the buffer. Halide does not own this array - you
  225 + * must manage the memory for it yourself. */
  226 + halide_dimension_t *dim;
  227 +
  228 + /** Pads the buffer up to a multiple of 8 bytes */
  229 + void *padding;
  230 +} halide_buffer_t;
  231 +
  232 +
  233 +#ifdef __cplusplus
  234 +
  235 +namespace {
  236 +template<typename T> struct check_is_pointer;
  237 +template<typename T> struct check_is_pointer<T *> {};
  238 +}
  239 +
  240 +/** Construct the halide equivalent of a C type */
  241 +template<typename T>
  242 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of() {
  243 + // Create a compile-time error if T is not a pointer (without
  244 + // using any includes - this code goes into the runtime).
  245 + check_is_pointer<T> check;
  246 + (void)check;
  247 + return halide_type_t(halide_type_handle, 64);
  248 +}
  249 +
  250 +template<>
  251 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<float>() {
  252 + return halide_type_t(halide_type_float, 32);
  253 +}
  254 +
  255 +template<>
  256 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<double>() {
  257 + return halide_type_t(halide_type_float, 64);
  258 +}
  259 +
  260 +template<>
  261 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<bool>() {
  262 + return halide_type_t(halide_type_uint, 1);
  263 +}
  264 +
  265 +template<>
  266 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<uint8_t>() {
  267 + return halide_type_t(halide_type_uint, 8);
  268 +}
  269 +
  270 +template<>
  271 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<uint16_t>() {
  272 + return halide_type_t(halide_type_uint, 16);
  273 +}
  274 +
  275 +template<>
  276 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<uint32_t>() {
  277 + return halide_type_t(halide_type_uint, 32);
  278 +}
  279 +
  280 +template<>
  281 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<uint64_t>() {
  282 + return halide_type_t(halide_type_uint, 64);
  283 +}
  284 +
  285 +template<>
  286 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<int8_t>() {
  287 + return halide_type_t(halide_type_int, 8);
  288 +}
  289 +
  290 +template<>
  291 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<int16_t>() {
  292 + return halide_type_t(halide_type_int, 16);
  293 +}
  294 +
  295 +template<>
  296 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<int32_t>() {
  297 + return halide_type_t(halide_type_int, 32);
  298 +}
  299 +
  300 +template<>
  301 +HALIDE_ALWAYS_INLINE halide_type_t halide_type_of<int64_t>() {
  302 + return halide_type_t(halide_type_int, 64);
  303 +}
  304 +
  305 +#endif
  306 +
  307 +#endif // HALIDE_HALIDERUNTIME_H
  1 +//
  2 +// ImageProcess.hpp
  3 +// MNN
  4 +//
  5 +// Created by MNN on 2018/09/19.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +
  9 +#ifndef ImageProcess_hpp
  10 +#define ImageProcess_hpp
  11 +
  12 +#include <MNN/ErrorCode.hpp>
  13 +#include <MNN/Matrix.h>
  14 +#include <MNN/Tensor.hpp>
  15 +
  16 +namespace MNN {
  17 +namespace CV {
  18 +enum ImageFormat {
  19 + RGBA = 0,
  20 + RGB,
  21 + BGR,
  22 + GRAY,
  23 + BGRA,
  24 + YUV_NV21 = 11,
  25 + YUV_NV12 = 12,
  26 + YUV_I420 = 13,
  27 +};
  28 +
  29 +enum Filter { NEAREST = 0, BILINEAR = 1, BICUBIC = 2 };
  30 +
  31 +enum Wrap { CLAMP_TO_EDGE = 0, ZERO = 1, REPEAT = 2 };
  32 +
  33 +/**
  34 + * handle image process for tensor.
  35 + * step:
  36 + * 1: Do transform compute and get points
  37 + * 2: Sample line and do format convert
  38 + * 3: Turn RGBA to float tensor, and do sub and normalize
  39 + */
  40 +class MNN_PUBLIC ImageProcess {
  41 +public:
  42 + struct Inside;
  43 + struct Config {
  44 + /** data filter */
  45 + Filter filterType = NEAREST;
  46 + /** format of source data */
  47 + ImageFormat sourceFormat = RGBA;
  48 + /** format of destination data */
  49 + ImageFormat destFormat = RGBA;
  50 +
  51 + // Only valid if the dest type is float
  52 + float mean[4] = {0.0f, 0.0f, 0.0f, 0.0f};
  53 + float normal[4] = {1.0f, 1.0f, 1.0f, 1.0f};
  54 +
  55 + /** edge wrapper */
  56 + Wrap wrap = CLAMP_TO_EDGE;
  57 + };
  58 +
  59 +public:
  60 + /**
  61 + * @brief create image process with given config for given tensor.
  62 + * @param config given config.
  63 + * @param dstTensor given tensor.
  64 + * @return image processor.
  65 + */
  66 + static ImageProcess* create(const Config& config, const Tensor* dstTensor = nullptr);
  67 +
  68 + /**
  69 + * @brief create image process with given config for given tensor.
  70 + * @param means given means
  71 + * @param meanCount given means count
  72 + * @param normals given normals
  73 + * @param normalCount given normal count
  74 + * @param sourceFormat format of source data
  75 + * @param destFormat format of destination data
  76 + * @param dstTensor given tensor.
  77 + * @return image processor.
  78 + */
  79 + static ImageProcess* create(const ImageFormat sourceFormat = RGBA, const ImageFormat destFormat = RGBA,
  80 + const float* means = nullptr, const int meanCount = 0, const float* normals = nullptr,
  81 + const int normalCount = 0, const Tensor* dstTensor = nullptr);
  82 +
  83 + ~ImageProcess();
  84 +
  85 + /**
  86 + * @brief get affine transform matrix.
  87 + * @return affine transform matrix.
  88 + */
  89 + inline const Matrix& matrix() const {
  90 + return mTransform;
  91 + }
  92 + void setMatrix(const Matrix& matrix);
  93 +
  94 + /**
  95 + * @brief convert source data to given tensor.
  96 + * @param source source data.
  97 + * @param iw source width.
  98 + * @param ih source height.
  99 + * @param stride number of elements per row. eg: 100 width RGB contains at least 300 elements.
  100 + * @param dest given tensor.
  101 + * @return result code.
  102 + */
  103 + ErrorCode convert(const uint8_t* source, int iw, int ih, int stride, Tensor* dest);
  104 +
  105 + /**
  106 + * @brief convert source data to given tensor.
  107 + * @param source source data.
  108 + * @param iw source width.
  109 + * @param ih source height.
  110 + * @param stride number of elements per row. eg: 100 width RGB contains at least 300 elements.
  111 + * @param dest dest data.
  112 + * @param ow output width.
  113 + * @param oh output height.
  114 + * @param outputBpp output bpp, if 0, set as the save and config.destFormat.
  115 + * @param outputStride output stride, if 0, set as ow * outputBpp.
  116 + * @param type Only support halide_type_of<uint8_t> and halide_type_of<float>.
  117 + * @return result code.
  118 + */
  119 + ErrorCode convert(const uint8_t* source, int iw, int ih, int stride, void* dest, int ow, int oh, int outputBpp = 0,
  120 + int outputStride = 0, halide_type_t type = halide_type_of<float>());
  121 +
  122 + /**
  123 + * @brief create tensor with given data.
  124 + * @param w image width.
  125 + * @param h image height.
  126 + * @param bpp bytes per pixel.
  127 + * @param p pixel data pointer.
  128 + * @return created tensor.
  129 + */
  130 + template <typename T>
  131 + static Tensor* createImageTensor(int w, int h, int bpp, void* p = nullptr) {
  132 + return createImageTensor(halide_type_of<T>(), w, h, bpp, p);
  133 + }
  134 + static Tensor* createImageTensor(halide_type_t type, int w, int h, int bpp, void* p = nullptr);
  135 +
  136 + /**
  137 + * @brief set padding value when wrap=ZERO.
  138 + * @param value padding value.
  139 + * @return void.
  140 + */
  141 + void setPadding(uint8_t value) {
  142 + mPaddingValue = value;
  143 + }
  144 +private:
  145 + ImageProcess(const Config& config);
  146 + Matrix mTransform;
  147 + Matrix mTransformInvert;
  148 + Inside* mInside;
  149 + uint8_t mPaddingValue = 0;
  150 +};
  151 +} // namespace CV
  152 +} // namespace MNN
  153 +
  154 +#endif /* ImageProcess_hpp */
  1 +//
  2 +// Interpreter.hpp
  3 +// MNN
  4 +//
  5 +// Created by MNN on 2018/07/23.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +
  9 +#ifndef Interpreter_hpp
  10 +#define Interpreter_hpp
  11 +
  12 +#include <functional>
  13 +#include <map>
  14 +#include <memory>
  15 +#include <string>
  16 +#include <MNN/ErrorCode.hpp>
  17 +#include <MNN/MNNForwardType.h>
  18 +#include <MNN/Tensor.hpp>
  19 +
  20 +namespace MNN {
  21 +
  22 +/** session schedule config */
  23 +struct ScheduleConfig {
  24 + /** which tensor should be kept */
  25 + std::vector<std::string> saveTensors;
  26 + /** forward type */
  27 + MNNForwardType type = MNN_FORWARD_CPU;
  28 + /** CPU:number of threads in parallel , Or GPU: mode setting*/
  29 + union {
  30 + int numThread = 4;
  31 + int mode;
  32 + };
  33 +
  34 + /** subpath to run */
  35 + struct Path {
  36 + std::vector<std::string> inputs;
  37 + std::vector<std::string> outputs;
  38 +
  39 + enum Mode {
  40 + /**
  41 + * Op Mode
  42 + * - inputs means the source op, can NOT be empty.
  43 + * - outputs means the sink op, can be empty.
  44 + * The path will start from source op, then flow when encounter the sink op.
  45 + * The sink op will not be compute in this path.
  46 + */
  47 + Op = 0,
  48 +
  49 + /**
  50 + * Tensor Mode
  51 + * - inputs means the inputs tensors, can NOT be empty.
  52 + * - outputs means the outputs tensors, can NOT be empty.
  53 + * It will find the pipeline that compute outputs from inputs.
  54 + */
  55 + Tensor = 1
  56 + };
  57 +
  58 + /** running mode */
  59 + Mode mode = Op;
  60 + };
  61 + Path path;
  62 +
  63 + /** backup backend used to create execution when desinated backend do NOT support any op */
  64 + MNNForwardType backupType = MNN_FORWARD_CPU;
  65 +
  66 + /** extra backend config */
  67 + BackendConfig* backendConfig = nullptr;
  68 +};
  69 +
  70 +class Session;
  71 +struct Content;
  72 +class Tensor;
  73 +class Backend;
  74 +class Runtime;
  75 +
  76 +class MNN_PUBLIC OperatorInfo {
  77 + struct Info;
  78 +
  79 +public:
  80 + /** Operator's name*/
  81 + const std::string& name() const;
  82 +
  83 + /** Operator's type*/
  84 + const std::string& type() const;
  85 +
  86 + /** Operator's flops, in M*/
  87 + float flops() const;
  88 +
  89 +protected:
  90 + OperatorInfo();
  91 + ~OperatorInfo();
  92 + Info* mContent;
  93 +};
  94 +
  95 +typedef std::function<bool(const std::vector<Tensor*>&, const std::string& /*opName*/)> TensorCallBack;
  96 +typedef std::function<bool(const std::vector<Tensor*>&, const OperatorInfo*)> TensorCallBackWithInfo;
  97 +typedef std::pair<std::map<MNNForwardType, std::shared_ptr<Runtime>>, std::shared_ptr<Runtime>> RuntimeInfo;
  98 +
  99 +/** net data holder. multiple sessions could share same net. */
  100 +class MNN_PUBLIC Interpreter {
  101 +public:
  102 + /**
  103 + * @brief create net from file.
  104 + * @param file given file.
  105 + * @return created net if success, NULL otherwise.
  106 + */
  107 + static Interpreter* createFromFile(const char* file);
  108 + /**
  109 + * @brief create net from buffer.
  110 + * @param buffer given data buffer.
  111 + * @param size size of data buffer.
  112 + * @return created net if success, NULL otherwise.
  113 + */
  114 + static Interpreter* createFromBuffer(const void* buffer, size_t size);
  115 + ~Interpreter();
  116 +
  117 + enum SessionMode {
  118 + /** About CallBack, Default Session_Debug*/
  119 + /** runSessionWithCallBack is allowed and can get internal op info*/
  120 + Session_Debug = 0,
  121 + /** runSessionWithCallBack is not valid and can't get any info of op in session*/
  122 + Session_Release = 1,
  123 +
  124 + /** About input tenosr, Default Session_Input_Inside*/
  125 + /** The input tensor is alloced by session, input data after session resized*/
  126 + Session_Input_Inside = 2,
  127 + /** The input tensor is alloced by user, set input data before session resize*/
  128 + Session_Input_User = 3,
  129 + };
  130 + /**
  131 + * @brief The API shoud be called before create session.
  132 + * @param mode session mode
  133 + */
  134 + void setSessionMode(SessionMode mode);
  135 +
  136 + /**
  137 + * @brief The API shoud be called before create session.
  138 + * If the cache exist, try to load cache from file.
  139 + * After createSession, try to save cache to file.
  140 + * @param cacheFile cache file name
  141 + * @param keySize the first `keySize` bytes used as the key to check if the `cacheFile` exists.
  142 + */
  143 + void setCacheFile(const char* cacheFile, size_t keySize = 128);
  144 +
  145 + /**
  146 + * @brief The API shoud be called after last resize session.
  147 + * If resize session generate new cache info, try to rewrite cache file.
  148 + * If resize session do not generate any new cache info, just do nothing.
  149 + * @param session giveb session
  150 + * @param flag Protected param, not used now
  151 + */
  152 + ErrorCode updateCacheFile(Session *session, int flag = 0);
  153 +
  154 +public:
  155 + /**
  156 + * @brief create runtimeInfo seperately with schedule config.
  157 + * @param configs session schedule configs.
  158 + */
  159 + static RuntimeInfo createRuntime(const std::vector<ScheduleConfig>& configs);
  160 +
  161 + /**
  162 + * @brief create session with schedule config. created session will be managed in net.
  163 + * @param config session schedule config.
  164 + * @return created session if success, NULL otherwise.
  165 + */
  166 + Session* createSession(const ScheduleConfig& config);
  167 +
  168 + /**
  169 + * @brief create session with schedule config and user-specified runtime.
  170 + * @param config session schedule config, runtime runtimeInfo used by the created session.
  171 + * @return created session if success, NULL otherwise.
  172 + */
  173 + Session* createSession(const ScheduleConfig& config, const RuntimeInfo& runtime);
  174 +
  175 + /**
  176 + * @brief create multi-path session with schedule configs. created session will be managed in net.
  177 + * @param configs session schedule configs.
  178 + * @return created session if success, NULL otherwise.
  179 + */
  180 + Session* createMultiPathSession(const std::vector<ScheduleConfig>& configs);
  181 +
  182 + /**
  183 + * @brief create multi-path session with schedule configs and user-specified runtime.
  184 + created session will be managed in net.
  185 + * @param configs session schedule configs.
  186 + * @return created session if success, NULL otherwise.
  187 + */
  188 + Session* createMultiPathSession(const std::vector<ScheduleConfig>& configs, const RuntimeInfo& runtime);
  189 +
  190 + /**
  191 + * @brief release session.
  192 + * @param session given session.
  193 + * @return true if given session is held by net and is freed.
  194 + */
  195 + bool releaseSession(Session* session);
  196 +
  197 + /**
  198 + * @brief call this function to get tensors ready. output tensor buffer (host or deviceId) should be retrieved
  199 + * after resize of any input tensor.
  200 + * @param session given session.
  201 + */
  202 + void resizeSession(Session* session);
  203 +
  204 + /**
  205 + * @brief call this function if don't need resize or create session any more, it will save a few memory that equal
  206 + * to the size of model buffer
  207 + */
  208 + void releaseModel();
  209 +
  210 + /**
  211 + * @brief Get the model buffer for user to save
  212 + * @return std::make_pair(modleBuffer, modelSize).
  213 + * @example:
  214 + * std::ofstream output("trainResult.alinn")
  215 + * auto buffer = net->getModelBuffer();
  216 + * output.write((const char*)buffer.first, buffer.second);
  217 + */
  218 + std::pair<const void*, size_t> getModelBuffer() const;
  219 +
  220 + /**
  221 + * @brief update Session's Tensor to model's Const Op
  222 + * @param session given session.
  223 + * @return result of running.
  224 + */
  225 + ErrorCode updateSessionToModel(Session* session);
  226 +
  227 + /**
  228 + * @brief run session.
  229 + * @param session given session.
  230 + * @return result of running.
  231 + */
  232 + ErrorCode runSession(Session* session) const;
  233 +
  234 + /*
  235 + * @brief run session.
  236 + * @param session given session.
  237 + * @param before callback before each op. return true to run the op; return false to skip the op.
  238 + * @param after callback after each op. return true to continue running; return false to interrupt the session.
  239 + * @param sync synchronously wait for finish of execution or not.
  240 + * @return result of running.
  241 + */
  242 + ErrorCode runSessionWithCallBack(const Session* session, const TensorCallBack& before, const TensorCallBack& end,
  243 + bool sync = false) const;
  244 +
  245 + /*
  246 + * @brief run session.
  247 + * @param session given session.
  248 + * @param before callback before each op. return true to run the op; return false to skip the op.
  249 + * @param after callback after each op. return true to continue running; return false to interrupt the session.
  250 + * @param sync synchronously wait for finish of execution or not.
  251 + * @return result of running.
  252 + */
  253 + ErrorCode runSessionWithCallBackInfo(const Session* session, const TensorCallBackWithInfo& before,
  254 + const TensorCallBackWithInfo& end, bool sync = false) const;
  255 +
  256 + /**
  257 + * @brief get input tensor for given name.
  258 + * @param session given session.
  259 + * @param name given name. if NULL, return first input.
  260 + * @return tensor if found, NULL otherwise.
  261 + */
  262 + Tensor* getSessionInput(const Session* session, const char* name);
  263 + /**
  264 + * @brief get output tensor for given name.
  265 + * @param session given session.
  266 + * @param name given name. if NULL, return first output.
  267 + * @return tensor if found, NULL otherwise.
  268 + */
  269 + Tensor* getSessionOutput(const Session* session, const char* name);
  270 +
  271 + enum SessionInfoCode {
  272 + /** memory session used in MB, float* */
  273 + MEMORY = 0,
  274 +
  275 + /** float operation needed in session in M, float* */
  276 + FLOPS = 1,
  277 +
  278 + /** Backends in session in M, int*, length >= 1 + number of configs when create session */
  279 + BACKENDS = 2,
  280 +
  281 + ALL
  282 + };
  283 +
  284 + /**
  285 + * @brief get session info
  286 + * @param session given session.
  287 + * @param code given info code.
  288 + * @param ptr given info ptr, see SessionInfoCode for detail
  289 + * @return true if support the code, false otherwise.
  290 + */
  291 + bool getSessionInfo(const Session* session, SessionInfoCode code, void* ptr);
  292 +
  293 + /**
  294 + * @brief get all output tensors.
  295 + * @param session given session.
  296 + * @return all output tensors mapped with name.
  297 + */
  298 + const std::map<std::string, Tensor*>& getSessionOutputAll(const Session* session) const;
  299 + /**
  300 + * @brief get all input tensors.
  301 + * @param session given session.
  302 + * @return all input tensors mapped with name.
  303 + */
  304 + const std::map<std::string, Tensor*>& getSessionInputAll(const Session* session) const;
  305 +
  306 +public:
  307 + /**
  308 + * @brief resize given tensor.
  309 + * @param tensor given tensor.
  310 + * @param dims new dims. at most 6 dims.
  311 + */
  312 + void resizeTensor(Tensor* tensor, const std::vector<int>& dims);
  313 +
  314 + /**
  315 + * @brief resize given tensor by nchw.
  316 + * @param batch / N.
  317 + * @param channel / C.
  318 + * @param height / H.
  319 + * @param width / W
  320 + */
  321 + void resizeTensor(Tensor* tensor, int batch, int channel, int height, int width);
  322 +
  323 + /**
  324 + * @brief get backend used to create given tensor.
  325 + * @param session given session.
  326 + * @param tensor given tensor.
  327 + * @return backend used to create given tensor, may be NULL.
  328 + */
  329 + const Backend* getBackend(const Session* session, const Tensor* tensor) const;
  330 +
  331 + /**
  332 + * @brief get business code (model identifier).
  333 + * @return business code.
  334 + */
  335 + const char* bizCode() const;
  336 +
  337 +private:
  338 + static Interpreter* createFromBufferInternal(Content* net);
  339 +
  340 + Content* mNet = nullptr;
  341 + Interpreter(Content* net);
  342 +
  343 + Interpreter(const Interpreter&) = delete;
  344 + Interpreter(const Interpreter&&) = delete;
  345 + Interpreter& operator=(const Interpreter&) = delete;
  346 + Interpreter& operator=(const Interpreter&&) = delete;
  347 +};
  348 +} // namespace MNN
  349 +
  350 +#endif /* Interpreter_hpp */
  1 +//
  2 +// MNNDefine.h
  3 +// MNN
  4 +//
  5 +// Created by MNN on 2018/08/09.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +
  9 +#ifndef MNNDefine_h
  10 +#define MNNDefine_h
  11 +
  12 +#include <assert.h>
  13 +#include <stdio.h>
  14 +
  15 +#if defined(__APPLE__)
  16 +#include <TargetConditionals.h>
  17 +#if TARGET_OS_IPHONE
  18 +#define MNN_BUILD_FOR_IOS
  19 +#endif
  20 +#endif
  21 +
  22 +#ifdef MNN_USE_LOGCAT
  23 +#include <android/log.h>
  24 +#define MNN_ERROR(format, ...) __android_log_print(ANDROID_LOG_ERROR, "MNNJNI", format, ##__VA_ARGS__)
  25 +#define MNN_PRINT(format, ...) __android_log_print(ANDROID_LOG_INFO, "MNNJNI", format, ##__VA_ARGS__)
  26 +#else
  27 +#define MNN_PRINT(format, ...) printf(format, ##__VA_ARGS__)
  28 +#define MNN_ERROR(format, ...) printf(format, ##__VA_ARGS__)
  29 +#endif
  30 +
  31 +#ifdef DEBUG
  32 +#define MNN_ASSERT(x) \
  33 + { \
  34 + int res = (x); \
  35 + if (!res) { \
  36 + MNN_ERROR("Error for %s, %d\n", __FILE__, __LINE__); \
  37 + assert(res); \
  38 + } \
  39 + }
  40 +#else
  41 +#define MNN_ASSERT(x)
  42 +#endif
  43 +
  44 +#define FUNC_PRINT(x) MNN_PRINT(#x "=%d in %s, %d \n", x, __func__, __LINE__);
  45 +#define FUNC_PRINT_ALL(x, type) MNN_PRINT(#x "=" #type " %" #type " in %s, %d \n", x, __func__, __LINE__);
  46 +
  47 +#define MNN_CHECK(success, log) \
  48 +if(!(success)){ \
  49 +MNN_ERROR("Check failed: %s ==> %s\n", #success, #log); \
  50 +}
  51 +
  52 +#if defined(_MSC_VER)
  53 +#if defined(BUILDING_MNN_DLL)
  54 +#define MNN_PUBLIC __declspec(dllexport)
  55 +#elif defined(USING_MNN_DLL)
  56 +#define MNN_PUBLIC __declspec(dllimport)
  57 +#else
  58 +#define MNN_PUBLIC
  59 +#endif
  60 +#else
  61 +#define MNN_PUBLIC __attribute__((visibility("default")))
  62 +#endif
  63 +
  64 +#endif /* MNNDefine_h */
  1 +//
  2 +// MNNForwardType.h
  3 +// MNN
  4 +//
  5 +// Created by MNN on 2019/01/19.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +
  9 +#ifndef MNNForwardType_h
  10 +#define MNNForwardType_h
  11 +#include <stdint.h>
  12 +#include <stddef.h>
  13 +
  14 +typedef enum {
  15 + MNN_FORWARD_CPU = 0,
  16 +
  17 + /*
  18 + Firtly find the first available backends not equal to CPU
  19 + If no other backends, use cpu
  20 + */
  21 + MNN_FORWARD_AUTO = 4,
  22 +
  23 + /*Hand write metal*/
  24 + MNN_FORWARD_METAL = 1,
  25 +
  26 + /*NVIDIA GPU API*/
  27 + MNN_FORWARD_CUDA = 2,
  28 +
  29 + /*Android / Common Device GPU API*/
  30 + MNN_FORWARD_OPENCL = 3,
  31 + MNN_FORWARD_OPENGL = 6,
  32 + MNN_FORWARD_VULKAN = 7,
  33 +
  34 + /*Android 8.1's NNAPI, Not Support yet. CoreML Now*/
  35 + MNN_FORWARD_NN = 5,
  36 +
  37 + /*User can use API from Backend.hpp to add or search Backend*/
  38 + MNN_FORWARD_USER_0 = 8,
  39 + MNN_FORWARD_USER_1 = 9,
  40 + MNN_FORWARD_USER_2 = 10,
  41 + MNN_FORWARD_USER_3 = 11,
  42 +
  43 + MNN_FORWARD_ALL,
  44 +
  45 + /* Apply arm extension instruction set to accelerate some Ops, this forward type
  46 + is only used in MNN internal, and will be active automatically when user set forward type
  47 + to be MNN_FORWARD_CPU and extension instruction set is valid on hardware.
  48 + */
  49 + MNN_FORWARD_CPU_EXTENSION
  50 +
  51 +} MNNForwardType;
  52 +
  53 +typedef enum {
  54 + // choose one tuning mode Only
  55 + MNN_GPU_TUNING_NONE = 1 << 0,/* Forbidden tuning, performance not good */
  56 + MNN_GPU_TUNING_HEAVY = 1 << 1,/* heavily tuning, usually not suggested */
  57 + MNN_GPU_TUNING_WIDE = 1 << 2,/* widely tuning, performance good. Default */
  58 + MNN_GPU_TUNING_NORMAL = 1 << 3,/* normal tuning, performance may be ok */
  59 + MNN_GPU_TUNING_FAST = 1 << 4,/* fast tuning, performance may not good */
  60 +
  61 + // choose one opencl memory mode Only
  62 + /* User can try OpenCL_MEMORY_BUFFER and OpenCL_MEMORY_IMAGE both,
  63 + then choose the better one according to performance*/
  64 + MNN_GPU_MEMORY_BUFFER = 1 << 6,/* User assign mode */
  65 + MNN_GPU_MEMORY_IMAGE = 1 << 7,/* User assign mode */
  66 +} MNNGpuMode;
  67 +
  68 +#ifdef __cplusplus
  69 +namespace MNN {
  70 +struct BackendConfig {
  71 + enum MemoryMode { Memory_Normal = 0, Memory_High, Memory_Low };
  72 +
  73 + MemoryMode memory = Memory_Normal;
  74 +
  75 + enum PowerMode { Power_Normal = 0, Power_High, Power_Low };
  76 +
  77 + PowerMode power = Power_Normal;
  78 +
  79 + enum PrecisionMode { Precision_Normal = 0, Precision_High, Precision_Low };
  80 +
  81 + PrecisionMode precision = Precision_Normal;
  82 +
  83 + /** user defined context */
  84 + union {
  85 + void* sharedContext = nullptr;
  86 + size_t flags; // Valid for CPU Backend
  87 + };
  88 +};
  89 +}; // namespace MNN
  90 +#endif
  91 +#endif /* MNNForwardType_h */
  1 +//
  2 +// MNNSharedContext.h
  3 +// MNN
  4 +//
  5 +// Created by MNN on 2018/10/11.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +
  9 +#ifndef MNNSharedContext_h
  10 +#define MNNSharedContext_h
  11 +#ifdef __cplusplus
  12 +extern "C" {
  13 +#endif
  14 +
  15 +#include <stdint.h> /*uint32_t*/
  16 +
  17 +#ifndef VK_DEFINE_HANDLE
  18 +#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
  19 +VK_DEFINE_HANDLE(VkInstance)
  20 +VK_DEFINE_HANDLE(VkPhysicalDevice)
  21 +VK_DEFINE_HANDLE(VkDevice)
  22 +VK_DEFINE_HANDLE(VkQueue)
  23 +#endif
  24 +struct MNNVulkanContext {
  25 + VkInstance pInstance;
  26 + VkPhysicalDevice pPhysicalDevice;
  27 + VkDevice pDevice;
  28 + VkQueue pQueue;
  29 + uint32_t iQueueFamilyIndex;
  30 +};
  31 +#ifdef __cplusplus
  32 +}
  33 +#endif
  34 +
  35 +#endif /* MNNSharedContext_h */
  1 +/*
  2 + * Copyright 2006 The Android Open Source Project
  3 + *
  4 + * Use of this source code is governed by a BSD-style license that can be
  5 + * found in the LICENSE file.
  6 + */
  7 +
  8 +/* Generated by tools/bookmaker from include/core/Matrix.h and docs/SkMatrix_Reference.bmh
  9 + on 2018-07-13 08:15:11. Additional documentation and examples can be found at:
  10 + https://skia.org/user/api/SkMatrix_Reference
  11 +
  12 + You may edit either file directly. Structural changes to public interfaces require
  13 + editing both files. After editing docs/SkMatrix_Reference.bmh, run:
  14 + bookmaker -b docs -i include/core/Matrix.h -p
  15 + to create an updated version of this file.
  16 + */
  17 +
  18 +
  19 +//
  20 +// Modified by jiangxiaotang on 2018/09/19.
  21 +// Copyright © 2018, Alibaba Group Holding Limited
  22 +//
  23 +
  24 +#ifndef SkMatrix_DEFINED
  25 +#define SkMatrix_DEFINED
  26 +
  27 +#include <string.h>
  28 +#include <cstdint>
  29 +#include <MNN/Rect.h>
  30 +
  31 +namespace MNN {
  32 +namespace CV {
  33 +
  34 +/** \class Matrix
  35 + Matrix holds a 3x3 matrix for transforming coordinates. This allows mapping
  36 + Point and vectors with translation, scaling, skewing, rotation, and
  37 + perspective.
  38 +
  39 + Matrix elements are in row major order. Matrix does not have a constructor,
  40 + so it must be explicitly initialized. setIdentity() initializes Matrix
  41 + so it has no effect. setTranslate(), setScale(), setSkew(), setRotate(), set9 and setAll()
  42 + initializes all Matrix elements with the corresponding mapping.
  43 +
  44 + Matrix includes a hidden variable that classifies the type of matrix to
  45 + improve performance. Matrix is not thread safe unless getType() is called first.
  46 +*/
  47 +
  48 +class MNN_PUBLIC Matrix {
  49 +public:
  50 + Matrix() {
  51 + setIdentity();
  52 + }
  53 +
  54 + /** Sets Matrix to scale by (sx, sy). Returned matrix is:
  55 +
  56 + | sx 0 0 |
  57 + | 0 sy 0 |
  58 + | 0 0 1 |
  59 +
  60 + @param sx horizontal scale factor
  61 + @param sy vertical scale factor
  62 + @return Matrix with scale
  63 + */
  64 + static Matrix MakeScale(float sx, float sy) {
  65 + Matrix m;
  66 + m.setScale(sx, sy);
  67 + return m;
  68 + }
  69 +
  70 + /** Sets Matrix to scale by (scale, scale). Returned matrix is:
  71 +
  72 + | scale 0 0 |
  73 + | 0 scale 0 |
  74 + | 0 0 1 |
  75 +
  76 + @param scale horizontal and vertical scale factor
  77 + @return Matrix with scale
  78 + */
  79 + static Matrix MakeScale(float scale) {
  80 + Matrix m;
  81 + m.setScale(scale, scale);
  82 + return m;
  83 + }
  84 +
  85 + /** Sets Matrix to translate by (dx, dy). Returned matrix is:
  86 +
  87 + | 1 0 dx |
  88 + | 0 1 dy |
  89 + | 0 0 1 |
  90 +
  91 + @param dx horizontal translation
  92 + @param dy vertical translation
  93 + @return Matrix with translation
  94 + */
  95 + static Matrix MakeTrans(float dx, float dy) {
  96 + Matrix m;
  97 + m.setTranslate(dx, dy);
  98 + return m;
  99 + }
  100 +
  101 + /** Sets Matrix to:
  102 +
  103 + | scaleX skewX transX |
  104 + | skewY scaleY transY |
  105 + | pers0 pers1 pers2 |
  106 +
  107 + @param scaleX horizontal scale factor
  108 + @param skewX horizontal skew factor
  109 + @param transX horizontal translation
  110 + @param skewY vertical skew factor
  111 + @param scaleY vertical scale factor
  112 + @param transY vertical translation
  113 + @param pers0 input x-axis perspective factor
  114 + @param pers1 input y-axis perspective factor
  115 + @param pers2 perspective scale factor
  116 + @return Matrix constructed from parameters
  117 + */
  118 + static Matrix MakeAll(float scaleX, float skewX, float transX, float skewY, float scaleY, float transY, float pers0,
  119 + float pers1, float pers2) {
  120 + Matrix m;
  121 + m.setAll(scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2);
  122 + return m;
  123 + }
  124 +
  125 + /** \enum Matrix::TypeMask
  126 + Enum of bit fields for mask returned by getType().
  127 + Used to identify the complexity of Matrix, to optimize performance.
  128 + */
  129 + enum TypeMask {
  130 + kIdentity_Mask = 0, //!< identity Matrix; all bits clear
  131 + kTranslate_Mask = 0x01, //!< translation Matrix
  132 + kScale_Mask = 0x02, //!< scale Matrix
  133 + kAffine_Mask = 0x04, //!< skew or rotate Matrix
  134 + kPerspective_Mask = 0x08, //!< perspective Matrix
  135 + };
  136 +
  137 + /** Returns a bit field describing the transformations the matrix may
  138 + perform. The bit field is computed conservatively, so it may include
  139 + false positives. For example, when kPerspective_Mask is set, all
  140 + other bits are set.
  141 +
  142 + @return kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask,
  143 + kAffine_Mask, kPerspective_Mask
  144 + */
  145 + TypeMask getType() const {
  146 + if (fTypeMask & kUnknown_Mask) {
  147 + fTypeMask = this->computeTypeMask();
  148 + }
  149 + // only return the public masks
  150 + return (TypeMask)(fTypeMask & 0xF);
  151 + }
  152 +
  153 + /** Returns true if Matrix is identity. Identity matrix is:
  154 +
  155 + | 1 0 0 |
  156 + | 0 1 0 |
  157 + | 0 0 1 |
  158 +
  159 + @return true if Matrix has no effect
  160 + */
  161 + bool isIdentity() const {
  162 + return this->getType() == 0;
  163 + }
  164 +
  165 + /** Returns true if Matrix at most scales and translates. Matrix may be identity,
  166 + contain only scale elements, only translate elements, or both. Matrix form is:
  167 +
  168 + | scale-x 0 translate-x |
  169 + | 0 scale-y translate-y |
  170 + | 0 0 1 |
  171 +
  172 + @return true if Matrix is identity; or scales, translates, or both
  173 + */
  174 + bool isScaleTranslate() const {
  175 + return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
  176 + }
  177 +
  178 + /** Returns true if Matrix is identity, or translates. Matrix form is:
  179 +
  180 + | 1 0 translate-x |
  181 + | 0 1 translate-y |
  182 + | 0 0 1 |
  183 +
  184 + @return true if Matrix is identity, or translates
  185 + */
  186 + bool isTranslate() const {
  187 + return !(this->getType() & ~(kTranslate_Mask));
  188 + }
  189 +
  190 + /** Returns true Matrix maps Rect to another Rect. If true, Matrix is identity,
  191 + or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all
  192 + cases, Matrix may also have translation. Matrix form is either:
  193 +
  194 + | scale-x 0 translate-x |
  195 + | 0 scale-y translate-y |
  196 + | 0 0 1 |
  197 +
  198 + or
  199 +
  200 + | 0 rotate-x translate-x |
  201 + | rotate-y 0 translate-y |
  202 + | 0 0 1 |
  203 +
  204 + for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
  205 +
  206 + Also called preservesAxisAlignment(); use the one that provides better inline
  207 + documentation.
  208 +
  209 + @return true if Matrix maps one Rect into another
  210 + */
  211 + bool rectStaysRect() const {
  212 + if (fTypeMask & kUnknown_Mask) {
  213 + fTypeMask = this->computeTypeMask();
  214 + }
  215 + return (fTypeMask & kRectStaysRect_Mask) != 0;
  216 + }
  217 +
  218 + /** Returns true Matrix maps Rect to another Rect. If true, Matrix is identity,
  219 + or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all
  220 + cases, Matrix may also have translation. Matrix form is either:
  221 +
  222 + | scale-x 0 translate-x |
  223 + | 0 scale-y translate-y |
  224 + | 0 0 1 |
  225 +
  226 + or
  227 +
  228 + | 0 rotate-x translate-x |
  229 + | rotate-y 0 translate-y |
  230 + | 0 0 1 |
  231 +
  232 + for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
  233 +
  234 + Also called rectStaysRect(); use the one that provides better inline
  235 + documentation.
  236 +
  237 + @return true if Matrix maps one Rect into another
  238 + */
  239 + bool preservesAxisAlignment() const {
  240 + return this->rectStaysRect();
  241 + }
  242 +
  243 + /** Matrix organizes its values in row order. These members correspond to
  244 + each value in Matrix.
  245 + */
  246 + static constexpr int kMScaleX = 0; //!< horizontal scale factor
  247 + static constexpr int kMSkewX = 1; //!< horizontal skew factor
  248 + static constexpr int kMTransX = 2; //!< horizontal translation
  249 + static constexpr int kMSkewY = 3; //!< vertical skew factor
  250 + static constexpr int kMScaleY = 4; //!< vertical scale factor
  251 + static constexpr int kMTransY = 5; //!< vertical translation
  252 + static constexpr int kMPersp0 = 6; //!< input x perspective factor
  253 + static constexpr int kMPersp1 = 7; //!< input y perspective factor
  254 + static constexpr int kMPersp2 = 8; //!< perspective bias
  255 +
  256 + /** Affine arrays are in column major order to match the matrix used by
  257 + PDF and XPS.
  258 + */
  259 + static constexpr int kAScaleX = 0; //!< horizontal scale factor
  260 + static constexpr int kASkewY = 1; //!< vertical skew factor
  261 + static constexpr int kASkewX = 2; //!< horizontal skew factor
  262 + static constexpr int kAScaleY = 3; //!< vertical scale factor
  263 + static constexpr int kATransX = 4; //!< horizontal translation
  264 + static constexpr int kATransY = 5; //!< vertical translation
  265 +
  266 + /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
  267 + defined.
  268 +
  269 + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
  270 + kMPersp0, kMPersp1, kMPersp2
  271 + @return value corresponding to index
  272 + */
  273 + float operator[](int index) const {
  274 + MNN_ASSERT((unsigned)index < 9);
  275 + return fMat[index];
  276 + }
  277 +
  278 + /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
  279 + defined.
  280 +
  281 + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
  282 + kMPersp0, kMPersp1, kMPersp2
  283 + @return value corresponding to index
  284 + */
  285 + float get(int index) const {
  286 + MNN_ASSERT((unsigned)index < 9);
  287 + return fMat[index];
  288 + }
  289 +
  290 + /** Returns scale factor multiplied by x-axis input, contributing to x-axis output.
  291 + With mapPoints(), scales Point along the x-axis.
  292 +
  293 + @return horizontal scale factor
  294 + */
  295 + float getScaleX() const {
  296 + return fMat[kMScaleX];
  297 + }
  298 +
  299 + /** Returns scale factor multiplied by y-axis input, contributing to y-axis output.
  300 + With mapPoints(), scales Point along the y-axis.
  301 +
  302 + @return vertical scale factor
  303 + */
  304 + float getScaleY() const {
  305 + return fMat[kMScaleY];
  306 + }
  307 +
  308 + /** Returns scale factor multiplied by x-axis input, contributing to y-axis output.
  309 + With mapPoints(), skews Point along the y-axis.
  310 + Skewing both axes can rotate Point.
  311 +
  312 + @return vertical skew factor
  313 + */
  314 + float getSkewY() const {
  315 + return fMat[kMSkewY];
  316 + }
  317 +
  318 + /** Returns scale factor multiplied by y-axis input, contributing to x-axis output.
  319 + With mapPoints(), skews Point along the x-axis.
  320 + Skewing both axes can rotate Point.
  321 +
  322 + @return horizontal scale factor
  323 + */
  324 + float getSkewX() const {
  325 + return fMat[kMSkewX];
  326 + }
  327 +
  328 + /** Returns translation contributing to x-axis output.
  329 + With mapPoints(), moves Point along the x-axis.
  330 +
  331 + @return horizontal translation factor
  332 + */
  333 + float getTranslateX() const {
  334 + return fMat[kMTransX];
  335 + }
  336 +
  337 + /** Returns translation contributing to y-axis output.
  338 + With mapPoints(), moves Point along the y-axis.
  339 +
  340 + @return vertical translation factor
  341 + */
  342 + float getTranslateY() const {
  343 + return fMat[kMTransY];
  344 + }
  345 +
  346 + /** Returns factor scaling input x-axis relative to input y-axis.
  347 +
  348 + @return input x-axis perspective factor
  349 + */
  350 + float getPerspX() const {
  351 + return fMat[kMPersp0];
  352 + }
  353 +
  354 + /** Returns factor scaling input y-axis relative to input x-axis.
  355 +
  356 + @return input y-axis perspective factor
  357 + */
  358 + float getPerspY() const {
  359 + return fMat[kMPersp1];
  360 + }
  361 +
  362 + /** Returns writable Matrix value. Asserts if index is out of range and SK_DEBUG is
  363 + defined. Clears internal cache anticipating that caller will change Matrix value.
  364 +
  365 + Next call to read Matrix state may recompute cache; subsequent writes to Matrix
  366 + value must be followed by dirtyMatrixTypeCache().
  367 +
  368 + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
  369 + kMPersp0, kMPersp1, kMPersp2
  370 + @return writable value corresponding to index
  371 + */
  372 + float& operator[](int index) {
  373 + MNN_ASSERT((unsigned)index < 9);
  374 + this->setTypeMask(kUnknown_Mask);
  375 + return fMat[index];
  376 + }
  377 +
  378 + /** Sets Matrix value. Asserts if index is out of range and SK_DEBUG is
  379 + defined. Safer than operator[]; internal cache is always maintained.
  380 +
  381 + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
  382 + kMPersp0, kMPersp1, kMPersp2
  383 + @param value scalar to store in Matrix
  384 + */
  385 + void set(int index, float value) {
  386 + MNN_ASSERT((unsigned)index < 9);
  387 + fMat[index] = value;
  388 + this->setTypeMask(kUnknown_Mask);
  389 + }
  390 +
  391 + /** Sets horizontal scale factor.
  392 +
  393 + @param v horizontal scale factor to store
  394 + */
  395 + void setScaleX(float v) {
  396 + this->set(kMScaleX, v);
  397 + }
  398 +
  399 + /** Sets vertical scale factor.
  400 +
  401 + @param v vertical scale factor to store
  402 + */
  403 + void setScaleY(float v) {
  404 + this->set(kMScaleY, v);
  405 + }
  406 +
  407 + /** Sets vertical skew factor.
  408 +
  409 + @param v vertical skew factor to store
  410 + */
  411 + void setSkewY(float v) {
  412 + this->set(kMSkewY, v);
  413 + }
  414 +
  415 + /** Sets horizontal skew factor.
  416 +
  417 + @param v horizontal skew factor to store
  418 + */
  419 + void setSkewX(float v) {
  420 + this->set(kMSkewX, v);
  421 + }
  422 +
  423 + /** Sets horizontal translation.
  424 +
  425 + @param v horizontal translation to store
  426 + */
  427 + void setTranslateX(float v) {
  428 + this->set(kMTransX, v);
  429 + }
  430 +
  431 + /** Sets vertical translation.
  432 +
  433 + @param v vertical translation to store
  434 + */
  435 + void setTranslateY(float v) {
  436 + this->set(kMTransY, v);
  437 + }
  438 +
  439 + /** Sets input x-axis perspective factor, which causes mapXY() to vary input x-axis values
  440 + inversely proportional to input y-axis values.
  441 +
  442 + @param v perspective factor
  443 + */
  444 + void setPerspX(float v) {
  445 + this->set(kMPersp0, v);
  446 + }
  447 +
  448 + /** Sets input y-axis perspective factor, which causes mapXY() to vary input y-axis values
  449 + inversely proportional to input x-axis values.
  450 +
  451 + @param v perspective factor
  452 + */
  453 + void setPerspY(float v) {
  454 + this->set(kMPersp1, v);
  455 + }
  456 +
  457 + /** Sets all values from parameters. Sets matrix to:
  458 +
  459 + | scaleX skewX transX |
  460 + | skewY scaleY transY |
  461 + | persp0 persp1 persp2 |
  462 +
  463 + @param scaleX horizontal scale factor to store
  464 + @param skewX horizontal skew factor to store
  465 + @param transX horizontal translation to store
  466 + @param skewY vertical skew factor to store
  467 + @param scaleY vertical scale factor to store
  468 + @param transY vertical translation to store
  469 + @param persp0 input x-axis values perspective factor to store
  470 + @param persp1 input y-axis values perspective factor to store
  471 + @param persp2 perspective scale factor to store
  472 + */
  473 + void setAll(float scaleX, float skewX, float transX, float skewY, float scaleY, float transY, float persp0,
  474 + float persp1, float persp2) {
  475 + fMat[kMScaleX] = scaleX;
  476 + fMat[kMSkewX] = skewX;
  477 + fMat[kMTransX] = transX;
  478 + fMat[kMSkewY] = skewY;
  479 + fMat[kMScaleY] = scaleY;
  480 + fMat[kMTransY] = transY;
  481 + fMat[kMPersp0] = persp0;
  482 + fMat[kMPersp1] = persp1;
  483 + fMat[kMPersp2] = persp2;
  484 + this->setTypeMask(kUnknown_Mask);
  485 + }
  486 +
  487 + /** Copies nine scalar values contained by Matrix into buffer, in member value
  488 + ascending order: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
  489 + kMPersp0, kMPersp1, kMPersp2.
  490 +
  491 + @param buffer storage for nine scalar values
  492 + */
  493 + void get9(float buffer[9]) const {
  494 + memcpy(buffer, fMat, 9 * sizeof(float));
  495 + }
  496 +
  497 + /** Sets Matrix to nine scalar values in buffer, in member value ascending order:
  498 + kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1,
  499 + kMPersp2.
  500 +
  501 + Sets matrix to:
  502 +
  503 + | buffer[0] buffer[1] buffer[2] |
  504 + | buffer[3] buffer[4] buffer[5] |
  505 + | buffer[6] buffer[7] buffer[8] |
  506 +
  507 + In the future, set9 followed by get9 may not return the same values. Since Matrix
  508 + maps non-homogeneous coordinates, scaling all nine values produces an equivalent
  509 + transformation, possibly improving precision.
  510 +
  511 + @param buffer nine scalar values
  512 + */
  513 + void set9(const float buffer[9]);
  514 +
  515 + /** Sets Matrix to identity; which has no effect on mapped Point. Sets Matrix to:
  516 +
  517 + | 1 0 0 |
  518 + | 0 1 0 |
  519 + | 0 0 1 |
  520 +
  521 + Also called setIdentity(); use the one that provides better inline
  522 + documentation.
  523 + */
  524 + void reset();
  525 +
  526 + /** Sets Matrix to identity; which has no effect on mapped Point. Sets Matrix to:
  527 +
  528 + | 1 0 0 |
  529 + | 0 1 0 |
  530 + | 0 0 1 |
  531 +
  532 + Also called reset(); use the one that provides better inline
  533 + documentation.
  534 + */
  535 + void setIdentity() {
  536 + this->reset();
  537 + }
  538 +
  539 + /** Sets Matrix to translate by (dx, dy).
  540 +
  541 + @param dx horizontal translation
  542 + @param dy vertical translation
  543 + */
  544 + void setTranslate(float dx, float dy);
  545 +
  546 + /** Sets Matrix to scale by sx and sy, about a pivot point at (px, py).
  547 + The pivot point is unchanged when mapped with Matrix.
  548 +
  549 + @param sx horizontal scale factor
  550 + @param sy vertical scale factor
  551 + @param px pivot x
  552 + @param py pivot y
  553 + */
  554 + void setScale(float sx, float sy, float px, float py);
  555 +
  556 + /** Sets Matrix to scale by sx and sy about at pivot point at (0, 0).
  557 +
  558 + @param sx horizontal scale factor
  559 + @param sy vertical scale factor
  560 + */
  561 + void setScale(float sx, float sy);
  562 +
  563 + /** Sets Matrix to rotate by degrees about a pivot point at (px, py).
  564 + The pivot point is unchanged when mapped with Matrix.
  565 +
  566 + Positive degrees rotates clockwise.
  567 +
  568 + @param degrees angle of axes relative to upright axes
  569 + @param px pivot x
  570 + @param py pivot y
  571 + */
  572 + void setRotate(float degrees, float px, float py);
  573 +
  574 + /** Sets Matrix to rotate by degrees about a pivot point at (0, 0).
  575 + Positive degrees rotates clockwise.
  576 +
  577 + @param degrees angle of axes relative to upright axes
  578 + */
  579 + void setRotate(float degrees);
  580 +
  581 + /** Sets Matrix to rotate by sinValue and cosValue, about a pivot point at (px, py).
  582 + The pivot point is unchanged when mapped with Matrix.
  583 +
  584 + Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
  585 + Vector length specifies scale.
  586 +
  587 + @param sinValue rotation vector x-axis component
  588 + @param cosValue rotation vector y-axis component
  589 + @param px pivot x-axis
  590 + @param py pivot y-axis
  591 + */
  592 + void setSinCos(float sinValue, float cosValue, float px, float py);
  593 +
  594 + /** Sets Matrix to rotate by sinValue and cosValue, about a pivot point at (0, 0).
  595 +
  596 + Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
  597 + Vector length specifies scale.
  598 +
  599 + @param sinValue rotation vector x-axis component
  600 + @param cosValue rotation vector y-axis component
  601 + */
  602 + void setSinCos(float sinValue, float cosValue);
  603 +
  604 + /** Sets Matrix to skew by kx and ky, about a pivot point at (px, py).
  605 + The pivot point is unchanged when mapped with Matrix.
  606 +
  607 + @param kx horizontal skew factor
  608 + @param ky vertical skew factor
  609 + @param px pivot x
  610 + @param py pivot y
  611 + */
  612 + void setSkew(float kx, float ky, float px, float py);
  613 +
  614 + /** Sets Matrix to skew by kx and ky, about a pivot point at (0, 0).
  615 +
  616 + @param kx horizontal skew factor
  617 + @param ky vertical skew factor
  618 + */
  619 + void setSkew(float kx, float ky);
  620 +
  621 + /** Sets Matrix to Matrix a multiplied by Matrix b. Either a or b may be this.
  622 +
  623 + Given:
  624 +
  625 + | A B C | | J K L |
  626 + a = | D E F |, b = | M N O |
  627 + | G H I | | P Q R |
  628 +
  629 + sets Matrix to:
  630 +
  631 + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
  632 + a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
  633 + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
  634 +
  635 + @param a Matrix on left side of multiply expression
  636 + @param b Matrix on right side of multiply expression
  637 + */
  638 + void setConcat(const Matrix& a, const Matrix& b);
  639 +
  640 + /** Sets Matrix to Matrix multiplied by Matrix constructed from translation (dx, dy).
  641 + This can be thought of as moving the point to be mapped before applying Matrix.
  642 +
  643 + Given:
  644 +
  645 + | A B C | | 1 0 dx |
  646 + Matrix = | D E F |, T(dx, dy) = | 0 1 dy |
  647 + | G H I | | 0 0 1 |
  648 +
  649 + sets Matrix to:
  650 +
  651 + | A B C | | 1 0 dx | | A B A*dx+B*dy+C |
  652 + Matrix * T(dx, dy) = | D E F | | 0 1 dy | = | D E D*dx+E*dy+F |
  653 + | G H I | | 0 0 1 | | G H G*dx+H*dy+I |
  654 +
  655 + @param dx x-axis translation before applying Matrix
  656 + @param dy y-axis translation before applying Matrix
  657 + */
  658 + void preTranslate(float dx, float dy);
  659 +
  660 + /** Sets Matrix to Matrix multiplied by Matrix constructed from scaling by (sx, sy)
  661 + about pivot point (px, py).
  662 + This can be thought of as scaling about a pivot point before applying Matrix.
  663 +
  664 + Given:
  665 +
  666 + | A B C | | sx 0 dx |
  667 + Matrix = | D E F |, S(sx, sy, px, py) = | 0 sy dy |
  668 + | G H I | | 0 0 1 |
  669 +
  670 + where
  671 +
  672 + dx = px - sx * px
  673 + dy = py - sy * py
  674 +
  675 + sets Matrix to:
  676 +
  677 + | A B C | | sx 0 dx | | A*sx B*sy A*dx+B*dy+C |
  678 + Matrix * S(sx, sy, px, py) = | D E F | | 0 sy dy | = | D*sx E*sy D*dx+E*dy+F |
  679 + | G H I | | 0 0 1 | | G*sx H*sy G*dx+H*dy+I |
  680 +
  681 + @param sx horizontal scale factor
  682 + @param sy vertical scale factor
  683 + @param px pivot x
  684 + @param py pivot y
  685 + */
  686 + void preScale(float sx, float sy, float px, float py);
  687 +
  688 + /** Sets Matrix to Matrix multiplied by Matrix constructed from scaling by (sx, sy)
  689 + about pivot point (0, 0).
  690 + This can be thought of as scaling about the origin before applying Matrix.
  691 +
  692 + Given:
  693 +
  694 + | A B C | | sx 0 0 |
  695 + Matrix = | D E F |, S(sx, sy) = | 0 sy 0 |
  696 + | G H I | | 0 0 1 |
  697 +
  698 + sets Matrix to:
  699 +
  700 + | A B C | | sx 0 0 | | A*sx B*sy C |
  701 + Matrix * S(sx, sy) = | D E F | | 0 sy 0 | = | D*sx E*sy F |
  702 + | G H I | | 0 0 1 | | G*sx H*sy I |
  703 +
  704 + @param sx horizontal scale factor
  705 + @param sy vertical scale factor
  706 + */
  707 + void preScale(float sx, float sy);
  708 +
  709 + /** Sets Matrix to Matrix multiplied by Matrix constructed from rotating by degrees
  710 + about pivot point (px, py).
  711 + This can be thought of as rotating about a pivot point before applying Matrix.
  712 +
  713 + Positive degrees rotates clockwise.
  714 +
  715 + Given:
  716 +
  717 + | A B C | | c -s dx |
  718 + Matrix = | D E F |, R(degrees, px, py) = | s c dy |
  719 + | G H I | | 0 0 1 |
  720 +
  721 + where
  722 +
  723 + c = cos(degrees)
  724 + s = sin(degrees)
  725 + dx = s * py + (1 - c) * px
  726 + dy = -s * px + (1 - c) * py
  727 +
  728 + sets Matrix to:
  729 +
  730 + | A B C | | c -s dx | | Ac+Bs -As+Bc A*dx+B*dy+C |
  731 + Matrix * R(degrees, px, py) = | D E F | | s c dy | = | Dc+Es -Ds+Ec D*dx+E*dy+F |
  732 + | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc G*dx+H*dy+I |
  733 +
  734 + @param degrees angle of axes relative to upright axes
  735 + @param px pivot x
  736 + @param py pivot y
  737 + */
  738 + void preRotate(float degrees, float px, float py);
  739 +
  740 + /** Sets Matrix to Matrix multiplied by Matrix constructed from rotating by degrees
  741 + about pivot point (0, 0).
  742 + This can be thought of as rotating about the origin before applying Matrix.
  743 +
  744 + Positive degrees rotates clockwise.
  745 +
  746 + Given:
  747 +
  748 + | A B C | | c -s 0 |
  749 + Matrix = | D E F |, R(degrees, px, py) = | s c 0 |
  750 + | G H I | | 0 0 1 |
  751 +
  752 + where
  753 +
  754 + c = cos(degrees)
  755 + s = sin(degrees)
  756 +
  757 + sets Matrix to:
  758 +
  759 + | A B C | | c -s 0 | | Ac+Bs -As+Bc C |
  760 + Matrix * R(degrees, px, py) = | D E F | | s c 0 | = | Dc+Es -Ds+Ec F |
  761 + | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc I |
  762 +
  763 + @param degrees angle of axes relative to upright axes
  764 + */
  765 + void preRotate(float degrees);
  766 +
  767 + /** Sets Matrix to Matrix multiplied by Matrix constructed from skewing by (kx, ky)
  768 + about pivot point (px, py).
  769 + This can be thought of as skewing about a pivot point before applying Matrix.
  770 +
  771 + Given:
  772 +
  773 + | A B C | | 1 kx dx |
  774 + Matrix = | D E F |, K(kx, ky, px, py) = | ky 1 dy |
  775 + | G H I | | 0 0 1 |
  776 +
  777 + where
  778 +
  779 + dx = -kx * py
  780 + dy = -ky * px
  781 +
  782 + sets Matrix to:
  783 +
  784 + | A B C | | 1 kx dx | | A+B*ky A*kx+B A*dx+B*dy+C |
  785 + Matrix * K(kx, ky, px, py) = | D E F | | ky 1 dy | = | D+E*ky D*kx+E D*dx+E*dy+F |
  786 + | G H I | | 0 0 1 | | G+H*ky G*kx+H G*dx+H*dy+I |
  787 +
  788 + @param kx horizontal skew factor
  789 + @param ky vertical skew factor
  790 + @param px pivot x
  791 + @param py pivot y
  792 + */
  793 + void preSkew(float kx, float ky, float px, float py);
  794 +
  795 + /** Sets Matrix to Matrix multiplied by Matrix constructed from skewing by (kx, ky)
  796 + about pivot point (0, 0).
  797 + This can be thought of as skewing about the origin before applying Matrix.
  798 +
  799 + Given:
  800 +
  801 + | A B C | | 1 kx 0 |
  802 + Matrix = | D E F |, K(kx, ky) = | ky 1 0 |
  803 + | G H I | | 0 0 1 |
  804 +
  805 + sets Matrix to:
  806 +
  807 + | A B C | | 1 kx 0 | | A+B*ky A*kx+B C |
  808 + Matrix * K(kx, ky) = | D E F | | ky 1 0 | = | D+E*ky D*kx+E F |
  809 + | G H I | | 0 0 1 | | G+H*ky G*kx+H I |
  810 +
  811 + @param kx horizontal skew factor
  812 + @param ky vertical skew factor
  813 + */
  814 + void preSkew(float kx, float ky);
  815 +
  816 + /** Sets Matrix to Matrix multiplied by Matrix other.
  817 + This can be thought of mapping by other before applying Matrix.
  818 +
  819 + Given:
  820 +
  821 + | A B C | | J K L |
  822 + Matrix = | D E F |, other = | M N O |
  823 + | G H I | | P Q R |
  824 +
  825 + sets Matrix to:
  826 +
  827 + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
  828 + Matrix * other = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
  829 + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
  830 +
  831 + @param other Matrix on right side of multiply expression
  832 + */
  833 + void preConcat(const Matrix& other);
  834 +
  835 + /** Sets Matrix to Matrix constructed from translation (dx, dy) multiplied by Matrix.
  836 + This can be thought of as moving the point to be mapped after applying Matrix.
  837 +
  838 + Given:
  839 +
  840 + | J K L | | 1 0 dx |
  841 + Matrix = | M N O |, T(dx, dy) = | 0 1 dy |
  842 + | P Q R | | 0 0 1 |
  843 +
  844 + sets Matrix to:
  845 +
  846 + | 1 0 dx | | J K L | | J+dx*P K+dx*Q L+dx*R |
  847 + T(dx, dy) * Matrix = | 0 1 dy | | M N O | = | M+dy*P N+dy*Q O+dy*R |
  848 + | 0 0 1 | | P Q R | | P Q R |
  849 +
  850 + @param dx x-axis translation after applying Matrix
  851 + @param dy y-axis translation after applying Matrix
  852 + */
  853 + void postTranslate(float dx, float dy);
  854 +
  855 + /** Sets Matrix to Matrix constructed from scaling by (sx, sy) about pivot point
  856 + (px, py), multiplied by Matrix.
  857 + This can be thought of as scaling about a pivot point after applying Matrix.
  858 +
  859 + Given:
  860 +
  861 + | J K L | | sx 0 dx |
  862 + Matrix = | M N O |, S(sx, sy, px, py) = | 0 sy dy |
  863 + | P Q R | | 0 0 1 |
  864 +
  865 + where
  866 +
  867 + dx = px - sx * px
  868 + dy = py - sy * py
  869 +
  870 + sets Matrix to:
  871 +
  872 + | sx 0 dx | | J K L | | sx*J+dx*P sx*K+dx*Q sx*L+dx+R |
  873 + S(sx, sy, px, py) * Matrix = | 0 sy dy | | M N O | = | sy*M+dy*P sy*N+dy*Q sy*O+dy*R |
  874 + | 0 0 1 | | P Q R | | P Q R |
  875 +
  876 + @param sx horizontal scale factor
  877 + @param sy vertical scale factor
  878 + @param px pivot x
  879 + @param py pivot y
  880 + */
  881 + void postScale(float sx, float sy, float px, float py);
  882 +
  883 + /** Sets Matrix to Matrix constructed from scaling by (sx, sy) about pivot point
  884 + (0, 0), multiplied by Matrix.
  885 + This can be thought of as scaling about the origin after applying Matrix.
  886 +
  887 + Given:
  888 +
  889 + | J K L | | sx 0 0 |
  890 + Matrix = | M N O |, S(sx, sy) = | 0 sy 0 |
  891 + | P Q R | | 0 0 1 |
  892 +
  893 + sets Matrix to:
  894 +
  895 + | sx 0 0 | | J K L | | sx*J sx*K sx*L |
  896 + S(sx, sy) * Matrix = | 0 sy 0 | | M N O | = | sy*M sy*N sy*O |
  897 + | 0 0 1 | | P Q R | | P Q R |
  898 +
  899 + @param sx horizontal scale factor
  900 + @param sy vertical scale factor
  901 + */
  902 + void postScale(float sx, float sy);
  903 +
  904 + /** Sets Matrix to Matrix constructed from scaling by (1/divx, 1/divy) about pivot point (px, py), multiplied by
  905 + Matrix.
  906 +
  907 + Returns false if either divx or divy is zero.
  908 +
  909 + Given:
  910 +
  911 + | J K L | | sx 0 0 |
  912 + Matrix = | M N O |, I(divx, divy) = | 0 sy 0 |
  913 + | P Q R | | 0 0 1 |
  914 +
  915 + where
  916 +
  917 + sx = 1 / divx
  918 + sy = 1 / divy
  919 +
  920 + sets Matrix to:
  921 +
  922 + | sx 0 0 | | J K L | | sx*J sx*K sx*L |
  923 + I(divx, divy) * Matrix = | 0 sy 0 | | M N O | = | sy*M sy*N sy*O |
  924 + | 0 0 1 | | P Q R | | P Q R |
  925 +
  926 + @param divx integer divisor for inverse scale in x
  927 + @param divy integer divisor for inverse scale in y
  928 + @return true on successful scale
  929 + */
  930 + bool postIDiv(int divx, int divy);
  931 +
  932 + /** Sets Matrix to Matrix constructed from rotating by degrees about pivot point
  933 + (px, py), multiplied by Matrix.
  934 + This can be thought of as rotating about a pivot point after applying Matrix.
  935 +
  936 + Positive degrees rotates clockwise.
  937 +
  938 + Given:
  939 +
  940 + | J K L | | c -s dx |
  941 + Matrix = | M N O |, R(degrees, px, py) = | s c dy |
  942 + | P Q R | | 0 0 1 |
  943 +
  944 + where
  945 +
  946 + c = cos(degrees)
  947 + s = sin(degrees)
  948 + dx = s * py + (1 - c) * px
  949 + dy = -s * px + (1 - c) * py
  950 +
  951 + sets Matrix to:
  952 +
  953 + |c -s dx| |J K L| |cJ-sM+dx*P cK-sN+dx*Q cL-sO+dx+R|
  954 + R(degrees, px, py) * Matrix = |s c dy| |M N O| = |sJ+cM+dy*P sK+cN+dy*Q sL+cO+dy*R|
  955 + |0 0 1| |P Q R| | P Q R|
  956 +
  957 + @param degrees angle of axes relative to upright axes
  958 + @param px pivot x
  959 + @param py pivot y
  960 + */
  961 + void postRotate(float degrees, float px, float py);
  962 +
  963 + /** Sets Matrix to Matrix constructed from rotating by degrees about pivot point
  964 + (0, 0), multiplied by Matrix.
  965 + This can be thought of as rotating about the origin after applying Matrix.
  966 +
  967 + Positive degrees rotates clockwise.
  968 +
  969 + Given:
  970 +
  971 + | J K L | | c -s 0 |
  972 + Matrix = | M N O |, R(degrees, px, py) = | s c 0 |
  973 + | P Q R | | 0 0 1 |
  974 +
  975 + where
  976 +
  977 + c = cos(degrees)
  978 + s = sin(degrees)
  979 +
  980 + sets Matrix to:
  981 +
  982 + | c -s dx | | J K L | | cJ-sM cK-sN cL-sO |
  983 + R(degrees, px, py) * Matrix = | s c dy | | M N O | = | sJ+cM sK+cN sL+cO |
  984 + | 0 0 1 | | P Q R | | P Q R |
  985 +
  986 + @param degrees angle of axes relative to upright axes
  987 + */
  988 + void postRotate(float degrees);
  989 +
  990 + /** Sets Matrix to Matrix constructed from skewing by (kx, ky) about pivot point
  991 + (px, py), multiplied by Matrix.
  992 + This can be thought of as skewing about a pivot point after applying Matrix.
  993 +
  994 + Given:
  995 +
  996 + | J K L | | 1 kx dx |
  997 + Matrix = | M N O |, K(kx, ky, px, py) = | ky 1 dy |
  998 + | P Q R | | 0 0 1 |
  999 +
  1000 + where
  1001 +
  1002 + dx = -kx * py
  1003 + dy = -ky * px
  1004 +
  1005 + sets Matrix to:
  1006 +
  1007 + | 1 kx dx| |J K L| |J+kx*M+dx*P K+kx*N+dx*Q L+kx*O+dx+R|
  1008 + K(kx, ky, px, py) * Matrix = |ky 1 dy| |M N O| = |ky*J+M+dy*P ky*K+N+dy*Q ky*L+O+dy*R|
  1009 + | 0 0 1| |P Q R| | P Q R|
  1010 +
  1011 + @param kx horizontal skew factor
  1012 + @param ky vertical skew factor
  1013 + @param px pivot x
  1014 + @param py pivot y
  1015 + */
  1016 + void postSkew(float kx, float ky, float px, float py);
  1017 +
  1018 + /** Sets Matrix to Matrix constructed from skewing by (kx, ky) about pivot point
  1019 + (0, 0), multiplied by Matrix.
  1020 + This can be thought of as skewing about the origin after applying Matrix.
  1021 +
  1022 + Given:
  1023 +
  1024 + | J K L | | 1 kx 0 |
  1025 + Matrix = | M N O |, K(kx, ky) = | ky 1 0 |
  1026 + | P Q R | | 0 0 1 |
  1027 +
  1028 + sets Matrix to:
  1029 +
  1030 + | 1 kx 0 | | J K L | | J+kx*M K+kx*N L+kx*O |
  1031 + K(kx, ky) * Matrix = | ky 1 0 | | M N O | = | ky*J+M ky*K+N ky*L+O |
  1032 + | 0 0 1 | | P Q R | | P Q R |
  1033 +
  1034 + @param kx horizontal skew factor
  1035 + @param ky vertical skew factor
  1036 + */
  1037 + void postSkew(float kx, float ky);
  1038 +
  1039 + /** Sets Matrix to Matrix other multiplied by Matrix.
  1040 + This can be thought of mapping by other after applying Matrix.
  1041 +
  1042 + Given:
  1043 +
  1044 + | J K L | | A B C |
  1045 + Matrix = | M N O |, other = | D E F |
  1046 + | P Q R | | G H I |
  1047 +
  1048 + sets Matrix to:
  1049 +
  1050 + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
  1051 + other * Matrix = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
  1052 + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
  1053 +
  1054 + @param other Matrix on left side of multiply expression
  1055 + */
  1056 + void postConcat(const Matrix& other);
  1057 +
  1058 + /** \enum Matrix::ScaleToFit
  1059 + ScaleToFit describes how Matrix is constructed to map one Rect to another.
  1060 + ScaleToFit may allow Matrix to have unequal horizontal and vertical scaling,
  1061 + or may restrict Matrix to square scaling. If restricted, ScaleToFit specifies
  1062 + how Matrix maps to the side or center of the destination Rect.
  1063 + */
  1064 + enum ScaleToFit {
  1065 + kFill_ScaleToFit, //!< scales in x and y to fill destination Rect
  1066 + kStart_ScaleToFit, //!< scales and aligns to left and top
  1067 + kCenter_ScaleToFit, //!< scales and aligns to center
  1068 + kEnd_ScaleToFit, //!< scales and aligns to right and bottom
  1069 + };
  1070 +
  1071 + /** Sets Matrix to scale and translate src Rect to dst Rect. stf selects whether
  1072 + mapping completely fills dst or preserves the aspect ratio, and how to align
  1073 + src within dst. Returns false if src is empty, and sets Matrix to identity.
  1074 + Returns true if dst is empty, and sets Matrix to:
  1075 +
  1076 + | 0 0 0 |
  1077 + | 0 0 0 |
  1078 + | 0 0 1 |
  1079 +
  1080 + @param src Rect to map from
  1081 + @param dst Rect to map to
  1082 + @param stf one of: kFill_ScaleToFit, kStart_ScaleToFit,
  1083 + kCenter_ScaleToFit, kEnd_ScaleToFit
  1084 + @return true if Matrix can represent Rect mapping
  1085 + */
  1086 + bool setRectToRect(const Rect& src, const Rect& dst, ScaleToFit stf);
  1087 +
  1088 + /** Returns Matrix set to scale and translate src Rect to dst Rect. stf selects
  1089 + whether mapping completely fills dst or preserves the aspect ratio, and how to
  1090 + align src within dst. Returns the identity Matrix if src is empty. If dst is
  1091 + empty, returns Matrix set to:
  1092 +
  1093 + | 0 0 0 |
  1094 + | 0 0 0 |
  1095 + | 0 0 1 |
  1096 +
  1097 + @param src Rect to map from
  1098 + @param dst Rect to map to
  1099 + @param stf one of: kFill_ScaleToFit, kStart_ScaleToFit,
  1100 + kCenter_ScaleToFit, kEnd_ScaleToFit
  1101 + @return Matrix mapping src to dst
  1102 + */
  1103 + static Matrix MakeRectToRect(const Rect& src, const Rect& dst, ScaleToFit stf) {
  1104 + Matrix m;
  1105 + m.setRectToRect(src, dst, stf);
  1106 + return m;
  1107 + }
  1108 +
  1109 + /** Sets Matrix to map src to dst. count must be zero or greater, and four or less.
  1110 +
  1111 + If count is zero, sets Matrix to identity and returns true.
  1112 + If count is one, sets Matrix to translate and returns true.
  1113 + If count is two or more, sets Matrix to map Point if possible; returns false
  1114 + if Matrix cannot be constructed. If count is four, Matrix may include
  1115 + perspective.
  1116 +
  1117 + @param src Point to map from
  1118 + @param dst Point to map to
  1119 + @param count number of Point in src and dst
  1120 + @return true if Matrix was constructed successfully
  1121 + */
  1122 + bool setPolyToPoly(const Point src[], const Point dst[], int count);
  1123 +
  1124 + /** Sets inverse to reciprocal matrix, returning true if Matrix can be inverted.
  1125 + Geometrically, if Matrix maps from source to destination, inverse Matrix
  1126 + maps from destination to source. If Matrix can not be inverted, inverse is
  1127 + unchanged.
  1128 +
  1129 + @param inverse storage for inverted Matrix; may be nullptr
  1130 + @return true if Matrix can be inverted
  1131 + */
  1132 + bool invert(Matrix* inverse) const {
  1133 + // Allow the trivial case to be inlined.
  1134 + if (this->isIdentity()) {
  1135 + if (inverse) {
  1136 + inverse->reset();
  1137 + }
  1138 + return true;
  1139 + }
  1140 + return this->invertNonIdentity(inverse);
  1141 + }
  1142 +
  1143 + /** Fills affine with identity values in column major order.
  1144 + Sets affine to:
  1145 +
  1146 + | 1 0 0 |
  1147 + | 0 1 0 |
  1148 +
  1149 + Affine 3x2 matrices in column major order are used by OpenGL and XPS.
  1150 +
  1151 + @param affine storage for 3x2 affine matrix
  1152 + */
  1153 + static void SetAffineIdentity(float affine[6]);
  1154 +
  1155 + /** Fills affine in column major order. Sets affine to:
  1156 +
  1157 + | scale-x skew-x translate-x |
  1158 + | skew-y scale-y translate-y |
  1159 +
  1160 + If Matrix contains perspective, returns false and leaves affine unchanged.
  1161 +
  1162 + @param affine storage for 3x2 affine matrix; may be nullptr
  1163 + @return true if Matrix does not contain perspective
  1164 + */
  1165 + bool asAffine(float affine[6]) const;
  1166 +
  1167 + /** Sets Matrix to affine values, passed in column major order. Given affine,
  1168 + column, then row, as:
  1169 +
  1170 + | scale-x skew-x translate-x |
  1171 + | skew-y scale-y translate-y |
  1172 +
  1173 + Matrix is set, row, then column, to:
  1174 +
  1175 + | scale-x skew-x translate-x |
  1176 + | skew-y scale-y translate-y |
  1177 + | 0 0 1 |
  1178 +
  1179 + @param affine 3x2 affine matrix
  1180 + */
  1181 + void setAffine(const float affine[6]);
  1182 +
  1183 + /** Maps src Point array of length count to dst Point array of equal or greater
  1184 + length. Point are mapped by multiplying each Point by Matrix. Given:
  1185 +
  1186 + | A B C | | x |
  1187 + Matrix = | D E F |, pt = | y |
  1188 + | G H I | | 1 |
  1189 +
  1190 + where
  1191 +
  1192 + for (i = 0; i < count; ++i) {
  1193 + x = src[i].fX
  1194 + y = src[i].fY
  1195 + }
  1196 +
  1197 + each dst Point is computed as:
  1198 +
  1199 + |A B C| |x| Ax+By+C Dx+Ey+F
  1200 + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
  1201 + |G H I| |1| Gx+Hy+I Gx+Hy+I
  1202 +
  1203 + src and dst may point to the same storage.
  1204 +
  1205 + @param dst storage for mapped Point
  1206 + @param src Point to transform
  1207 + @param count number of Point to transform
  1208 + */
  1209 + void mapPoints(Point dst[], const Point src[], int count) const {
  1210 + MNN_ASSERT((dst && src && count > 0) || 0 == count);
  1211 + // no partial overlap
  1212 + MNN_ASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);
  1213 + this->getMapPtsProc()(*this, dst, src, count);
  1214 + }
  1215 +
  1216 + /** Maps pts Point array of length count in place. Point are mapped by multiplying
  1217 + each Point by Matrix. Given:
  1218 +
  1219 + | A B C | | x |
  1220 + Matrix = | D E F |, pt = | y |
  1221 + | G H I | | 1 |
  1222 +
  1223 + where
  1224 +
  1225 + for (i = 0; i < count; ++i) {
  1226 + x = pts[i].fX
  1227 + y = pts[i].fY
  1228 + }
  1229 +
  1230 + each resulting pts Point is computed as:
  1231 +
  1232 + |A B C| |x| Ax+By+C Dx+Ey+F
  1233 + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
  1234 + |G H I| |1| Gx+Hy+I Gx+Hy+I
  1235 +
  1236 + @param pts storage for mapped Point
  1237 + @param count number of Point to transform
  1238 + */
  1239 + void mapPoints(Point pts[], int count) const {
  1240 + this->mapPoints(pts, pts, count);
  1241 + }
  1242 +
  1243 + /** Maps Point (x, y) to result. Point is mapped by multiplying by Matrix. Given:
  1244 +
  1245 + | A B C | | x |
  1246 + Matrix = | D E F |, pt = | y |
  1247 + | G H I | | 1 |
  1248 +
  1249 + result is computed as:
  1250 +
  1251 + |A B C| |x| Ax+By+C Dx+Ey+F
  1252 + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
  1253 + |G H I| |1| Gx+Hy+I Gx+Hy+I
  1254 +
  1255 + @param x x-axis value of Point to map
  1256 + @param y y-axis value of Point to map
  1257 + @param result storage for mapped Point
  1258 + */
  1259 + void mapXY(float x, float y, Point* result) const {
  1260 + this->getMapXYProc()(*this, x, y, result);
  1261 + }
  1262 +
  1263 + /** Returns Point (x, y) multiplied by Matrix. Given:
  1264 +
  1265 + | A B C | | x |
  1266 + Matrix = | D E F |, pt = | y |
  1267 + | G H I | | 1 |
  1268 +
  1269 + result is computed as:
  1270 +
  1271 + |A B C| |x| Ax+By+C Dx+Ey+F
  1272 + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
  1273 + |G H I| |1| Gx+Hy+I Gx+Hy+I
  1274 +
  1275 + @param x x-axis value of Point to map
  1276 + @param y y-axis value of Point to map
  1277 + @return mapped Point
  1278 + */
  1279 + Point mapXY(float x, float y) const {
  1280 + Point result;
  1281 + this->getMapXYProc()(*this, x, y, &result);
  1282 + return result;
  1283 + }
  1284 +
  1285 + /** Sets dst to bounds of src corners mapped by Matrix.
  1286 + Returns true if mapped corners are dst corners.
  1287 +
  1288 + Returned value is the same as calling rectStaysRect().
  1289 +
  1290 + @param dst storage for bounds of mapped Point
  1291 + @param src Rect to map
  1292 + @return true if dst is equivalent to mapped src
  1293 + */
  1294 + bool mapRect(Rect* dst, const Rect& src) const;
  1295 +
  1296 + /** Sets rect to bounds of rect corners mapped by Matrix.
  1297 + Returns true if mapped corners are computed rect corners.
  1298 +
  1299 + Returned value is the same as calling rectStaysRect().
  1300 +
  1301 + @param rect rectangle to map, and storage for bounds of mapped corners
  1302 + @return true if result is equivalent to mapped src
  1303 + */
  1304 + bool mapRect(Rect* rect) const {
  1305 + return this->mapRect(rect, *rect);
  1306 + }
  1307 +
  1308 + /** Returns bounds of src corners mapped by Matrix.
  1309 +
  1310 + @param src rectangle to map
  1311 + @return mapped bounds
  1312 + */
  1313 + Rect mapRect(const Rect& src) const {
  1314 + Rect dst;
  1315 + (void)this->mapRect(&dst, src);
  1316 + return dst;
  1317 + }
  1318 +
  1319 + /** Sets dst to bounds of src corners mapped by Matrix. If matrix contains
  1320 + elements other than scale or translate: asserts if SK_DEBUG is defined;
  1321 + otherwise, results are undefined.
  1322 +
  1323 + @param dst storage for bounds of mapped Point
  1324 + @param src Rect to map
  1325 + */
  1326 + void mapRectScaleTranslate(Rect* dst, const Rect& src) const;
  1327 +
  1328 + /** Returns true if Matrix equals m, using an efficient comparison.
  1329 +
  1330 + Returns false when the sign of zero values is the different; when one
  1331 + matrix has positive zero value and the other has negative zero value.
  1332 +
  1333 + Returns true even when both Matrix contain NaN.
  1334 +
  1335 + NaN never equals any value, including itself. To improve performance, NaN values
  1336 + are treated as bit patterns that are equal if their bit patterns are equal.
  1337 +
  1338 + @param m Matrix to compare
  1339 + @return true if m and Matrix are represented by identical bit patterns
  1340 + */
  1341 + bool cheapEqualTo(const Matrix& m) const {
  1342 + return 0 == memcmp(fMat, m.fMat, sizeof(fMat));
  1343 + }
  1344 +
  1345 + /** Compares a and b; returns true if a and b are numerically equal. Returns true
  1346 + even if sign of zero values are different. Returns false if either Matrix
  1347 + contains NaN, even if the other Matrix also contains NaN.
  1348 +
  1349 + @param a Matrix to compare
  1350 + @param b Matrix to compare
  1351 + @return true if Matrix a and Matrix b are numerically equal
  1352 + */
  1353 + friend MNN_PUBLIC bool operator==(const Matrix& a, const Matrix& b);
  1354 +
  1355 + /** Compares a and b; returns true if a and b are not numerically equal. Returns false
  1356 + even if sign of zero values are different. Returns true if either Matrix
  1357 + contains NaN, even if the other Matrix also contains NaN.
  1358 +
  1359 + @param a Matrix to compare
  1360 + @param b Matrix to compare
  1361 + @return true if Matrix a and Matrix b are numerically not equal
  1362 + */
  1363 + friend MNN_PUBLIC bool operator!=(const Matrix& a, const Matrix& b) {
  1364 + return !(a == b);
  1365 + }
  1366 +
  1367 + /** Writes text representation of Matrix to standard output. Floating point values
  1368 + are written with limited precision; it may not be possible to reconstruct
  1369 + original Matrix from output.
  1370 + */
  1371 + void dump() const;
  1372 +
  1373 + /** Returns the minimum scaling factor of Matrix by decomposing the scaling and
  1374 + skewing elements.
  1375 + Returns -1 if scale factor overflows or Matrix contains perspective.
  1376 +
  1377 + @return minimum scale factor
  1378 + */
  1379 + float getMinScale() const;
  1380 +
  1381 + /** Returns the maximum scaling factor of Matrix by decomposing the scaling and
  1382 + skewing elements.
  1383 + Returns -1 if scale factor overflows or Matrix contains perspective.
  1384 +
  1385 + @return maximum scale factor
  1386 + */
  1387 + float getMaxScale() const;
  1388 +
  1389 + /** Sets scaleFactors[0] to the minimum scaling factor, and scaleFactors[1] to the
  1390 + maximum scaling factor. Scaling factors are computed by decomposing
  1391 + the Matrix scaling and skewing elements.
  1392 +
  1393 + Returns true if scaleFactors are found; otherwise, returns false and sets
  1394 + scaleFactors to undefined values.
  1395 +
  1396 + @param scaleFactors storage for minimum and maximum scale factors
  1397 + @return true if scale factors were computed correctly
  1398 + */
  1399 + bool getMinMaxScales(float scaleFactors[2]) const;
  1400 +
  1401 + /** Returns reference to const identity Matrix. Returned Matrix is set to:
  1402 +
  1403 + | 1 0 0 |
  1404 + | 0 1 0 |
  1405 + | 0 0 1 |
  1406 +
  1407 + @return const identity Matrix
  1408 + */
  1409 + static const Matrix& I();
  1410 +
  1411 + /** Returns reference to a const Matrix with invalid values. Returned Matrix is set
  1412 + to:
  1413 +
  1414 + | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
  1415 + | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
  1416 + | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
  1417 +
  1418 + @return const invalid Matrix
  1419 + */
  1420 + static const Matrix& InvalidMatrix();
  1421 +
  1422 + /** Returns Matrix a multiplied by Matrix b.
  1423 +
  1424 + Given:
  1425 +
  1426 + | A B C | | J K L |
  1427 + a = | D E F |, b = | M N O |
  1428 + | G H I | | P Q R |
  1429 +
  1430 + sets Matrix to:
  1431 +
  1432 + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
  1433 + a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
  1434 + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
  1435 +
  1436 + @param a Matrix on left side of multiply expression
  1437 + @param b Matrix on right side of multiply expression
  1438 + @return Matrix computed from a times b
  1439 + */
  1440 + static Matrix Concat(const Matrix& a, const Matrix& b) {
  1441 + Matrix result;
  1442 + result.setConcat(a, b);
  1443 + return result;
  1444 + }
  1445 +
  1446 + /** Sets internal cache to unknown state. Use to force update after repeated
  1447 + modifications to Matrix element reference returned by operator[](int index).
  1448 + */
  1449 + void dirtyMatrixTypeCache() {
  1450 + this->setTypeMask(kUnknown_Mask);
  1451 + }
  1452 +
  1453 + /** Initializes Matrix with scale and translate elements.
  1454 +
  1455 + | sx 0 tx |
  1456 + | 0 sy ty |
  1457 + | 0 0 1 |
  1458 +
  1459 + @param sx horizontal scale factor to store
  1460 + @param sy vertical scale factor to store
  1461 + @param tx horizontal translation to store
  1462 + @param ty vertical translation to store
  1463 + */
  1464 + void setScaleTranslate(float sx, float sy, float tx, float ty) {
  1465 + fMat[kMScaleX] = sx;
  1466 + fMat[kMSkewX] = 0;
  1467 + fMat[kMTransX] = tx;
  1468 +
  1469 + fMat[kMSkewY] = 0;
  1470 + fMat[kMScaleY] = sy;
  1471 + fMat[kMTransY] = ty;
  1472 +
  1473 + fMat[kMPersp0] = 0;
  1474 + fMat[kMPersp1] = 0;
  1475 + fMat[kMPersp2] = 1;
  1476 +
  1477 + unsigned mask = 0;
  1478 + if (sx != 1 || sy != 1) {
  1479 + mask |= kScale_Mask;
  1480 + }
  1481 + if (tx || ty) {
  1482 + mask |= kTranslate_Mask;
  1483 + }
  1484 + this->setTypeMask(mask | kRectStaysRect_Mask);
  1485 + }
  1486 +
  1487 + /** Returns true if all elements of the matrix are finite. Returns false if any
  1488 + element is infinity, or NaN.
  1489 +
  1490 + @return true if matrix has only finite elements
  1491 + */
  1492 +
  1493 +private:
  1494 + /** Set if the matrix will map a rectangle to another rectangle. This
  1495 + can be true if the matrix is scale-only, or rotates a multiple of
  1496 + 90 degrees.
  1497 +
  1498 + This bit will be set on identity matrices
  1499 + */
  1500 + static constexpr int kRectStaysRect_Mask = 0x10;
  1501 +
  1502 + /** Set if the perspective bit is valid even though the rest of
  1503 + the matrix is Unknown.
  1504 + */
  1505 + static constexpr int kOnlyPerspectiveValid_Mask = 0x40;
  1506 +
  1507 + static constexpr int kUnknown_Mask = 0x80;
  1508 +
  1509 + static constexpr int kORableMasks = kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask;
  1510 +
  1511 + static constexpr int kAllMasks =
  1512 + kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask | kRectStaysRect_Mask;
  1513 +
  1514 + float fMat[9];
  1515 + mutable uint32_t fTypeMask;
  1516 +
  1517 + static void ComputeInv(float dst[9], const float src[9], double invDet, bool isPersp);
  1518 +
  1519 + uint8_t computeTypeMask() const;
  1520 + uint8_t computePerspectiveTypeMask() const;
  1521 +
  1522 + void setTypeMask(int mask) {
  1523 + // allow kUnknown or a valid mask
  1524 + MNN_ASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
  1525 + ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask) ==
  1526 + (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
  1527 + fTypeMask = (uint8_t)(mask);
  1528 + }
  1529 +
  1530 + void orTypeMask(int mask) {
  1531 + MNN_ASSERT((mask & kORableMasks) == mask);
  1532 + fTypeMask = (uint8_t)(fTypeMask | mask);
  1533 + }
  1534 +
  1535 + void clearTypeMask(int mask) {
  1536 + // only allow a valid mask
  1537 + MNN_ASSERT((mask & kAllMasks) == mask);
  1538 + fTypeMask = fTypeMask & ~mask;
  1539 + }
  1540 +
  1541 + TypeMask getPerspectiveTypeMaskOnly() const {
  1542 + if ((fTypeMask & kUnknown_Mask) && !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
  1543 + fTypeMask = this->computePerspectiveTypeMask();
  1544 + }
  1545 + return (TypeMask)(fTypeMask & 0xF);
  1546 + }
  1547 +
  1548 + /** Returns true if we already know that the matrix is identity;
  1549 + false otherwise.
  1550 + */
  1551 + bool isTriviallyIdentity() const {
  1552 + if (fTypeMask & kUnknown_Mask) {
  1553 + return false;
  1554 + }
  1555 + return ((fTypeMask & 0xF) == 0);
  1556 + }
  1557 +
  1558 + inline void updateTranslateMask() {
  1559 + if ((fMat[kMTransX] != 0) | (fMat[kMTransY] != 0)) {
  1560 + fTypeMask |= kTranslate_Mask;
  1561 + } else {
  1562 + fTypeMask &= ~kTranslate_Mask;
  1563 + }
  1564 + }
  1565 +
  1566 + typedef void (*MapXYProc)(const Matrix& mat, float x, float y, Point* result);
  1567 +
  1568 + static MapXYProc GetMapXYProc(TypeMask mask) {
  1569 + MNN_ASSERT((mask & ~kAllMasks) == 0);
  1570 + return gMapXYProcs[mask & kAllMasks];
  1571 + }
  1572 +
  1573 + MapXYProc getMapXYProc() const {
  1574 + return GetMapXYProc(this->getType());
  1575 + }
  1576 +
  1577 + typedef void (*MapPtsProc)(const Matrix& mat, Point dst[], const Point src[], int count);
  1578 +
  1579 + static MapPtsProc GetMapPtsProc(TypeMask mask) {
  1580 + MNN_ASSERT((mask & ~kAllMasks) == 0);
  1581 + return gMapPtsProcs[mask & kAllMasks];
  1582 + }
  1583 +
  1584 + MapPtsProc getMapPtsProc() const {
  1585 + return GetMapPtsProc(this->getType());
  1586 + }
  1587 +
  1588 + bool invertNonIdentity(Matrix* inverse) const;
  1589 +
  1590 + static void Identity_xy(const Matrix&, float, float, Point*);
  1591 + static void Trans_xy(const Matrix&, float, float, Point*);
  1592 + static void Scale_xy(const Matrix&, float, float, Point*);
  1593 + static void ScaleTrans_xy(const Matrix&, float, float, Point*);
  1594 + static void Rot_xy(const Matrix&, float, float, Point*);
  1595 + static void RotTrans_xy(const Matrix&, float, float, Point*);
  1596 + static void Persp_xy(const Matrix&, float, float, Point*);
  1597 +
  1598 + static const MapXYProc gMapXYProcs[];
  1599 +
  1600 + static void Identity_pts(const Matrix&, Point[], const Point[], int);
  1601 + static void Trans_pts(const Matrix&, Point dst[], const Point[], int);
  1602 + static void Scale_pts(const Matrix&, Point dst[], const Point[], int);
  1603 + static void ScaleTrans_pts(const Matrix&, Point dst[], const Point[], int count);
  1604 + static void Persp_pts(const Matrix&, Point dst[], const Point[], int);
  1605 +
  1606 + static void Affine_vpts(const Matrix&, Point dst[], const Point[], int);
  1607 +
  1608 + static const MapPtsProc gMapPtsProcs[];
  1609 + static bool Poly2Proc(const Point srcPt[], Matrix* dst);
  1610 + static bool Poly3Proc(const Point srcPt[], Matrix* dst);
  1611 + static bool Poly4Proc(const Point srcPt[], Matrix* dst);
  1612 +};
  1613 +} // namespace CV
  1614 +} // namespace MNN
  1615 +#endif
  1 +//
  2 +// Rect.h
  3 +// MNN
  4 +//
  5 +// Modified by jiangxiaotang on 2018/09/19.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +
  9 +/*
  10 + * Copyright 2006 The Android Open Source Project
  11 + *
  12 + * Use of this source code is governed by a BSD-style license that can be
  13 + * found in the LICENSE file.
  14 + */
  15 +
  16 +/* Generated by tools/bookmaker from include/core/Rect.h and docs/SkRect_Reference.bmh
  17 + on 2018-07-13 08:15:11. Additional documentation and examples can be found at:
  18 + https://skia.org/user/api/SkRect_Reference
  19 +
  20 + You may edit either file directly. Structural changes to public interfaces require
  21 + editing both files. After editing docs/SkRect_Reference.bmh, run:
  22 + bookmaker -b docs -i include/core/Rect.h -p
  23 + to create an updated version of this file.
  24 + */
  25 +
  26 +#ifndef SkRect_DEFINED
  27 +#define SkRect_DEFINED
  28 +
  29 +#include <math.h>
  30 +#include <algorithm>
  31 +#include <utility>
  32 +#include <MNN/MNNDefine.h>
  33 +
  34 +namespace MNN {
  35 +namespace CV {
  36 +
  37 +struct Point {
  38 + float fX;
  39 + float fY;
  40 +
  41 + void set(float x, float y) {
  42 + fX = x;
  43 + fY = y;
  44 + }
  45 +};
  46 +
  47 +/** \struct Rect
  48 + Rect holds four float coordinates describing the upper and
  49 + lower bounds of a rectangle. Rect may be created from outer bounds or
  50 + from position, width, and height. Rect describes an area; if its right
  51 + is less than or equal to its left, or if its bottom is less than or equal to
  52 + its top, it is considered empty.
  53 +*/
  54 +struct MNN_PUBLIC Rect {
  55 + float fLeft; //!< smaller x-axis bounds
  56 + float fTop; //!< smaller y-axis bounds
  57 + float fRight; //!< larger x-axis bounds
  58 + float fBottom; //!< larger y-axis bounds
  59 +
  60 + /** Returns constructed Rect set to (0, 0, 0, 0).
  61 + Many other rectangles are empty; if left is equal to or greater than right,
  62 + or if top is equal to or greater than bottom. Setting all members to zero
  63 + is a convenience, but does not designate a special empty rectangle.
  64 +
  65 + @return bounds (0, 0, 0, 0)
  66 + */
  67 + static constexpr Rect MakeEmpty() {
  68 + return Rect{0, 0, 0, 0};
  69 + }
  70 +
  71 +#ifdef SK_SUPPORT_LEGACY_RECTMAKELARGEST
  72 + /** Deprecated.
  73 + */
  74 + static Rect MakeLargest() {
  75 + return {SK_ScalarMin, SK_ScalarMin, SK_ScalarMax, SK_ScalarMax};
  76 + }
  77 +#endif
  78 +
  79 + /** Returns constructed Rect set to float values (0, 0, w, h). Does not
  80 + validate input; w or h may be negative.
  81 +
  82 + Passing integer values may generate a compiler warning since Rect cannot
  83 + represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
  84 +
  85 + @param w float width of constructed Rect
  86 + @param h float height of constructed Rect
  87 + @return bounds (0, 0, w, h)
  88 + */
  89 + static constexpr Rect MakeWH(float w, float h) {
  90 + return Rect{0, 0, w, h};
  91 + }
  92 +
  93 + /** Returns constructed Rect set to integer values (0, 0, w, h). Does not validate
  94 + input; w or h may be negative.
  95 +
  96 + Use to avoid a compiler warning that input may lose precision when stored.
  97 + Use SkIRect for an exact integer rectangle.
  98 +
  99 + @param w integer width of constructed Rect
  100 + @param h integer height of constructed Rect
  101 + @return bounds (0, 0, w, h)
  102 + */
  103 + static Rect MakeIWH(int w, int h) {
  104 + Rect r;
  105 + r.set(0, 0, (float)(w), (float)(h));
  106 + return r;
  107 + }
  108 +
  109 + /** Returns constructed Rect set to (l, t, r, b). Does not sort input; Rect may
  110 + result in fLeft greater than fRight, or fTop greater than fBottom.
  111 +
  112 + @param l float stored in fLeft
  113 + @param t float stored in fTop
  114 + @param r float stored in fRight
  115 + @param b float stored in fBottom
  116 + @return bounds (l, t, r, b)
  117 + */
  118 + static constexpr Rect MakeLTRB(float l, float t, float r, float b) {
  119 + return Rect{l, t, r, b};
  120 + }
  121 +
  122 + /** Returns constructed Rect set to (x, y, x + w, y + h). Does not validate input;
  123 + w or h may be negative.
  124 +
  125 + @param x stored in fLeft
  126 + @param y stored in fTop
  127 + @param w added to x and stored in fRight
  128 + @param h added to y and stored in fBottom
  129 + @return bounds at (x, y) with width w and height h
  130 + */
  131 + static constexpr Rect MakeXYWH(float x, float y, float w, float h) {
  132 + return Rect{x, y, x + w, y + h};
  133 + }
  134 +
  135 + /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
  136 + to or greater than fBottom. Call sort() to reverse rectangles with negative
  137 + width() or height().
  138 +
  139 + @return true if width() or height() are zero or negative
  140 + */
  141 + bool isEmpty() const {
  142 + // We write it as the NOT of a non-empty rect, so we will return true if any values
  143 + // are NaN.
  144 + return !(fLeft < fRight && fTop < fBottom);
  145 + }
  146 +
  147 + /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
  148 + to or less than fBottom. Call sort() to reverse rectangles with negative
  149 + width() or height().
  150 +
  151 + @return true if width() or height() are zero or positive
  152 + */
  153 + bool isSorted() const {
  154 + return fLeft <= fRight && fTop <= fBottom;
  155 + }
  156 +
  157 + /** Returns left edge of Rect, if sorted. Call isSorted() to see if Rect is valid.
  158 + Call sort() to reverse fLeft and fRight if needed.
  159 +
  160 + @return fLeft
  161 + */
  162 + float x() const {
  163 + return fLeft;
  164 + }
  165 +
  166 + /** Returns top edge of Rect, if sorted. Call isEmpty() to see if Rect may be invalid,
  167 + and sort() to reverse fTop and fBottom if needed.
  168 +
  169 + @return fTop
  170 + */
  171 + float y() const {
  172 + return fTop;
  173 + }
  174 +
  175 + /** Returns left edge of Rect, if sorted. Call isSorted() to see if Rect is valid.
  176 + Call sort() to reverse fLeft and fRight if needed.
  177 +
  178 + @return fLeft
  179 + */
  180 + float left() const {
  181 + return fLeft;
  182 + }
  183 +
  184 + /** Returns top edge of Rect, if sorted. Call isEmpty() to see if Rect may be invalid,
  185 + and sort() to reverse fTop and fBottom if needed.
  186 +
  187 + @return fTop
  188 + */
  189 + float top() const {
  190 + return fTop;
  191 + }
  192 +
  193 + /** Returns right edge of Rect, if sorted. Call isSorted() to see if Rect is valid.
  194 + Call sort() to reverse fLeft and fRight if needed.
  195 +
  196 + @return fRight
  197 + */
  198 + float right() const {
  199 + return fRight;
  200 + }
  201 +
  202 + /** Returns bottom edge of Rect, if sorted. Call isEmpty() to see if Rect may be invalid,
  203 + and sort() to reverse fTop and fBottom if needed.
  204 +
  205 + @return fBottom
  206 + */
  207 + float bottom() const {
  208 + return fBottom;
  209 + }
  210 +
  211 + /** Returns span on the x-axis. This does not check if Rect is sorted, or if
  212 + result fits in 32-bit float; result may be negative or infinity.
  213 +
  214 + @return fRight minus fLeft
  215 + */
  216 + float width() const {
  217 + return fRight - fLeft;
  218 + }
  219 +
  220 + /** Returns span on the y-axis. This does not check if Rect is sorted, or if
  221 + result fits in 32-bit float; result may be negative or infinity.
  222 +
  223 + @return fBottom minus fTop
  224 + */
  225 + float height() const {
  226 + return fBottom - fTop;
  227 + }
  228 +
  229 + /** Returns average of left edge and right edge. Result does not change if Rect
  230 + is sorted. Result may overflow to infinity if Rect is far from the origin.
  231 +
  232 + @return midpoint in x
  233 + */
  234 + float centerX() const {
  235 + // don't use floatHalf(fLeft + fBottom) as that might overflow before the 0.5
  236 + return 0.5f * (fLeft) + 0.5f * (fRight);
  237 + }
  238 +
  239 + /** Returns average of top edge and bottom edge. Result does not change if Rect
  240 + is sorted.
  241 +
  242 + @return midpoint in y
  243 + */
  244 + float centerY() const {
  245 + // don't use floatHalf(fTop + fBottom) as that might overflow before the 0.5
  246 + return 0.5f * (fTop) + 0.5f * (fBottom);
  247 + }
  248 +
  249 + /** Sets Rect to (0, 0, 0, 0).
  250 +
  251 + Many other rectangles are empty; if left is equal to or greater than right,
  252 + or if top is equal to or greater than bottom. Setting all members to zero
  253 + is a convenience, but does not designate a special empty rectangle.
  254 + */
  255 + void setEmpty() {
  256 + *this = MakeEmpty();
  257 + }
  258 +
  259 + /** Sets Rect to (left, top, right, bottom).
  260 + left and right are not sorted; left is not necessarily less than right.
  261 + top and bottom are not sorted; top is not necessarily less than bottom.
  262 +
  263 + @param left stored in fLeft
  264 + @param top stored in fTop
  265 + @param right stored in fRight
  266 + @param bottom stored in fBottom
  267 + */
  268 + void set(float left, float top, float right, float bottom) {
  269 + fLeft = left;
  270 + fTop = top;
  271 + fRight = right;
  272 + fBottom = bottom;
  273 + }
  274 +
  275 + /** Sets Rect to (left, top, right, bottom).
  276 + left and right are not sorted; left is not necessarily less than right.
  277 + top and bottom are not sorted; top is not necessarily less than bottom.
  278 +
  279 + @param left stored in fLeft
  280 + @param top stored in fTop
  281 + @param right stored in fRight
  282 + @param bottom stored in fBottom
  283 + */
  284 + void setLTRB(float left, float top, float right, float bottom) {
  285 + this->set(left, top, right, bottom);
  286 + }
  287 +
  288 + /** Sets Rect to (left, top, right, bottom).
  289 + All parameters are promoted from integer to scalar.
  290 + left and right are not sorted; left is not necessarily less than right.
  291 + top and bottom are not sorted; top is not necessarily less than bottom.
  292 +
  293 + @param left promoted to float and stored in fLeft
  294 + @param top promoted to float and stored in fTop
  295 + @param right promoted to float and stored in fRight
  296 + @param bottom promoted to float and stored in fBottom
  297 + */
  298 + void iset(int left, int top, int right, int bottom) {
  299 + fLeft = (float)(left);
  300 + fTop = (float)(top);
  301 + fRight = (float)(right);
  302 + fBottom = (float)(bottom);
  303 + }
  304 +
  305 + /** Sets Rect to (0, 0, width, height).
  306 + width and height may be zero or negative. width and height are promoted from
  307 + integer to float, large values may lose precision.
  308 +
  309 + @param width promoted to float and stored in fRight
  310 + @param height promoted to float and stored in fBottom
  311 + */
  312 + void isetWH(int width, int height) {
  313 + fLeft = fTop = 0;
  314 + fRight = (float)(width);
  315 + fBottom = (float)(height);
  316 + }
  317 +
  318 + /** Sets Rect to (x, y, x + width, y + height). Does not validate input;
  319 + width or height may be negative.
  320 +
  321 + @param x stored in fLeft
  322 + @param y stored in fTop
  323 + @param width added to x and stored in fRight
  324 + @param height added to y and stored in fBottom
  325 + */
  326 + void setXYWH(float x, float y, float width, float height) {
  327 + fLeft = x;
  328 + fTop = y;
  329 + fRight = x + width;
  330 + fBottom = y + height;
  331 + }
  332 +
  333 + /** Sets Rect to (0, 0, width, height). Does not validate input;
  334 + width or height may be negative.
  335 +
  336 + @param width stored in fRight
  337 + @param height stored in fBottom
  338 + */
  339 + void setWH(float width, float height) {
  340 + fLeft = 0;
  341 + fTop = 0;
  342 + fRight = width;
  343 + fBottom = height;
  344 + }
  345 +
  346 + /** Returns Rect offset by (dx, dy).
  347 +
  348 + If dx is negative, Rect returned is moved to the left.
  349 + If dx is positive, Rect returned is moved to the right.
  350 + If dy is negative, Rect returned is moved upward.
  351 + If dy is positive, Rect returned is moved downward.
  352 +
  353 + @param dx added to fLeft and fRight
  354 + @param dy added to fTop and fBottom
  355 + @return Rect offset on axes, with original width and height
  356 + */
  357 + Rect makeOffset(float dx, float dy) const {
  358 + return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
  359 + }
  360 +
  361 + /** Returns Rect, inset by (dx, dy).
  362 +
  363 + If dx is negative, Rect returned is wider.
  364 + If dx is positive, Rect returned is narrower.
  365 + If dy is negative, Rect returned is taller.
  366 + If dy is positive, Rect returned is shorter.
  367 +
  368 + @param dx added to fLeft and subtracted from fRight
  369 + @param dy added to fTop and subtracted from fBottom
  370 + @return Rect inset symmetrically left and right, top and bottom
  371 + */
  372 + Rect makeInset(float dx, float dy) const {
  373 + return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
  374 + }
  375 +
  376 + /** Returns Rect, outset by (dx, dy).
  377 +
  378 + If dx is negative, Rect returned is narrower.
  379 + If dx is positive, Rect returned is wider.
  380 + If dy is negative, Rect returned is shorter.
  381 + If dy is positive, Rect returned is taller.
  382 +
  383 + @param dx subtracted to fLeft and added from fRight
  384 + @param dy subtracted to fTop and added from fBottom
  385 + @return Rect outset symmetrically left and right, top and bottom
  386 + */
  387 + Rect makeOutset(float dx, float dy) const {
  388 + return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
  389 + }
  390 +
  391 + /** Offsets Rect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
  392 +
  393 + If dx is negative, moves Rect to the left.
  394 + If dx is positive, moves Rect to the right.
  395 + If dy is negative, moves Rect upward.
  396 + If dy is positive, moves Rect downward.
  397 +
  398 + @param dx offset added to fLeft and fRight
  399 + @param dy offset added to fTop and fBottom
  400 + */
  401 + void offset(float dx, float dy) {
  402 + fLeft += dx;
  403 + fTop += dy;
  404 + fRight += dx;
  405 + fBottom += dy;
  406 + }
  407 +
  408 + /** Offsets Rect so that fLeft equals newX, and fTop equals newY. width and height
  409 + are unchanged.
  410 +
  411 + @param newX stored in fLeft, preserving width()
  412 + @param newY stored in fTop, preserving height()
  413 + */
  414 + void offsetTo(float newX, float newY) {
  415 + fRight += newX - fLeft;
  416 + fBottom += newY - fTop;
  417 + fLeft = newX;
  418 + fTop = newY;
  419 + }
  420 +
  421 + /** Insets Rect by (dx, dy).
  422 +
  423 + If dx is positive, makes Rect narrower.
  424 + If dx is negative, makes Rect wider.
  425 + If dy is positive, makes Rect shorter.
  426 + If dy is negative, makes Rect taller.
  427 +
  428 + @param dx added to fLeft and subtracted from fRight
  429 + @param dy added to fTop and subtracted from fBottom
  430 + */
  431 + void inset(float dx, float dy) {
  432 + fLeft += dx;
  433 + fTop += dy;
  434 + fRight -= dx;
  435 + fBottom -= dy;
  436 + }
  437 +
  438 + /** Outsets Rect by (dx, dy).
  439 +
  440 + If dx is positive, makes Rect wider.
  441 + If dx is negative, makes Rect narrower.
  442 + If dy is positive, makes Rect taller.
  443 + If dy is negative, makes Rect shorter.
  444 +
  445 + @param dx subtracted to fLeft and added from fRight
  446 + @param dy subtracted to fTop and added from fBottom
  447 + */
  448 + void outset(float dx, float dy) {
  449 + this->inset(-dx, -dy);
  450 + }
  451 +
  452 +private:
  453 + static bool Intersects(float al, float at, float ar, float ab, float bl, float bt, float br, float bb) {
  454 + float L = std::max(al, bl);
  455 + float R = std::min(ar, br);
  456 + float T = std::max(at, bt);
  457 + float B = std::min(ab, bb);
  458 + return L < R && T < B;
  459 + }
  460 +
  461 +public:
  462 + /** Constructs Rect to intersect from (left, top, right, bottom). Does not sort
  463 + construction.
  464 +
  465 + Returns true if Rect intersects construction.
  466 + Returns false if either construction or Rect is empty, or do not intersect.
  467 +
  468 + @param left x-axis minimum of constructed Rect
  469 + @param top y-axis minimum of constructed Rect
  470 + @param right x-axis maximum of constructed Rect
  471 + @param bottom y-axis maximum of constructed Rect
  472 + @return true if construction and Rect have area in common
  473 + */
  474 + bool intersects(float left, float top, float right, float bottom) const {
  475 + return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom);
  476 + }
  477 +
  478 + /** Returns true if Rect intersects r.
  479 + Returns false if either r or Rect is empty, or do not intersect.
  480 +
  481 + @param r Rect to intersect
  482 + @return true if r and Rect have area in common
  483 + */
  484 + bool intersects(const Rect& r) const {
  485 + return Intersects(fLeft, fTop, fRight, fBottom, r.fLeft, r.fTop, r.fRight, r.fBottom);
  486 + }
  487 +
  488 + /** Returns true if a intersects b.
  489 + Returns false if either a or b is empty, or do not intersect.
  490 +
  491 + @param a Rect to intersect
  492 + @param b Rect to intersect
  493 + @return true if a and b have area in common
  494 + */
  495 + static bool Intersects(const Rect& a, const Rect& b) {
  496 + return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom, b.fLeft, b.fTop, b.fRight, b.fBottom);
  497 + }
  498 +
  499 + /** Sets Rect to the union of itself and r.
  500 +
  501 + Asserts if r is empty and SK_DEBUG is defined.
  502 + If Rect is empty, sets Rect to r.
  503 +
  504 + May produce incorrect results if r is empty.
  505 +
  506 + @param r expansion Rect
  507 + */
  508 + void joinNonEmptyArg(const Rect& r) {
  509 + MNN_ASSERT(!r.isEmpty());
  510 + // if we are empty, just assign
  511 + if (fLeft >= fRight || fTop >= fBottom) {
  512 + *this = r;
  513 + } else {
  514 + this->joinPossiblyEmptyRect(r);
  515 + }
  516 + }
  517 +
  518 + /** Sets Rect to the union of itself and the construction.
  519 +
  520 + May produce incorrect results if Rect or r is empty.
  521 +
  522 + @param r expansion Rect
  523 + */
  524 + void joinPossiblyEmptyRect(const Rect& r) {
  525 + fLeft = std::min(fLeft, r.left());
  526 + fTop = std::min(fTop, r.top());
  527 + fRight = std::max(fRight, r.right());
  528 + fBottom = std::max(fBottom, r.bottom());
  529 + }
  530 +
  531 + /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
  532 + Returns false if Rect is empty.
  533 +
  534 + @param x test Point x-coordinate
  535 + @param y test Point y-coordinate
  536 + @return true if (x, y) is inside Rect
  537 + */
  538 + bool contains(float x, float y) const {
  539 + return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
  540 + }
  541 +
  542 + /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
  543 + fTop and fBottom if fTop is greater than fBottom. Result may be empty;
  544 + and width() and height() will be zero or positive.
  545 + */
  546 + void sort() {
  547 + using std::swap;
  548 + if (fLeft > fRight) {
  549 + swap(fLeft, fRight);
  550 + }
  551 +
  552 + if (fTop > fBottom) {
  553 + swap(fTop, fBottom);
  554 + }
  555 + }
  556 +
  557 + /** Returns Rect with fLeft and fRight swapped if fLeft is greater than fRight; and
  558 + with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
  559 + and width() and height() will be zero or positive.
  560 +
  561 + @return sorted Rect
  562 + */
  563 + Rect makeSorted() const {
  564 + return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom), std::max(fLeft, fRight),
  565 + std::max(fTop, fBottom));
  566 + }
  567 +
  568 + /** Returns pointer to first scalar in Rect, to treat it as an array with four
  569 + entries.
  570 +
  571 + @return pointer to fLeft
  572 + */
  573 + const float* asScalars() const {
  574 + return &fLeft;
  575 + }
  576 +};
  577 +
  578 +} // namespace CV
  579 +} // namespace MNN
  580 +#endif
  1 +//
  2 +// Tensor.hpp
  3 +// MNN
  4 +//
  5 +// Created by MNN on 2018/08/14.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +
  9 +#ifndef Tensor_hpp
  10 +#define Tensor_hpp
  11 +
  12 +#include <vector>
  13 +#include <MNN/HalideRuntime.h>
  14 +#include <MNN/MNNDefine.h>
  15 +#define MNN_MAX_TENSOR_DIM 6
  16 +
  17 +namespace MNN {
  18 +
  19 +/**
  20 + * data container.
  21 + * data for host tensor is saved in `host` field. its memory is allocated malloc directly.
  22 + * data for device tensor is saved in `deviceId` field. its memory is allocated by session's backend.
  23 + * usually, device tensors are created by engine (like net, session).
  24 + * meanwhile, host tensors could be created by engine or user.
  25 + */
  26 +class MNN_PUBLIC Tensor {
  27 +public:
  28 + struct InsideDescribe;
  29 +
  30 + /** dimension type used to create tensor */
  31 + enum DimensionType {
  32 + /** for tensorflow net type. uses NHWC as data format. */
  33 + TENSORFLOW,
  34 + /** for caffe net type. uses NCHW as data format. */
  35 + CAFFE,
  36 + /** for caffe net type. uses NC4HW4 as data format. */
  37 + CAFFE_C4
  38 + };
  39 +
  40 + /** handle type */
  41 + enum HandleDataType {
  42 + /** default handle type */
  43 + HANDLE_NONE = 0,
  44 + /** string handle type */
  45 + HANDLE_STRING = 1
  46 + };
  47 +
  48 + /** Tensor map type : Read or Write*/
  49 + enum MapType {
  50 + /** map Tensor for writing data*/
  51 + MAP_TENSOR_WRITE = 0,
  52 + MAP_TENSOR_READ = 1
  53 + };
  54 +
  55 +public:
  56 + /**
  57 + * @brief create a tensor with dimension size and type without acquire memory for data.
  58 + * @param dimSize dimension size.
  59 + * @param type dimension type.
  60 + */
  61 + Tensor(int dimSize = 4, DimensionType type = CAFFE);
  62 +
  63 + /**
  64 + * @brief create a tensor with same shape as given tensor.
  65 + * @param tensor shape provider.
  66 + * @param type dimension type.
  67 + * @param allocMemory acquire memory for data or not.
  68 + * @warning tensor data won't be copied.
  69 + */
  70 + Tensor(const Tensor* tensor, DimensionType type = CAFFE, bool allocMemory = true);
  71 +
  72 + /** deinitializer */
  73 + ~Tensor();
  74 +
  75 +private:
  76 + // remove all assignment operator
  77 + Tensor(const Tensor& tensor) = delete;
  78 + Tensor(const Tensor&& tensor) = delete;
  79 + Tensor& operator=(const Tensor&) = delete;
  80 + Tensor& operator=(const Tensor&&) = delete;
  81 +
  82 +public:
  83 + /**
  84 + * @brief create tensor with shape, data type and dimension type.
  85 + * @param shape tensor shape.
  86 + * @param type data type.
  87 + * @param dimType dimension type.
  88 + * @return created tensor.
  89 + * @warning memory for data won't be acquired. call backend's onAcquireBuffer to get memory ready.
  90 + */
  91 + static Tensor* createDevice(const std::vector<int>& shape, halide_type_t type, DimensionType dimType = TENSORFLOW);
  92 +
  93 + /**
  94 + * @brief create tensor with shape and dimension type. data type is represented by `T`.
  95 + * @param shape tensor shape.
  96 + * @param dimType dimension type.
  97 + * @return created tensor.
  98 + * @warning memory for data won't be acquired. call backend's onAcquireBuffer to get memory ready.
  99 + */
  100 + template <typename T>
  101 + static Tensor* createDevice(const std::vector<int>& shape, DimensionType dimType = TENSORFLOW) {
  102 + return createDevice(shape, halide_type_of<T>(), dimType);
  103 + }
  104 +
  105 + /**
  106 + * @brief create tensor with shape, data type, data and dimension type.
  107 + * @param shape tensor shape.
  108 + * @param type data type.
  109 + * @param data data to save.
  110 + * @param dimType dimension type.
  111 + * @return created tensor.
  112 + */
  113 + static Tensor* create(const std::vector<int>& shape, halide_type_t type, void* data = NULL,
  114 + DimensionType dimType = TENSORFLOW);
  115 +
  116 + /**
  117 + * @brief create tensor with shape, data and dimension type. data type is represented by `T`.
  118 + * @param shape tensor shape.
  119 + * @param data data to save.
  120 + * @param dimType dimension type.
  121 + * @return created tensor.
  122 + */
  123 + template <typename T>
  124 + static Tensor* create(const std::vector<int>& shape, void* data = NULL, DimensionType dimType = TENSORFLOW) {
  125 + return create(shape, halide_type_of<T>(), data, dimType);
  126 + }
  127 +
  128 +public:
  129 + /**
  130 + * @brief for DEVICE tensor, copy data from given host tensor.
  131 + * @param hostTensor host tensor, the data provider.
  132 + * @return true for DEVICE tensor, and false for HOST tensor.
  133 + */
  134 + bool copyFromHostTensor(const Tensor* hostTensor);
  135 +
  136 + /**
  137 + * @brief for DEVICE tensor, copy data to given host tensor.
  138 + * @param hostTensor host tensor, the data consumer.
  139 + * @return true for DEVICE tensor, and false for HOST tensor.
  140 + */
  141 + bool copyToHostTensor(Tensor* hostTensor) const;
  142 +
  143 + /**
  144 + * @brief create HOST tensor from DEVICE tensor, with or without data copying.
  145 + * @param deviceTensor given device tensor.
  146 + * @param copyData copy data or not.
  147 + * @return created host tensor.
  148 + */
  149 + static Tensor* createHostTensorFromDevice(const Tensor* deviceTensor, bool copyData = true);
  150 +
  151 +public:
  152 + const halide_buffer_t& buffer() const {
  153 + return mBuffer;
  154 + }
  155 + halide_buffer_t& buffer() {
  156 + return mBuffer;
  157 + }
  158 +
  159 + /**
  160 + * @brief get dimension type.
  161 + * @return dimension type.
  162 + */
  163 + DimensionType getDimensionType() const;
  164 +
  165 + /**
  166 + * @brief handle data type. used when data type code is halide_type_handle.
  167 + * @return handle data type.
  168 + */
  169 + HandleDataType getHandleDataType() const;
  170 +
  171 + /**
  172 + * @brief set data type.
  173 + * @param type data type defined in 'Type_generated.h'.
  174 + */
  175 + void setType(int type);
  176 +
  177 + /**
  178 + * @brief get data type.
  179 + * @return data type.
  180 + */
  181 + inline halide_type_t getType() const {
  182 + return mBuffer.type;
  183 + }
  184 +
  185 + /**
  186 + * @brief visit host memory, data type is represented by `T`.
  187 + * @return data point in `T` type.
  188 + */
  189 + template <typename T>
  190 + T* host() const {
  191 + return (T*)mBuffer.host;
  192 + }
  193 +
  194 + /**
  195 + * @brief visit device memory.
  196 + * @return device data ID. what the ID means varies between backends.
  197 + */
  198 + uint64_t deviceId() const {
  199 + return mBuffer.device;
  200 + }
  201 +
  202 +public:
  203 + int dimensions() const {
  204 + return mBuffer.dimensions;
  205 + }
  206 +
  207 + /**
  208 + * @brief get all dimensions' extent.
  209 + * @return dimensions' extent.
  210 + */
  211 + std::vector<int> shape() const;
  212 +
  213 + /**
  214 + * @brief calculate number of bytes needed to store data taking reordering flag into account.
  215 + * @return bytes needed to store data
  216 + */
  217 + int size() const;
  218 +
  219 + /**
  220 + * @brief calculate number of elements needed to store data taking reordering flag into account.
  221 + * @return elements needed to store data
  222 + */
  223 + inline int elementSize() const {
  224 + return size() / mBuffer.type.bytes();
  225 + }
  226 +
  227 +public:
  228 + inline int width() const {
  229 + if (getDimensionType() == TENSORFLOW) {
  230 + return mBuffer.dim[2].extent;
  231 + }
  232 +
  233 + return mBuffer.dim[3].extent;
  234 + }
  235 + inline int height() const {
  236 + if (getDimensionType() == TENSORFLOW) {
  237 + return mBuffer.dim[1].extent;
  238 + }
  239 + return mBuffer.dim[2].extent;
  240 + }
  241 + inline int channel() const {
  242 + if (getDimensionType() == TENSORFLOW) {
  243 + return mBuffer.dim[3].extent;
  244 + }
  245 + return mBuffer.dim[1].extent;
  246 + }
  247 + inline int batch() const {
  248 + return mBuffer.dim[0].extent;
  249 + }
  250 +
  251 + // visit dimension's extent & stride
  252 + inline int stride(int index) const {
  253 + return mBuffer.dim[index].stride;
  254 + }
  255 + inline int length(int index) const {
  256 + return mBuffer.dim[index].extent;
  257 + }
  258 + inline void setStride(int index, int stride) {
  259 + mBuffer.dim[index].stride = stride;
  260 + }
  261 + inline void setLength(int index, int length) {
  262 + mBuffer.dim[index].extent = length;
  263 + }
  264 +
  265 +public:
  266 + /**
  267 + * @brief print tensor data. for DEBUG use only.
  268 + */
  269 + void print() const;
  270 +
  271 + /**
  272 + *@brief print tensor shape
  273 + */
  274 + void printShape() const;
  275 +
  276 +public:
  277 + /**
  278 + * @brief map/umap GPU Tensor, to get host ptr
  279 + */
  280 + void* map(MapType mtype, DimensionType dtype);
  281 + void unmap(MapType mtype, DimensionType dtype, void* mapPtr);
  282 +
  283 +private:
  284 + halide_buffer_t mBuffer;
  285 + struct InsideDescribe* mDescribe;
  286 +
  287 +private:
  288 + friend class TensorUtils;
  289 +};
  290 +} // namespace MNN
  291 +
  292 +#endif /* Tensor_hpp */
  1 +//
  2 +// Executor.hpp
  3 +// MNN
  4 +//
  5 +// Created by MNN on 2019/07/25.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +#ifndef Executor_hpp
  9 +#define Executor_hpp
  10 +#include <MNN/ErrorCode.hpp>
  11 +#include <MNN/expr/Expr.hpp>
  12 +#include <MNN/Tensor.hpp>
  13 +#include <MNN/Interpreter.hpp>
  14 +#include <vector>
  15 +#include <mutex>
  16 +#include <set>
  17 +#include <MNN/MNNForwardType.h>
  18 +namespace MNN {
  19 +class Backend;
  20 +class Execution;
  21 +class Runtime;
  22 +struct Op;
  23 +namespace Express {
  24 +class MNN_PUBLIC Executor {
  25 +public:
  26 + class ComputeCache;
  27 + struct Unit;
  28 + static void setShapeDirty(ComputeCache* cache);
  29 + static void setContentDirty(ComputeCache* cache);
  30 + static Tensor* getOutput(ComputeCache* cache, int offset);
  31 + static void* mapOutput(ComputeCache* cache, int offset, Tensor* dest);
  32 + struct Requirement {
  33 + std::vector<bool> contentNeedContent;
  34 + std::vector<bool> shapeNeedContent;
  35 + };
  36 + ~Executor();
  37 + Requirement getRequirement(Expr* expr) const;
  38 + ErrorCode computeInfo(Expr* expr);
  39 + void makeCache(const std::vector<EXPRP>& expr, bool forceCPU = false);
  40 + ErrorCode runCache(std::shared_ptr<ComputeCache> cache);
  41 + void setGlobalExecutorConfig(MNNForwardType type, const BackendConfig& config, int numberThread);
  42 + enum GCFlag {
  43 + FULL,
  44 + PART
  45 + };
  46 + void gc(GCFlag flag = FULL);
  47 + static std::shared_ptr<Executor> getGlobalExecutor();
  48 +
  49 + static std::shared_ptr<Executor> newExecutor(MNNForwardType type,
  50 + const BackendConfig& config,
  51 + int numberThread);
  52 + void resetProfile();
  53 + void dumpProfile();
  54 + void addOpCostTime(int op, float costTime);
  55 + void addOpCostTime(const std::string& type, float costTime);
  56 + void addOpFlops(const std::string& type, float flops);
  57 + class Profiler;
  58 + static RuntimeInfo getRuntime();
  59 +
  60 + struct Cache;
  61 + class RuntimeManager {
  62 + public:
  63 + RuntimeManager(std::vector<ScheduleConfig> &configs);
  64 + ~RuntimeManager() {};
  65 +
  66 + /**
  67 + * @param configs: schedule configs.
  68 + * @param cacheName: full path for cache file. Note: should choose location for reading and writing.
  69 + */
  70 + static RuntimeManager* createRuntimeManager(std::vector<ScheduleConfig> &configs);
  71 +
  72 + /**
  73 + * @brief set cache file. when file not exist -- create it, when file exist -- load it.
  74 + * When should use : When choose GPU backend or use AUTO backend.
  75 + * Calling Position: calling after createRuntimeManager.
  76 + */
  77 + void setCache(std::string cacheName);
  78 +
  79 + /**
  80 + * @brief update cache file
  81 + * When should use : Together with setCache API. calling for first inference and when input shape is changed.
  82 + * Calling Position : calling after inference done.
  83 + */
  84 + void updateCache();
  85 + std::vector<bool> isBackendSupport(const std::vector<MNNForwardType> type);
  86 + RuntimeInfo getRuntimeInfo() {
  87 + return mRuntime;
  88 + }
  89 + private:
  90 + RuntimeInfo mRuntime;
  91 + std::shared_ptr<Runtime> mInfo;
  92 + std::shared_ptr<Cache> mCache;
  93 +
  94 + };
  95 +
  96 +
  97 +private:
  98 + void _makeCache(const std::vector<EXPRP>& outputs, bool forceCPU);
  99 + void _create(const std::vector<EXPRP>& outputs, std::set<std::shared_ptr<Executor::ComputeCache>>&& inputCaches, std::set<std::shared_ptr<Expr::Inside>>&& inputNode, bool forceCPU);
  100 +
  101 + void _visit(EXPRP expr, std::set<std::shared_ptr<Executor::ComputeCache>>& inputCaches, std::set<std::shared_ptr<Expr::Inside>>& inputNode);
  102 +
  103 + Executor(std::shared_ptr<Runtime> backend, MNNForwardType type);
  104 + std::pair<std::shared_ptr<Runtime>, MNNForwardType> mRuntime;
  105 + std::pair<std::shared_ptr<Runtime>, MNNForwardType> mBackupRuntime;
  106 + std::mutex mMutex;
  107 + std::shared_ptr<Profiler> mProfiler;
  108 +};
  109 +} // namespace Express
  110 +} // namespace MNN
  111 +#endif
  1 +//
  2 +// ExecutorScope.hpp
  3 +// MNN
  4 +//
  5 +// Created by MNN on 2020/10/26.
  6 +// Copyright © 2018, Alibaba Group Holding Limited
  7 +//
  8 +
  9 +#ifndef MNN_EXPR_EXECUTOR_SCOPE_HPP_
  10 +#define MNN_EXPR_EXECUTOR_SCOPE_HPP_
  11 +
  12 +#include <MNN/expr/Executor.hpp>
  13 +
  14 +namespace MNN {
  15 +namespace Express {
  16 +
  17 +struct MNN_PUBLIC ExecutorScope final {
  18 +public:
  19 + ExecutorScope() = delete;
  20 + explicit ExecutorScope(const ExecutorScope&) = delete;
  21 + explicit ExecutorScope(const std::shared_ptr<Executor>& current);
  22 +
  23 + explicit ExecutorScope(const std::string& scope_name,
  24 + const std::shared_ptr<Executor>& current);
  25 +
  26 + virtual ~ExecutorScope();
  27 +
  28 + static const std::shared_ptr<Executor> Current();
  29 +};
  30 +
  31 +} // namespace MNN
  32 +} // namespace Express
  33 +#endif // MNN_EXPR_EXECUTOR_SCOPE_HPP_