1diff --git a/benchmark/Android.mk b/benchmark/Android.mk 2new file mode 100755 3index 00000000..d48e0d8e 4--- /dev/null 5+++ b/benchmark/Android.mk 6@@ -0,0 +1,53 @@ 7+local_target_dir := $(TARGET_OUT_DATA)/local/tmp 8+ 9+LOCAL_PATH:= $(call my-dir) 10+ 11+include $(CLEAR_VARS) 12+ 13+LOCAL_C_INCLUDES := \ 14+ $(LOCAL_PATH)/feature_mos/src \ 15+ $(LOCAL_PATH)/feature_stab/src \ 16+ $(LOCAL_PATH)/feature_stab/db_vlvm 17+ 18+LOCAL_SRC_FILES := benchmark.cpp \ 19+ feature_mos/src/mosaic/ImageUtils.cpp \ 20+ feature_mos/src/mosaic/Mosaic.cpp \ 21+ feature_mos/src/mosaic/AlignFeatures.cpp \ 22+ feature_mos/src/mosaic/Blend.cpp \ 23+ feature_mos/src/mosaic/Pyramid.cpp \ 24+ feature_mos/src/mosaic/trsMatrix.cpp \ 25+ feature_mos/src/mosaic/Delaunay.cpp \ 26+ feature_mos/src/mosaic_renderer/Renderer.cpp \ 27+ feature_mos/src/mosaic_renderer/WarpRenderer.cpp \ 28+ feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp \ 29+ feature_mos/src/mosaic_renderer/YVURenderer.cpp \ 30+ feature_mos/src/mosaic_renderer/FrameBuffer.cpp \ 31+ feature_stab/db_vlvm/db_rob_image_homography.cpp \ 32+ feature_stab/db_vlvm/db_feature_detection.cpp \ 33+ feature_stab/db_vlvm/db_image_homography.cpp \ 34+ feature_stab/db_vlvm/db_framestitching.cpp \ 35+ feature_stab/db_vlvm/db_feature_matching.cpp \ 36+ feature_stab/db_vlvm/db_utilities.cpp \ 37+ feature_stab/db_vlvm/db_utilities_camera.cpp \ 38+ feature_stab/db_vlvm/db_utilities_indexing.cpp \ 39+ feature_stab/db_vlvm/db_utilities_linalg.cpp \ 40+ feature_stab/db_vlvm/db_utilities_poly.cpp \ 41+ feature_stab/src/dbreg/dbstabsmooth.cpp \ 42+ feature_stab/src/dbreg/dbreg.cpp \ 43+ feature_stab/src/dbreg/vp_motionmodel.c 44+ 45+LOCAL_CFLAGS := -O3 -DNDEBUG -Wno-unused-parameter -Wno-maybe-uninitialized 46+LOCAL_CFLAGS += $(CFLAGS_FOR_BENCH_SUITE) 47+LOCAL_LDFLAGS := $(LDFLAGS_FOR_BENCH_SUITE) 48+LOCAL_CPPFLAGS := -std=c++98 49+LOCAL_MODULE_TAGS := tests 50+LOCAL_MODULE := panorama_bench 51+LOCAL_MODULE_STEM_32 := panorama_bench 52+LOCAL_MODULE_STEM_64 := panorama_bench64 53+LOCAL_MULTILIB := both 54+LOCAL_MODULE_PATH := $(local_target_dir) 55+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk 56+LOCAL_FORCE_STATIC_EXECUTABLE := true 57+LOCAL_STATIC_LIBRARIES := libc libm 58+ 59+include $(BUILD_EXECUTABLE) 60diff --git a/benchmark/NOTICE b/benchmark/NOTICE 61new file mode 100644 62index 00000000..7317ae2a 63--- /dev/null 64+++ b/benchmark/NOTICE 65@@ -0,0 +1,190 @@ 66+ 67+ Copyright (c) 2005-2011, The Android Open Source Project 68+ 69+ Licensed under the Apache License, Version 2.0 (the "License"); 70+ you may not use this file except in compliance with the License. 71+ 72+ Unless required by applicable law or agreed to in writing, software 73+ distributed under the License is distributed on an "AS IS" BASIS, 74+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 75+ See the License for the specific language governing permissions and 76+ limitations under the License. 77+ 78+ 79+ Apache License 80+ Version 2.0, January 2004 81+ http://www.apache.org/licenses/ 82+ 83+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 84+ 85+ 1. Definitions. 86+ 87+ "License" shall mean the terms and conditions for use, reproduction, 88+ and distribution as defined by Sections 1 through 9 of this document. 89+ 90+ "Licensor" shall mean the copyright owner or entity authorized by 91+ the copyright owner that is granting the License. 92+ 93+ "Legal Entity" shall mean the union of the acting entity and all 94+ other entities that control, are controlled by, or are under common 95+ control with that entity. For the purposes of this definition, 96+ "control" means (i) the power, direct or indirect, to cause the 97+ direction or management of such entity, whether by contract or 98+ otherwise, or (ii) ownership of fifty percent (50%) or more of the 99+ outstanding shares, or (iii) beneficial ownership of such entity. 100+ 101+ "You" (or "Your") shall mean an individual or Legal Entity 102+ exercising permissions granted by this License. 103+ 104+ "Source" form shall mean the preferred form for making modifications, 105+ including but not limited to software source code, documentation 106+ source, and configuration files. 107+ 108+ "Object" form shall mean any form resulting from mechanical 109+ transformation or translation of a Source form, including but 110+ not limited to compiled object code, generated documentation, 111+ and conversions to other media types. 112+ 113+ "Work" shall mean the work of authorship, whether in Source or 114+ Object form, made available under the License, as indicated by a 115+ copyright notice that is included in or attached to the work 116+ (an example is provided in the Appendix below). 117+ 118+ "Derivative Works" shall mean any work, whether in Source or Object 119+ form, that is based on (or derived from) the Work and for which the 120+ editorial revisions, annotations, elaborations, or other modifications 121+ represent, as a whole, an original work of authorship. For the purposes 122+ of this License, Derivative Works shall not include works that remain 123+ separable from, or merely link (or bind by name) to the interfaces of, 124+ the Work and Derivative Works thereof. 125+ 126+ "Contribution" shall mean any work of authorship, including 127+ the original version of the Work and any modifications or additions 128+ to that Work or Derivative Works thereof, that is intentionally 129+ submitted to Licensor for inclusion in the Work by the copyright owner 130+ or by an individual or Legal Entity authorized to submit on behalf of 131+ the copyright owner. For the purposes of this definition, "submitted" 132+ means any form of electronic, verbal, or written communication sent 133+ to the Licensor or its representatives, including but not limited to 134+ communication on electronic mailing lists, source code control systems, 135+ and issue tracking systems that are managed by, or on behalf of, the 136+ Licensor for the purpose of discussing and improving the Work, but 137+ excluding communication that is conspicuously marked or otherwise 138+ designated in writing by the copyright owner as "Not a Contribution." 139+ 140+ "Contributor" shall mean Licensor and any individual or Legal Entity 141+ on behalf of whom a Contribution has been received by Licensor and 142+ subsequently incorporated within the Work. 143+ 144+ 2. Grant of Copyright License. Subject to the terms and conditions of 145+ this License, each Contributor hereby grants to You a perpetual, 146+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable 147+ copyright license to reproduce, prepare Derivative Works of, 148+ publicly display, publicly perform, sublicense, and distribute the 149+ Work and such Derivative Works in Source or Object form. 150+ 151+ 3. Grant of Patent License. Subject to the terms and conditions of 152+ this License, each Contributor hereby grants to You a perpetual, 153+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable 154+ (except as stated in this section) patent license to make, have made, 155+ use, offer to sell, sell, import, and otherwise transfer the Work, 156+ where such license applies only to those patent claims licensable 157+ by such Contributor that are necessarily infringed by their 158+ Contribution(s) alone or by combination of their Contribution(s) 159+ with the Work to which such Contribution(s) was submitted. If You 160+ institute patent litigation against any entity (including a 161+ cross-claim or counterclaim in a lawsuit) alleging that the Work 162+ or a Contribution incorporated within the Work constitutes direct 163+ or contributory patent infringement, then any patent licenses 164+ granted to You under this License for that Work shall terminate 165+ as of the date such litigation is filed. 166+ 167+ 4. Redistribution. You may reproduce and distribute copies of the 168+ Work or Derivative Works thereof in any medium, with or without 169+ modifications, and in Source or Object form, provided that You 170+ meet the following conditions: 171+ 172+ (a) You must give any other recipients of the Work or 173+ Derivative Works a copy of this License; and 174+ 175+ (b) You must cause any modified files to carry prominent notices 176+ stating that You changed the files; and 177+ 178+ (c) You must retain, in the Source form of any Derivative Works 179+ that You distribute, all copyright, patent, trademark, and 180+ attribution notices from the Source form of the Work, 181+ excluding those notices that do not pertain to any part of 182+ the Derivative Works; and 183+ 184+ (d) If the Work includes a "NOTICE" text file as part of its 185+ distribution, then any Derivative Works that You distribute must 186+ include a readable copy of the attribution notices contained 187+ within such NOTICE file, excluding those notices that do not 188+ pertain to any part of the Derivative Works, in at least one 189+ of the following places: within a NOTICE text file distributed 190+ as part of the Derivative Works; within the Source form or 191+ documentation, if provided along with the Derivative Works; or, 192+ within a display generated by the Derivative Works, if and 193+ wherever such third-party notices normally appear. The contents 194+ of the NOTICE file are for informational purposes only and 195+ do not modify the License. You may add Your own attribution 196+ notices within Derivative Works that You distribute, alongside 197+ or as an addendum to the NOTICE text from the Work, provided 198+ that such additional attribution notices cannot be construed 199+ as modifying the License. 200+ 201+ You may add Your own copyright statement to Your modifications and 202+ may provide additional or different license terms and conditions 203+ for use, reproduction, or distribution of Your modifications, or 204+ for any such Derivative Works as a whole, provided Your use, 205+ reproduction, and distribution of the Work otherwise complies with 206+ the conditions stated in this License. 207+ 208+ 5. Submission of Contributions. Unless You explicitly state otherwise, 209+ any Contribution intentionally submitted for inclusion in the Work 210+ by You to the Licensor shall be under the terms and conditions of 211+ this License, without any additional terms or conditions. 212+ Notwithstanding the above, nothing herein shall supersede or modify 213+ the terms of any separate license agreement you may have executed 214+ with Licensor regarding such Contributions. 215+ 216+ 6. Trademarks. This License does not grant permission to use the trade 217+ names, trademarks, service marks, or product names of the Licensor, 218+ except as required for reasonable and customary use in describing the 219+ origin of the Work and reproducing the content of the NOTICE file. 220+ 221+ 7. Disclaimer of Warranty. Unless required by applicable law or 222+ agreed to in writing, Licensor provides the Work (and each 223+ Contributor provides its Contributions) on an "AS IS" BASIS, 224+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 225+ implied, including, without limitation, any warranties or conditions 226+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 227+ PARTICULAR PURPOSE. You are solely responsible for determining the 228+ appropriateness of using or redistributing the Work and assume any 229+ risks associated with Your exercise of permissions under this License. 230+ 231+ 8. Limitation of Liability. In no event and under no legal theory, 232+ whether in tort (including negligence), contract, or otherwise, 233+ unless required by applicable law (such as deliberate and grossly 234+ negligent acts) or agreed to in writing, shall any Contributor be 235+ liable to You for damages, including any direct, indirect, special, 236+ incidental, or consequential damages of any character arising as a 237+ result of this License or out of the use or inability to use the 238+ Work (including but not limited to damages for loss of goodwill, 239+ work stoppage, computer failure or malfunction, or any and all 240+ other commercial damages or losses), even if such Contributor 241+ has been advised of the possibility of such damages. 242+ 243+ 9. Accepting Warranty or Additional Liability. While redistributing 244+ the Work or Derivative Works thereof, You may choose to offer, 245+ and charge a fee for, acceptance of support, warranty, indemnity, 246+ or other liability obligations and/or rights consistent with this 247+ License. However, in accepting such obligations, You may act only 248+ on Your own behalf and on Your sole responsibility, not on behalf 249+ of any other Contributor, and only if You agree to indemnify, 250+ defend, and hold each Contributor harmless for any liability 251+ incurred by, or claims asserted against, such Contributor by reason 252+ of your accepting any such warranty or additional liability. 253+ 254+ END OF TERMS AND CONDITIONS 255+ 256diff --git a/benchmark/benchmark.cpp b/benchmark/benchmark.cpp 257new file mode 100755 258index 00000000..2a6440f4 259--- /dev/null 260+++ b/benchmark/benchmark.cpp 261@@ -0,0 +1,131 @@ 262+/* 263+ * Copyright (C) 2012 The Android Open Source Project 264+ * 265+ * Licensed under the Apache License, Version 2.0 (the "License"); 266+ * you may not use this file except in compliance with the License. 267+ * You may obtain a copy of the License at 268+ * 269+ * http://www.apache.org/licenses/LICENSE-2.0 270+ * 271+ * Unless required by applicable law or agreed to in writing, software 272+ * distributed under the License is distributed on an "AS IS" BASIS, 273+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 274+ * See the License for the specific language governing permissions and 275+ * limitations under the License. 276+ */ 277+ 278+#include <time.h> 279+#include <sys/types.h> 280+#include <sys/stat.h> 281+#include <unistd.h> 282+ 283+#include "mosaic/Mosaic.h" 284+#include "mosaic/ImageUtils.h" 285+ 286+#define MAX_FRAMES 200 287+#define KERNEL_ITERATIONS 10 288+ 289+const int blendingType = Blend::BLEND_TYPE_HORZ; 290+const int stripType = Blend::STRIP_TYPE_WIDE; 291+ 292+ImageType yvuFrames[MAX_FRAMES]; 293+ 294+int loadImages(const char* basename, int &width, int &height) 295+{ 296+ char filename[512]; 297+ struct stat filestat; 298+ int i; 299+ 300+ for (i = 0; i < MAX_FRAMES; i++) { 301+ sprintf(filename, "%s_%03d.ppm", basename, i + 1); 302+ if (stat(filename, &filestat) != 0) break; 303+ ImageType rgbFrame = ImageUtils::readBinaryPPM(filename, width, height); 304+ yvuFrames[i] = ImageUtils::allocateImage(width, height, 305+ ImageUtils::IMAGE_TYPE_NUM_CHANNELS); 306+ ImageUtils::rgb2yvu(yvuFrames[i], rgbFrame, width, height); 307+ ImageUtils::freeImage(rgbFrame); 308+ } 309+ return i; 310+} 311+ 312+int main(int argc, char **argv) 313+{ 314+ struct timespec t1, t2, t3; 315+ 316+ int width, height; 317+ float totalElapsedTime = 0; 318+ 319+ const char *basename; 320+ const char *filename; 321+ 322+ if (argc != 3) { 323+ printf("Usage: %s input_dir output_filename\n", argv[0]); 324+ return 0; 325+ } else { 326+ basename = argv[1]; 327+ filename = argv[2]; 328+ } 329+ 330+ // Load the images outside the computational kernel 331+ int totalFrames = loadImages(basename, width, height); 332+ 333+ if (totalFrames == 0) { 334+ printf("Image files not found. Make sure %s exists.\n", 335+ basename); 336+ return 1; 337+ } 338+ 339+ printf("%d frames loaded\n", totalFrames); 340+ 341+ 342+ // Interesting stuff is here 343+ for (int iteration = 0; iteration < KERNEL_ITERATIONS; iteration++) { 344+ Mosaic mosaic; 345+ 346+ mosaic.initialize(blendingType, stripType, width, height, -1, false, 0); 347+ 348+ clock_gettime(CLOCK_MONOTONIC, &t1); 349+ for (int i = 0; i < totalFrames; i++) { 350+ mosaic.addFrame(yvuFrames[i]); 351+ } 352+ clock_gettime(CLOCK_MONOTONIC, &t2); 353+ 354+ float progress = 0.0; 355+ bool cancelComputation = false; 356+ 357+ mosaic.createMosaic(progress, cancelComputation); 358+ 359+ int mosaicWidth, mosaicHeight; 360+ ImageType resultYVU = mosaic.getMosaic(mosaicWidth, mosaicHeight); 361+ 362+ ImageType imageRGB = ImageUtils::allocateImage( 363+ mosaicWidth, mosaicHeight, ImageUtils::IMAGE_TYPE_NUM_CHANNELS); 364+ 365+ clock_gettime(CLOCK_MONOTONIC, &t3); 366+ 367+ float elapsedTime = 368+ (t3.tv_sec - t1.tv_sec) + (t3.tv_nsec - t1.tv_nsec)/1e9; 369+ float addImageTime = 370+ (t2.tv_sec - t1.tv_sec) + (t2.tv_nsec - t1.tv_nsec)/1e9; 371+ float stitchImageTime = 372+ (t3.tv_sec - t2.tv_sec) + (t3.tv_nsec - t2.tv_nsec)/1e9; 373+ 374+ totalElapsedTime += elapsedTime; 375+ 376+ printf("Iteration %d: %dx%d moasic created: " 377+ "%.2f seconds (%.2f + %.2f)\n", 378+ iteration, mosaicWidth, mosaicHeight, 379+ elapsedTime, addImageTime, stitchImageTime); 380+ 381+ // Write the output only once for correctness check 382+ if (iteration == 0) { 383+ ImageUtils::yvu2rgb(imageRGB, resultYVU, mosaicWidth, 384+ mosaicHeight); 385+ ImageUtils::writeBinaryPPM(imageRGB, filename, mosaicWidth, 386+ mosaicHeight); 387+ } 388+ } 389+ printf("Total elapsed time: %.2f seconds\n", totalElapsedTime); 390+ 391+ return 0; 392+} 393diff --git a/benchmark/feature_mos/doc/Readme.txt b/benchmark/feature_mos/doc/Readme.txt 394new file mode 100644 395index 00000000..83ce165e 396--- /dev/null 397+++ b/benchmark/feature_mos/doc/Readme.txt 398@@ -0,0 +1,3 @@ 399+To generate the html docs, execute 400+doxygen feature_mos_API_doxyfile 401+ 402diff --git a/benchmark/feature_mos/doc/feature_mos_API_doxyfile b/benchmark/feature_mos/doc/feature_mos_API_doxyfile 403new file mode 100755 404index 00000000..dca8c8c0 405--- /dev/null 406+++ b/benchmark/feature_mos/doc/feature_mos_API_doxyfile 407@@ -0,0 +1,1557 @@ 408+# Doxyfile 1.6.1 409+ 410+# This file describes the settings to be used by the documentation system 411+# doxygen (www.doxygen.org) for a project 412+# 413+# All text after a hash (#) is considered a comment and will be ignored 414+# The format is: 415+# TAG = value [value, ...] 416+# For lists items can also be appended using: 417+# TAG += value [value, ...] 418+# Values that contain spaces should be placed between quotes (" ") 419+ 420+#--------------------------------------------------------------------------- 421+# Project related configuration options 422+#--------------------------------------------------------------------------- 423+ 424+# This tag specifies the encoding used for all characters in the config file 425+# that follow. The default is UTF-8 which is also the encoding used for all 426+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 427+# iconv built into libc) for the transcoding. See 428+# http://www.gnu.org/software/libiconv for the list of possible encodings. 429+ 430+DOXYFILE_ENCODING = UTF-8 431+ 432+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 433+# by quotes) that should identify the project. 434+ 435+PROJECT_NAME = 436+ 437+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 438+# This could be handy for archiving the generated documentation or 439+# if some version control system is used. 440+ 441+PROJECT_NUMBER = 442+ 443+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 444+# base path where the generated documentation will be put. 445+# If a relative path is entered, it will be relative to the location 446+# where doxygen was started. If left blank the current directory will be used. 447+ 448+OUTPUT_DIRECTORY = . 449+ 450+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 451+# 4096 sub-directories (in 2 levels) under the output directory of each output 452+# format and will distribute the generated files over these directories. 453+# Enabling this option can be useful when feeding doxygen a huge amount of 454+# source files, where putting all generated files in the same directory would 455+# otherwise cause performance problems for the file system. 456+ 457+CREATE_SUBDIRS = NO 458+ 459+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 460+# documentation generated by doxygen is written. Doxygen will use this 461+# information to generate all constant output in the proper language. 462+# The default language is English, other supported languages are: 463+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 464+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, 465+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English 466+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, 467+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, 468+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. 469+ 470+OUTPUT_LANGUAGE = English 471+ 472+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 473+# include brief member descriptions after the members that are listed in 474+# the file and class documentation (similar to JavaDoc). 475+# Set to NO to disable this. 476+ 477+BRIEF_MEMBER_DESC = YES 478+ 479+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 480+# the brief description of a member or function before the detailed description. 481+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 482+# brief descriptions will be completely suppressed. 483+ 484+REPEAT_BRIEF = YES 485+ 486+# This tag implements a quasi-intelligent brief description abbreviator 487+# that is used to form the text in various listings. Each string 488+# in this list, if found as the leading text of the brief description, will be 489+# stripped from the text and the result after processing the whole list, is 490+# used as the annotated text. Otherwise, the brief description is used as-is. 491+# If left blank, the following values are used ("$name" is automatically 492+# replaced with the name of the entity): "The $name class" "The $name widget" 493+# "The $name file" "is" "provides" "specifies" "contains" 494+# "represents" "a" "an" "the" 495+ 496+ABBREVIATE_BRIEF = "The $name class" \ 497+ "The $name widget" \ 498+ "The $name file" \ 499+ is \ 500+ provides \ 501+ specifies \ 502+ contains \ 503+ represents \ 504+ a \ 505+ an \ 506+ the 507+ 508+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 509+# Doxygen will generate a detailed section even if there is only a brief 510+# description. 511+ 512+ALWAYS_DETAILED_SEC = NO 513+ 514+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 515+# inherited members of a class in the documentation of that class as if those 516+# members were ordinary class members. Constructors, destructors and assignment 517+# operators of the base classes will not be shown. 518+ 519+INLINE_INHERITED_MEMB = NO 520+ 521+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 522+# path before files name in the file list and in the header files. If set 523+# to NO the shortest path that makes the file name unique will be used. 524+ 525+FULL_PATH_NAMES = YES 526+ 527+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 528+# can be used to strip a user-defined part of the path. Stripping is 529+# only done if one of the specified strings matches the left-hand part of 530+# the path. The tag can be used to show relative paths in the file list. 531+# If left blank the directory from which doxygen is run is used as the 532+# path to strip. 533+ 534+STRIP_FROM_PATH = /Users/dimitri/doxygen/mail/1.5.7/doxywizard/ 535+ 536+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 537+# the path mentioned in the documentation of a class, which tells 538+# the reader which header file to include in order to use a class. 539+# If left blank only the name of the header file containing the class 540+# definition is used. Otherwise one should specify the include paths that 541+# are normally passed to the compiler using the -I flag. 542+ 543+STRIP_FROM_INC_PATH = 544+ 545+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 546+# (but less readable) file names. This can be useful is your file systems 547+# doesn't support long names like on DOS, Mac, or CD-ROM. 548+ 549+SHORT_NAMES = NO 550+ 551+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 552+# will interpret the first line (until the first dot) of a JavaDoc-style 553+# comment as the brief description. If set to NO, the JavaDoc 554+# comments will behave just like regular Qt-style comments 555+# (thus requiring an explicit @brief command for a brief description.) 556+ 557+JAVADOC_AUTOBRIEF = NO 558+ 559+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 560+# interpret the first line (until the first dot) of a Qt-style 561+# comment as the brief description. If set to NO, the comments 562+# will behave just like regular Qt-style comments (thus requiring 563+# an explicit \brief command for a brief description.) 564+ 565+QT_AUTOBRIEF = NO 566+ 567+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 568+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 569+# comments) as a brief description. This used to be the default behaviour. 570+# The new default is to treat a multi-line C++ comment block as a detailed 571+# description. Set this tag to YES if you prefer the old behaviour instead. 572+ 573+MULTILINE_CPP_IS_BRIEF = NO 574+ 575+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 576+# member inherits the documentation from any documented member that it 577+# re-implements. 578+ 579+INHERIT_DOCS = YES 580+ 581+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 582+# a new page for each member. If set to NO, the documentation of a member will 583+# be part of the file/class/namespace that contains it. 584+ 585+SEPARATE_MEMBER_PAGES = NO 586+ 587+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 588+# Doxygen uses this value to replace tabs by spaces in code fragments. 589+ 590+TAB_SIZE = 8 591+ 592+# This tag can be used to specify a number of aliases that acts 593+# as commands in the documentation. An alias has the form "name=value". 594+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 595+# put the command \sideeffect (or @sideeffect) in the documentation, which 596+# will result in a user-defined paragraph with heading "Side Effects:". 597+# You can put \n's in the value part of an alias to insert newlines. 598+ 599+ALIASES = 600+ 601+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 602+# sources only. Doxygen will then generate output that is more tailored for C. 603+# For instance, some of the names that are used will be different. The list 604+# of all members will be omitted, etc. 605+ 606+OPTIMIZE_OUTPUT_FOR_C = NO 607+ 608+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 609+# sources only. Doxygen will then generate output that is more tailored for 610+# Java. For instance, namespaces will be presented as packages, qualified 611+# scopes will look different, etc. 612+ 613+OPTIMIZE_OUTPUT_JAVA = NO 614+ 615+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 616+# sources only. Doxygen will then generate output that is more tailored for 617+# Fortran. 618+ 619+OPTIMIZE_FOR_FORTRAN = NO 620+ 621+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 622+# sources. Doxygen will then generate output that is tailored for 623+# VHDL. 624+ 625+OPTIMIZE_OUTPUT_VHDL = NO 626+ 627+# Doxygen selects the parser to use depending on the extension of the files it parses. 628+# With this tag you can assign which parser to use for a given extension. 629+# Doxygen has a built-in mapping, but you can override or extend it using this tag. 630+# The format is ext=language, where ext is a file extension, and language is one of 631+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, 632+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat 633+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), 634+# use: inc=Fortran f=C. Note that for custom extensions you also need to set 635+# FILE_PATTERNS otherwise the files are not read by doxygen. 636+ 637+EXTENSION_MAPPING = 638+ 639+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 640+# to include (a tag file for) the STL sources as input, then you should 641+# set this tag to YES in order to let doxygen match functions declarations and 642+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 643+# func(std::string) {}). This also make the inheritance and collaboration 644+# diagrams that involve STL classes more complete and accurate. 645+ 646+BUILTIN_STL_SUPPORT = NO 647+ 648+# If you use Microsoft's C++/CLI language, you should set this option to YES to 649+# enable parsing support. 650+ 651+CPP_CLI_SUPPORT = NO 652+ 653+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 654+# Doxygen will parse them like normal C++ but will assume all classes use public 655+# instead of private inheritance when no explicit protection keyword is present. 656+ 657+SIP_SUPPORT = NO 658+ 659+# For Microsoft's IDL there are propget and propput attributes to indicate getter 660+# and setter methods for a property. Setting this option to YES (the default) 661+# will make doxygen to replace the get and set methods by a property in the 662+# documentation. This will only work if the methods are indeed getting or 663+# setting a simple type. If this is not the case, or you want to show the 664+# methods anyway, you should set this option to NO. 665+ 666+IDL_PROPERTY_SUPPORT = YES 667+ 668+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 669+# tag is set to YES, then doxygen will reuse the documentation of the first 670+# member in the group (if any) for the other members of the group. By default 671+# all members of a group must be documented explicitly. 672+ 673+DISTRIBUTE_GROUP_DOC = NO 674+ 675+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 676+# the same type (for instance a group of public functions) to be put as a 677+# subgroup of that type (e.g. under the Public Functions section). Set it to 678+# NO to prevent subgrouping. Alternatively, this can be done per class using 679+# the \nosubgrouping command. 680+ 681+SUBGROUPING = YES 682+ 683+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 684+# is documented as struct, union, or enum with the name of the typedef. So 685+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 686+# with name TypeT. When disabled the typedef will appear as a member of a file, 687+# namespace, or class. And the struct will be named TypeS. This can typically 688+# be useful for C code in case the coding convention dictates that all compound 689+# types are typedef'ed and only the typedef is referenced, never the tag name. 690+ 691+TYPEDEF_HIDES_STRUCT = NO 692+ 693+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 694+# determine which symbols to keep in memory and which to flush to disk. 695+# When the cache is full, less often used symbols will be written to disk. 696+# For small to medium size projects (<1000 input files) the default value is 697+# probably good enough. For larger projects a too small cache size can cause 698+# doxygen to be busy swapping symbols to and from disk most of the time 699+# causing a significant performance penality. 700+# If the system has enough physical memory increasing the cache will improve the 701+# performance by keeping more symbols in memory. Note that the value works on 702+# a logarithmic scale so increasing the size by one will rougly double the 703+# memory usage. The cache size is given by this formula: 704+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 705+# corresponding to a cache size of 2^16 = 65536 symbols 706+ 707+SYMBOL_CACHE_SIZE = 0 708+ 709+#--------------------------------------------------------------------------- 710+# Build related configuration options 711+#--------------------------------------------------------------------------- 712+ 713+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 714+# documentation are documented, even if no documentation was available. 715+# Private class members and static file members will be hidden unless 716+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES 717+ 718+EXTRACT_ALL = NO 719+ 720+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 721+# will be included in the documentation. 722+ 723+EXTRACT_PRIVATE = NO 724+ 725+# If the EXTRACT_STATIC tag is set to YES all static members of a file 726+# will be included in the documentation. 727+ 728+EXTRACT_STATIC = NO 729+ 730+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 731+# defined locally in source files will be included in the documentation. 732+# If set to NO only classes defined in header files are included. 733+ 734+EXTRACT_LOCAL_CLASSES = YES 735+ 736+# This flag is only useful for Objective-C code. When set to YES local 737+# methods, which are defined in the implementation section but not in 738+# the interface are included in the documentation. 739+# If set to NO (the default) only methods in the interface are included. 740+ 741+EXTRACT_LOCAL_METHODS = NO 742+ 743+# If this flag is set to YES, the members of anonymous namespaces will be 744+# extracted and appear in the documentation as a namespace called 745+# 'anonymous_namespace{file}', where file will be replaced with the base 746+# name of the file that contains the anonymous namespace. By default 747+# anonymous namespace are hidden. 748+ 749+EXTRACT_ANON_NSPACES = NO 750+ 751+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 752+# undocumented members of documented classes, files or namespaces. 753+# If set to NO (the default) these members will be included in the 754+# various overviews, but no documentation section is generated. 755+# This option has no effect if EXTRACT_ALL is enabled. 756+ 757+HIDE_UNDOC_MEMBERS = NO 758+ 759+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 760+# undocumented classes that are normally visible in the class hierarchy. 761+# If set to NO (the default) these classes will be included in the various 762+# overviews. This option has no effect if EXTRACT_ALL is enabled. 763+ 764+HIDE_UNDOC_CLASSES = NO 765+ 766+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 767+# friend (class|struct|union) declarations. 768+# If set to NO (the default) these declarations will be included in the 769+# documentation. 770+ 771+HIDE_FRIEND_COMPOUNDS = NO 772+ 773+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 774+# documentation blocks found inside the body of a function. 775+# If set to NO (the default) these blocks will be appended to the 776+# function's detailed documentation block. 777+ 778+HIDE_IN_BODY_DOCS = NO 779+ 780+# The INTERNAL_DOCS tag determines if documentation 781+# that is typed after a \internal command is included. If the tag is set 782+# to NO (the default) then the documentation will be excluded. 783+# Set it to YES to include the internal documentation. 784+ 785+INTERNAL_DOCS = NO 786+ 787+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 788+# file names in lower-case letters. If set to YES upper-case letters are also 789+# allowed. This is useful if you have classes or files whose names only differ 790+# in case and if your file system supports case sensitive file names. Windows 791+# and Mac users are advised to set this option to NO. 792+ 793+CASE_SENSE_NAMES = NO 794+ 795+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 796+# will show members with their full class and namespace scopes in the 797+# documentation. If set to YES the scope will be hidden. 798+ 799+HIDE_SCOPE_NAMES = NO 800+ 801+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 802+# will put a list of the files that are included by a file in the documentation 803+# of that file. 804+ 805+SHOW_INCLUDE_FILES = YES 806+ 807+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 808+# is inserted in the documentation for inline members. 809+ 810+INLINE_INFO = YES 811+ 812+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 813+# will sort the (detailed) documentation of file and class members 814+# alphabetically by member name. If set to NO the members will appear in 815+# declaration order. 816+ 817+SORT_MEMBER_DOCS = YES 818+ 819+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 820+# brief documentation of file, namespace and class members alphabetically 821+# by member name. If set to NO (the default) the members will appear in 822+# declaration order. 823+ 824+SORT_BRIEF_DOCS = NO 825+ 826+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen 827+# will sort the (brief and detailed) documentation of class members so that 828+# constructors and destructors are listed first. If set to NO (the default) 829+# the constructors will appear in the respective orders defined by 830+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. 831+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO 832+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. 833+ 834+SORT_MEMBERS_CTORS_1ST = NO 835+ 836+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 837+# hierarchy of group names into alphabetical order. If set to NO (the default) 838+# the group names will appear in their defined order. 839+ 840+SORT_GROUP_NAMES = NO 841+ 842+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 843+# sorted by fully-qualified names, including namespaces. If set to 844+# NO (the default), the class list will be sorted only by class name, 845+# not including the namespace part. 846+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 847+# Note: This option applies only to the class list, not to the 848+# alphabetical list. 849+ 850+SORT_BY_SCOPE_NAME = NO 851+ 852+# The GENERATE_TODOLIST tag can be used to enable (YES) or 853+# disable (NO) the todo list. This list is created by putting \todo 854+# commands in the documentation. 855+ 856+GENERATE_TODOLIST = YES 857+ 858+# The GENERATE_TESTLIST tag can be used to enable (YES) or 859+# disable (NO) the test list. This list is created by putting \test 860+# commands in the documentation. 861+ 862+GENERATE_TESTLIST = YES 863+ 864+# The GENERATE_BUGLIST tag can be used to enable (YES) or 865+# disable (NO) the bug list. This list is created by putting \bug 866+# commands in the documentation. 867+ 868+GENERATE_BUGLIST = YES 869+ 870+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 871+# disable (NO) the deprecated list. This list is created by putting 872+# \deprecated commands in the documentation. 873+ 874+GENERATE_DEPRECATEDLIST= YES 875+ 876+# The ENABLED_SECTIONS tag can be used to enable conditional 877+# documentation sections, marked by \if sectionname ... \endif. 878+ 879+ENABLED_SECTIONS = 880+ 881+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 882+# the initial value of a variable or define consists of for it to appear in 883+# the documentation. If the initializer consists of more lines than specified 884+# here it will be hidden. Use a value of 0 to hide initializers completely. 885+# The appearance of the initializer of individual variables and defines in the 886+# documentation can be controlled using \showinitializer or \hideinitializer 887+# command in the documentation regardless of this setting. 888+ 889+MAX_INITIALIZER_LINES = 30 890+ 891+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 892+# at the bottom of the documentation of classes and structs. If set to YES the 893+# list will mention the files that were used to generate the documentation. 894+ 895+SHOW_USED_FILES = YES 896+ 897+# If the sources in your project are distributed over multiple directories 898+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 899+# in the documentation. The default is NO. 900+ 901+SHOW_DIRECTORIES = NO 902+ 903+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 904+# This will remove the Files entry from the Quick Index and from the 905+# Folder Tree View (if specified). The default is YES. 906+ 907+SHOW_FILES = YES 908+ 909+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 910+# Namespaces page. This will remove the Namespaces entry from the Quick Index 911+# and from the Folder Tree View (if specified). The default is YES. 912+ 913+SHOW_NAMESPACES = YES 914+ 915+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 916+# doxygen should invoke to get the current version for each file (typically from 917+# the version control system). Doxygen will invoke the program by executing (via 918+# popen()) the command <command> <input-file>, where <command> is the value of 919+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 920+# provided by doxygen. Whatever the program writes to standard output 921+# is used as the file version. See the manual for examples. 922+ 923+FILE_VERSION_FILTER = 924+ 925+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by 926+# doxygen. The layout file controls the global structure of the generated output files 927+# in an output format independent way. The create the layout file that represents 928+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a 929+# file name after the option, if omitted DoxygenLayout.xml will be used as the name 930+# of the layout file. 931+ 932+LAYOUT_FILE = 933+ 934+#--------------------------------------------------------------------------- 935+# configuration options related to warning and progress messages 936+#--------------------------------------------------------------------------- 937+ 938+# The QUIET tag can be used to turn on/off the messages that are generated 939+# by doxygen. Possible values are YES and NO. If left blank NO is used. 940+ 941+QUIET = NO 942+ 943+# The WARNINGS tag can be used to turn on/off the warning messages that are 944+# generated by doxygen. Possible values are YES and NO. If left blank 945+# NO is used. 946+ 947+WARNINGS = YES 948+ 949+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 950+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 951+# automatically be disabled. 952+ 953+WARN_IF_UNDOCUMENTED = YES 954+ 955+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 956+# potential errors in the documentation, such as not documenting some 957+# parameters in a documented function, or documenting parameters that 958+# don't exist or using markup commands wrongly. 959+ 960+WARN_IF_DOC_ERROR = YES 961+ 962+# This WARN_NO_PARAMDOC option can be abled to get warnings for 963+# functions that are documented, but have no documentation for their parameters 964+# or return value. If set to NO (the default) doxygen will only warn about 965+# wrong or incomplete parameter documentation, but not about the absence of 966+# documentation. 967+ 968+WARN_NO_PARAMDOC = NO 969+ 970+# The WARN_FORMAT tag determines the format of the warning messages that 971+# doxygen can produce. The string should contain the $file, $line, and $text 972+# tags, which will be replaced by the file and line number from which the 973+# warning originated and the warning text. Optionally the format may contain 974+# $version, which will be replaced by the version of the file (if it could 975+# be obtained via FILE_VERSION_FILTER) 976+ 977+WARN_FORMAT = "$file:$line: $text" 978+ 979+# The WARN_LOGFILE tag can be used to specify a file to which warning 980+# and error messages should be written. If left blank the output is written 981+# to stderr. 982+ 983+WARN_LOGFILE = 984+ 985+#--------------------------------------------------------------------------- 986+# configuration options related to the input files 987+#--------------------------------------------------------------------------- 988+ 989+# The INPUT tag can be used to specify the files and/or directories that contain 990+# documented source files. You may enter file names like "myfile.cpp" or 991+# directories like "/usr/src/myproject". Separate the files or directories 992+# with spaces. 993+ 994+INPUT = ../src/mosaic/Mosaic.h 995+ 996+# This tag can be used to specify the character encoding of the source files 997+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 998+# also the default input encoding. Doxygen uses libiconv (or the iconv built 999+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 1000+# the list of possible encodings. 1001+ 1002+INPUT_ENCODING = UTF-8 1003+ 1004+# If the value of the INPUT tag contains directories, you can use the 1005+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 1006+# and *.h) to filter out the source-files in the directories. If left 1007+# blank the following patterns are tested: 1008+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 1009+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 1010+ 1011+FILE_PATTERNS = *.c \ 1012+ *.cc \ 1013+ *.cxx \ 1014+ *.cpp \ 1015+ *.c++ \ 1016+ *.d \ 1017+ *.java \ 1018+ *.ii \ 1019+ *.ixx \ 1020+ *.ipp \ 1021+ *.i++ \ 1022+ *.inl \ 1023+ *.h \ 1024+ *.hh \ 1025+ *.hxx \ 1026+ *.hpp \ 1027+ *.h++ \ 1028+ *.idl \ 1029+ *.odl \ 1030+ *.cs \ 1031+ *.php \ 1032+ *.php3 \ 1033+ *.inc \ 1034+ *.m \ 1035+ *.mm \ 1036+ *.dox \ 1037+ *.py \ 1038+ *.f90 \ 1039+ *.f \ 1040+ *.vhd \ 1041+ *.vhdl 1042+ 1043+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 1044+# should be searched for input files as well. Possible values are YES and NO. 1045+# If left blank NO is used. 1046+ 1047+RECURSIVE = NO 1048+ 1049+# The EXCLUDE tag can be used to specify files and/or directories that should 1050+# excluded from the INPUT source files. This way you can easily exclude a 1051+# subdirectory from a directory tree whose root is specified with the INPUT tag. 1052+ 1053+EXCLUDE = 1054+ 1055+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 1056+# directories that are symbolic links (a Unix filesystem feature) are excluded 1057+# from the input. 1058+ 1059+EXCLUDE_SYMLINKS = NO 1060+ 1061+# If the value of the INPUT tag contains directories, you can use the 1062+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 1063+# certain files from those directories. Note that the wildcards are matched 1064+# against the file with absolute path, so to exclude all test directories 1065+# for example use the pattern */test/* 1066+ 1067+EXCLUDE_PATTERNS = 1068+ 1069+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 1070+# (namespaces, classes, functions, etc.) that should be excluded from the 1071+# output. The symbol name can be a fully qualified name, a word, or if the 1072+# wildcard * is used, a substring. Examples: ANamespace, AClass, 1073+# AClass::ANamespace, ANamespace::*Test 1074+ 1075+EXCLUDE_SYMBOLS = 1076+ 1077+# The EXAMPLE_PATH tag can be used to specify one or more files or 1078+# directories that contain example code fragments that are included (see 1079+# the \include command). 1080+ 1081+EXAMPLE_PATH = 1082+ 1083+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 1084+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 1085+# and *.h) to filter out the source-files in the directories. If left 1086+# blank all files are included. 1087+ 1088+EXAMPLE_PATTERNS = * 1089+ 1090+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 1091+# searched for input files to be used with the \include or \dontinclude 1092+# commands irrespective of the value of the RECURSIVE tag. 1093+# Possible values are YES and NO. If left blank NO is used. 1094+ 1095+EXAMPLE_RECURSIVE = NO 1096+ 1097+# The IMAGE_PATH tag can be used to specify one or more files or 1098+# directories that contain image that are included in the documentation (see 1099+# the \image command). 1100+ 1101+IMAGE_PATH = 1102+ 1103+# The INPUT_FILTER tag can be used to specify a program that doxygen should 1104+# invoke to filter for each input file. Doxygen will invoke the filter program 1105+# by executing (via popen()) the command <filter> <input-file>, where <filter> 1106+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 1107+# input file. Doxygen will then use the output that the filter program writes 1108+# to standard output. If FILTER_PATTERNS is specified, this tag will be 1109+# ignored. 1110+ 1111+INPUT_FILTER = 1112+ 1113+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 1114+# basis. Doxygen will compare the file name with each pattern and apply the 1115+# filter if there is a match. The filters are a list of the form: 1116+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 1117+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 1118+# is applied to all files. 1119+ 1120+FILTER_PATTERNS = 1121+ 1122+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 1123+# INPUT_FILTER) will be used to filter the input files when producing source 1124+# files to browse (i.e. when SOURCE_BROWSER is set to YES). 1125+ 1126+FILTER_SOURCE_FILES = NO 1127+ 1128+#--------------------------------------------------------------------------- 1129+# configuration options related to source browsing 1130+#--------------------------------------------------------------------------- 1131+ 1132+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 1133+# be generated. Documented entities will be cross-referenced with these sources. 1134+# Note: To get rid of all source code in the generated output, make sure also 1135+# VERBATIM_HEADERS is set to NO. 1136+ 1137+SOURCE_BROWSER = NO 1138+ 1139+# Setting the INLINE_SOURCES tag to YES will include the body 1140+# of functions and classes directly in the documentation. 1141+ 1142+INLINE_SOURCES = NO 1143+ 1144+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 1145+# doxygen to hide any special comment blocks from generated source code 1146+# fragments. Normal C and C++ comments will always remain visible. 1147+ 1148+STRIP_CODE_COMMENTS = YES 1149+ 1150+# If the REFERENCED_BY_RELATION tag is set to YES 1151+# then for each documented function all documented 1152+# functions referencing it will be listed. 1153+ 1154+REFERENCED_BY_RELATION = NO 1155+ 1156+# If the REFERENCES_RELATION tag is set to YES 1157+# then for each documented function all documented entities 1158+# called/used by that function will be listed. 1159+ 1160+REFERENCES_RELATION = NO 1161+ 1162+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 1163+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 1164+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 1165+# link to the source code. Otherwise they will link to the documentation. 1166+ 1167+REFERENCES_LINK_SOURCE = YES 1168+ 1169+# If the USE_HTAGS tag is set to YES then the references to source code 1170+# will point to the HTML generated by the htags(1) tool instead of doxygen 1171+# built-in source browser. The htags tool is part of GNU's global source 1172+# tagging system (see http://www.gnu.org/software/global/global.html). You 1173+# will need version 4.8.6 or higher. 1174+ 1175+USE_HTAGS = NO 1176+ 1177+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 1178+# will generate a verbatim copy of the header file for each class for 1179+# which an include is specified. Set to NO to disable this. 1180+ 1181+VERBATIM_HEADERS = YES 1182+ 1183+#--------------------------------------------------------------------------- 1184+# configuration options related to the alphabetical class index 1185+#--------------------------------------------------------------------------- 1186+ 1187+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 1188+# of all compounds will be generated. Enable this if the project 1189+# contains a lot of classes, structs, unions or interfaces. 1190+ 1191+ALPHABETICAL_INDEX = NO 1192+ 1193+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 1194+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 1195+# in which this list will be split (can be a number in the range [1..20]) 1196+ 1197+COLS_IN_ALPHA_INDEX = 5 1198+ 1199+# In case all classes in a project start with a common prefix, all 1200+# classes will be put under the same header in the alphabetical index. 1201+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 1202+# should be ignored while generating the index headers. 1203+ 1204+IGNORE_PREFIX = 1205+ 1206+#--------------------------------------------------------------------------- 1207+# configuration options related to the HTML output 1208+#--------------------------------------------------------------------------- 1209+ 1210+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 1211+# generate HTML output. 1212+ 1213+GENERATE_HTML = YES 1214+ 1215+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 1216+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 1217+# put in front of it. If left blank `html' will be used as the default path. 1218+ 1219+HTML_OUTPUT = html 1220+ 1221+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 1222+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 1223+# doxygen will generate files with .html extension. 1224+ 1225+HTML_FILE_EXTENSION = .html 1226+ 1227+# The HTML_HEADER tag can be used to specify a personal HTML header for 1228+# each generated HTML page. If it is left blank doxygen will generate a 1229+# standard header. 1230+ 1231+HTML_HEADER = 1232+ 1233+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 1234+# each generated HTML page. If it is left blank doxygen will generate a 1235+# standard footer. 1236+ 1237+HTML_FOOTER = 1238+ 1239+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 1240+# style sheet that is used by each HTML page. It can be used to 1241+# fine-tune the look of the HTML output. If the tag is left blank doxygen 1242+# will generate a default style sheet. Note that doxygen will try to copy 1243+# the style sheet file to the HTML output directory, so don't put your own 1244+# stylesheet in the HTML output directory as well, or it will be erased! 1245+ 1246+HTML_STYLESHEET = 1247+ 1248+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 1249+# files or namespaces will be aligned in HTML using tables. If set to 1250+# NO a bullet list will be used. 1251+ 1252+HTML_ALIGN_MEMBERS = YES 1253+ 1254+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 1255+# documentation will contain sections that can be hidden and shown after the 1256+# page has loaded. For this to work a browser that supports 1257+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 1258+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). 1259+ 1260+HTML_DYNAMIC_SECTIONS = NO 1261+ 1262+# If the GENERATE_DOCSET tag is set to YES, additional index files 1263+# will be generated that can be used as input for Apple's Xcode 3 1264+# integrated development environment, introduced with OSX 10.5 (Leopard). 1265+# To create a documentation set, doxygen will generate a Makefile in the 1266+# HTML output directory. Running make will produce the docset in that 1267+# directory and running "make install" will install the docset in 1268+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 1269+# it at startup. 1270+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. 1271+ 1272+GENERATE_DOCSET = NO 1273+ 1274+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 1275+# feed. A documentation feed provides an umbrella under which multiple 1276+# documentation sets from a single provider (such as a company or product suite) 1277+# can be grouped. 1278+ 1279+DOCSET_FEEDNAME = "Doxygen generated docs" 1280+ 1281+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 1282+# should uniquely identify the documentation set bundle. This should be a 1283+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 1284+# will append .docset to the name. 1285+ 1286+DOCSET_BUNDLE_ID = org.doxygen.Project 1287+ 1288+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 1289+# will be generated that can be used as input for tools like the 1290+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 1291+# of the generated HTML documentation. 1292+ 1293+GENERATE_HTMLHELP = NO 1294+ 1295+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 1296+# be used to specify the file name of the resulting .chm file. You 1297+# can add a path in front of the file if the result should not be 1298+# written to the html output directory. 1299+ 1300+CHM_FILE = 1301+ 1302+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 1303+# be used to specify the location (absolute path including file name) of 1304+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 1305+# the HTML help compiler on the generated index.hhp. 1306+ 1307+HHC_LOCATION = 1308+ 1309+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 1310+# controls if a separate .chi index file is generated (YES) or that 1311+# it should be included in the master .chm file (NO). 1312+ 1313+GENERATE_CHI = NO 1314+ 1315+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 1316+# is used to encode HtmlHelp index (hhk), content (hhc) and project file 1317+# content. 1318+ 1319+CHM_INDEX_ENCODING = 1320+ 1321+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 1322+# controls whether a binary table of contents is generated (YES) or a 1323+# normal table of contents (NO) in the .chm file. 1324+ 1325+BINARY_TOC = NO 1326+ 1327+# The TOC_EXPAND flag can be set to YES to add extra items for group members 1328+# to the contents of the HTML help documentation and to the tree view. 1329+ 1330+TOC_EXPAND = NO 1331+ 1332+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER 1333+# are set, an additional index file will be generated that can be used as input for 1334+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated 1335+# HTML documentation. 1336+ 1337+GENERATE_QHP = NO 1338+ 1339+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 1340+# be used to specify the file name of the resulting .qch file. 1341+# The path specified is relative to the HTML output folder. 1342+ 1343+QCH_FILE = 1344+ 1345+# The QHP_NAMESPACE tag specifies the namespace to use when generating 1346+# Qt Help Project output. For more information please see 1347+# http://doc.trolltech.com/qthelpproject.html#namespace 1348+ 1349+QHP_NAMESPACE = 1350+ 1351+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 1352+# Qt Help Project output. For more information please see 1353+# http://doc.trolltech.com/qthelpproject.html#virtual-folders 1354+ 1355+QHP_VIRTUAL_FOLDER = doc 1356+ 1357+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. 1358+# For more information please see 1359+# http://doc.trolltech.com/qthelpproject.html#custom-filters 1360+ 1361+QHP_CUST_FILTER_NAME = 1362+ 1363+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see 1364+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>. 1365+ 1366+QHP_CUST_FILTER_ATTRS = 1367+ 1368+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's 1369+# filter section matches. 1370+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>. 1371+ 1372+QHP_SECT_FILTER_ATTRS = 1373+ 1374+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 1375+# be used to specify the location of Qt's qhelpgenerator. 1376+# If non-empty doxygen will try to run qhelpgenerator on the generated 1377+# .qhp file. 1378+ 1379+QHG_LOCATION = 1380+ 1381+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 1382+# top of each HTML page. The value NO (the default) enables the index and 1383+# the value YES disables it. 1384+ 1385+DISABLE_INDEX = NO 1386+ 1387+# This tag can be used to set the number of enum values (range [1..20]) 1388+# that doxygen will group on one line in the generated HTML documentation. 1389+ 1390+ENUM_VALUES_PER_LINE = 4 1391+ 1392+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 1393+# structure should be generated to display hierarchical information. 1394+# If the tag value is set to YES, a side panel will be generated 1395+# containing a tree-like index structure (just like the one that 1396+# is generated for HTML Help). For this to work a browser that supports 1397+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 1398+# Windows users are probably better off using the HTML help feature. 1399+ 1400+GENERATE_TREEVIEW = NO 1401+ 1402+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, 1403+# and Class Hierarchy pages using a tree view instead of an ordered list. 1404+ 1405+USE_INLINE_TREES = NO 1406+ 1407+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 1408+# used to set the initial width (in pixels) of the frame in which the tree 1409+# is shown. 1410+ 1411+TREEVIEW_WIDTH = 250 1412+ 1413+# Use this tag to change the font size of Latex formulas included 1414+# as images in the HTML documentation. The default is 10. Note that 1415+# when you change the font size after a successful doxygen run you need 1416+# to manually remove any form_*.png images from the HTML output directory 1417+# to force them to be regenerated. 1418+ 1419+FORMULA_FONTSIZE = 10 1420+ 1421+# When the SEARCHENGINE tag is enable doxygen will generate a search box 1422+# for the HTML output. The underlying search engine uses javascript 1423+# and DHTML and should work on any modern browser. Note that when using 1424+# HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) 1425+# there is already a search function so this one should typically 1426+# be disabled. 1427+ 1428+SEARCHENGINE = YES 1429+ 1430+#--------------------------------------------------------------------------- 1431+# configuration options related to the LaTeX output 1432+#--------------------------------------------------------------------------- 1433+ 1434+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 1435+# generate Latex output. 1436+ 1437+GENERATE_LATEX = NO 1438+ 1439+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 1440+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 1441+# put in front of it. If left blank `latex' will be used as the default path. 1442+ 1443+LATEX_OUTPUT = latex 1444+ 1445+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 1446+# invoked. If left blank `latex' will be used as the default command name. 1447+ 1448+LATEX_CMD_NAME = latex 1449+ 1450+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 1451+# generate index for LaTeX. If left blank `makeindex' will be used as the 1452+# default command name. 1453+ 1454+MAKEINDEX_CMD_NAME = makeindex 1455+ 1456+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 1457+# LaTeX documents. This may be useful for small projects and may help to 1458+# save some trees in general. 1459+ 1460+COMPACT_LATEX = NO 1461+ 1462+# The PAPER_TYPE tag can be used to set the paper type that is used 1463+# by the printer. Possible values are: a4, a4wide, letter, legal and 1464+# executive. If left blank a4wide will be used. 1465+ 1466+PAPER_TYPE = a4wide 1467+ 1468+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 1469+# packages that should be included in the LaTeX output. 1470+ 1471+EXTRA_PACKAGES = 1472+ 1473+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 1474+# the generated latex document. The header should contain everything until 1475+# the first chapter. If it is left blank doxygen will generate a 1476+# standard header. Notice: only use this tag if you know what you are doing! 1477+ 1478+LATEX_HEADER = 1479+ 1480+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 1481+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 1482+# contain links (just like the HTML output) instead of page references 1483+# This makes the output suitable for online browsing using a pdf viewer. 1484+ 1485+PDF_HYPERLINKS = YES 1486+ 1487+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 1488+# plain latex in the generated Makefile. Set this option to YES to get a 1489+# higher quality PDF documentation. 1490+ 1491+USE_PDFLATEX = YES 1492+ 1493+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 1494+# command to the generated LaTeX files. This will instruct LaTeX to keep 1495+# running if errors occur, instead of asking the user for help. 1496+# This option is also used when generating formulas in HTML. 1497+ 1498+LATEX_BATCHMODE = NO 1499+ 1500+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 1501+# include the index chapters (such as File Index, Compound Index, etc.) 1502+# in the output. 1503+ 1504+LATEX_HIDE_INDICES = NO 1505+ 1506+# If LATEX_SOURCE_CODE is set to YES then doxygen will include 1507+# source code with syntax highlighting in the LaTeX output. 1508+# Note that which sources are shown also depends on other settings 1509+# such as SOURCE_BROWSER. 1510+ 1511+LATEX_SOURCE_CODE = NO 1512+ 1513+#--------------------------------------------------------------------------- 1514+# configuration options related to the RTF output 1515+#--------------------------------------------------------------------------- 1516+ 1517+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 1518+# The RTF output is optimized for Word 97 and may not look very pretty with 1519+# other RTF readers or editors. 1520+ 1521+GENERATE_RTF = NO 1522+ 1523+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 1524+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 1525+# put in front of it. If left blank `rtf' will be used as the default path. 1526+ 1527+RTF_OUTPUT = rtf 1528+ 1529+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 1530+# RTF documents. This may be useful for small projects and may help to 1531+# save some trees in general. 1532+ 1533+COMPACT_RTF = NO 1534+ 1535+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 1536+# will contain hyperlink fields. The RTF file will 1537+# contain links (just like the HTML output) instead of page references. 1538+# This makes the output suitable for online browsing using WORD or other 1539+# programs which support those fields. 1540+# Note: wordpad (write) and others do not support links. 1541+ 1542+RTF_HYPERLINKS = NO 1543+ 1544+# Load stylesheet definitions from file. Syntax is similar to doxygen's 1545+# config file, i.e. a series of assignments. You only have to provide 1546+# replacements, missing definitions are set to their default value. 1547+ 1548+RTF_STYLESHEET_FILE = 1549+ 1550+# Set optional variables used in the generation of an rtf document. 1551+# Syntax is similar to doxygen's config file. 1552+ 1553+RTF_EXTENSIONS_FILE = 1554+ 1555+#--------------------------------------------------------------------------- 1556+# configuration options related to the man page output 1557+#--------------------------------------------------------------------------- 1558+ 1559+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 1560+# generate man pages 1561+ 1562+GENERATE_MAN = NO 1563+ 1564+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 1565+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 1566+# put in front of it. If left blank `man' will be used as the default path. 1567+ 1568+MAN_OUTPUT = man 1569+ 1570+# The MAN_EXTENSION tag determines the extension that is added to 1571+# the generated man pages (default is the subroutine's section .3) 1572+ 1573+MAN_EXTENSION = .3 1574+ 1575+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 1576+# then it will generate one additional man file for each entity 1577+# documented in the real man page(s). These additional files 1578+# only source the real man page, but without them the man command 1579+# would be unable to find the correct page. The default is NO. 1580+ 1581+MAN_LINKS = NO 1582+ 1583+#--------------------------------------------------------------------------- 1584+# configuration options related to the XML output 1585+#--------------------------------------------------------------------------- 1586+ 1587+# If the GENERATE_XML tag is set to YES Doxygen will 1588+# generate an XML file that captures the structure of 1589+# the code including all documentation. 1590+ 1591+GENERATE_XML = NO 1592+ 1593+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 1594+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 1595+# put in front of it. If left blank `xml' will be used as the default path. 1596+ 1597+XML_OUTPUT = xml 1598+ 1599+# The XML_SCHEMA tag can be used to specify an XML schema, 1600+# which can be used by a validating XML parser to check the 1601+# syntax of the XML files. 1602+ 1603+XML_SCHEMA = 1604+ 1605+# The XML_DTD tag can be used to specify an XML DTD, 1606+# which can be used by a validating XML parser to check the 1607+# syntax of the XML files. 1608+ 1609+XML_DTD = 1610+ 1611+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 1612+# dump the program listings (including syntax highlighting 1613+# and cross-referencing information) to the XML output. Note that 1614+# enabling this will significantly increase the size of the XML output. 1615+ 1616+XML_PROGRAMLISTING = YES 1617+ 1618+#--------------------------------------------------------------------------- 1619+# configuration options for the AutoGen Definitions output 1620+#--------------------------------------------------------------------------- 1621+ 1622+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 1623+# generate an AutoGen Definitions (see autogen.sf.net) file 1624+# that captures the structure of the code including all 1625+# documentation. Note that this feature is still experimental 1626+# and incomplete at the moment. 1627+ 1628+GENERATE_AUTOGEN_DEF = NO 1629+ 1630+#--------------------------------------------------------------------------- 1631+# configuration options related to the Perl module output 1632+#--------------------------------------------------------------------------- 1633+ 1634+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 1635+# generate a Perl module file that captures the structure of 1636+# the code including all documentation. Note that this 1637+# feature is still experimental and incomplete at the 1638+# moment. 1639+ 1640+GENERATE_PERLMOD = NO 1641+ 1642+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 1643+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 1644+# to generate PDF and DVI output from the Perl module output. 1645+ 1646+PERLMOD_LATEX = NO 1647+ 1648+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 1649+# nicely formatted so it can be parsed by a human reader. This is useful 1650+# if you want to understand what is going on. On the other hand, if this 1651+# tag is set to NO the size of the Perl module output will be much smaller 1652+# and Perl will parse it just the same. 1653+ 1654+PERLMOD_PRETTY = YES 1655+ 1656+# The names of the make variables in the generated doxyrules.make file 1657+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 1658+# This is useful so different doxyrules.make files included by the same 1659+# Makefile don't overwrite each other's variables. 1660+ 1661+PERLMOD_MAKEVAR_PREFIX = 1662+ 1663+#--------------------------------------------------------------------------- 1664+# Configuration options related to the preprocessor 1665+#--------------------------------------------------------------------------- 1666+ 1667+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 1668+# evaluate all C-preprocessor directives found in the sources and include 1669+# files. 1670+ 1671+ENABLE_PREPROCESSING = YES 1672+ 1673+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 1674+# names in the source code. If set to NO (the default) only conditional 1675+# compilation will be performed. Macro expansion can be done in a controlled 1676+# way by setting EXPAND_ONLY_PREDEF to YES. 1677+ 1678+MACRO_EXPANSION = NO 1679+ 1680+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 1681+# then the macro expansion is limited to the macros specified with the 1682+# PREDEFINED and EXPAND_AS_DEFINED tags. 1683+ 1684+EXPAND_ONLY_PREDEF = NO 1685+ 1686+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 1687+# in the INCLUDE_PATH (see below) will be search if a #include is found. 1688+ 1689+SEARCH_INCLUDES = YES 1690+ 1691+# The INCLUDE_PATH tag can be used to specify one or more directories that 1692+# contain include files that are not input files but should be processed by 1693+# the preprocessor. 1694+ 1695+INCLUDE_PATH = 1696+ 1697+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 1698+# patterns (like *.h and *.hpp) to filter out the header-files in the 1699+# directories. If left blank, the patterns specified with FILE_PATTERNS will 1700+# be used. 1701+ 1702+INCLUDE_FILE_PATTERNS = 1703+ 1704+# The PREDEFINED tag can be used to specify one or more macro names that 1705+# are defined before the preprocessor is started (similar to the -D option of 1706+# gcc). The argument of the tag is a list of macros of the form: name 1707+# or name=definition (no spaces). If the definition and the = are 1708+# omitted =1 is assumed. To prevent a macro definition from being 1709+# undefined via #undef or recursively expanded use the := operator 1710+# instead of the = operator. 1711+ 1712+PREDEFINED = 1713+ 1714+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 1715+# this tag can be used to specify a list of macro names that should be expanded. 1716+# The macro definition that is found in the sources will be used. 1717+# Use the PREDEFINED tag if you want to use a different macro definition. 1718+ 1719+EXPAND_AS_DEFINED = 1720+ 1721+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 1722+# doxygen's preprocessor will remove all function-like macros that are alone 1723+# on a line, have an all uppercase name, and do not end with a semicolon. Such 1724+# function macros are typically used for boiler-plate code, and will confuse 1725+# the parser if not removed. 1726+ 1727+SKIP_FUNCTION_MACROS = YES 1728+ 1729+#--------------------------------------------------------------------------- 1730+# Configuration::additions related to external references 1731+#--------------------------------------------------------------------------- 1732+ 1733+# The TAGFILES option can be used to specify one or more tagfiles. 1734+# Optionally an initial location of the external documentation 1735+# can be added for each tagfile. The format of a tag file without 1736+# this location is as follows: 1737+# TAGFILES = file1 file2 ... 1738+# Adding location for the tag files is done as follows: 1739+# TAGFILES = file1=loc1 "file2 = loc2" ... 1740+# where "loc1" and "loc2" can be relative or absolute paths or 1741+# URLs. If a location is present for each tag, the installdox tool 1742+# does not have to be run to correct the links. 1743+# Note that each tag file must have a unique name 1744+# (where the name does NOT include the path) 1745+# If a tag file is not located in the directory in which doxygen 1746+# is run, you must also specify the path to the tagfile here. 1747+ 1748+TAGFILES = 1749+ 1750+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 1751+# a tag file that is based on the input files it reads. 1752+ 1753+GENERATE_TAGFILE = 1754+ 1755+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 1756+# in the class index. If set to NO only the inherited external classes 1757+# will be listed. 1758+ 1759+ALLEXTERNALS = NO 1760+ 1761+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 1762+# in the modules index. If set to NO, only the current project's groups will 1763+# be listed. 1764+ 1765+EXTERNAL_GROUPS = YES 1766+ 1767+# The PERL_PATH should be the absolute path and name of the perl script 1768+# interpreter (i.e. the result of `which perl'). 1769+ 1770+PERL_PATH = /usr/bin/perl 1771+ 1772+#--------------------------------------------------------------------------- 1773+# Configuration options related to the dot tool 1774+#--------------------------------------------------------------------------- 1775+ 1776+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 1777+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 1778+# or super classes. Setting the tag to NO turns the diagrams off. Note that 1779+# this option is superseded by the HAVE_DOT option below. This is only a 1780+# fallback. It is recommended to install and use dot, since it yields more 1781+# powerful graphs. 1782+ 1783+CLASS_DIAGRAMS = YES 1784+ 1785+# You can define message sequence charts within doxygen comments using the \msc 1786+# command. Doxygen will then run the mscgen tool (see 1787+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 1788+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 1789+# the mscgen tool resides. If left empty the tool is assumed to be found in the 1790+# default search path. 1791+ 1792+MSCGEN_PATH = 1793+ 1794+# If set to YES, the inheritance and collaboration graphs will hide 1795+# inheritance and usage relations if the target is undocumented 1796+# or is not a class. 1797+ 1798+HIDE_UNDOC_RELATIONS = YES 1799+ 1800+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 1801+# available from the path. This tool is part of Graphviz, a graph visualization 1802+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 1803+# have no effect if this option is set to NO (the default) 1804+ 1805+HAVE_DOT = NO 1806+ 1807+# By default doxygen will write a font called FreeSans.ttf to the output 1808+# directory and reference it in all dot files that doxygen generates. This 1809+# font does not include all possible unicode characters however, so when you need 1810+# these (or just want a differently looking font) you can specify the font name 1811+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 1812+# which can be done by putting it in a standard location or by setting the 1813+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 1814+# containing the font. 1815+ 1816+DOT_FONTNAME = FreeSans 1817+ 1818+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 1819+# The default size is 10pt. 1820+ 1821+DOT_FONTSIZE = 10 1822+ 1823+# By default doxygen will tell dot to use the output directory to look for the 1824+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 1825+# different font using DOT_FONTNAME you can set the path where dot 1826+# can find it using this tag. 1827+ 1828+DOT_FONTPATH = 1829+ 1830+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 1831+# will generate a graph for each documented class showing the direct and 1832+# indirect inheritance relations. Setting this tag to YES will force the 1833+# the CLASS_DIAGRAMS tag to NO. 1834+ 1835+CLASS_GRAPH = YES 1836+ 1837+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 1838+# will generate a graph for each documented class showing the direct and 1839+# indirect implementation dependencies (inheritance, containment, and 1840+# class references variables) of the class with other documented classes. 1841+ 1842+COLLABORATION_GRAPH = YES 1843+ 1844+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 1845+# will generate a graph for groups, showing the direct groups dependencies 1846+ 1847+GROUP_GRAPHS = YES 1848+ 1849+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 1850+# collaboration diagrams in a style similar to the OMG's Unified Modeling 1851+# Language. 1852+ 1853+UML_LOOK = NO 1854+ 1855+# If set to YES, the inheritance and collaboration graphs will show the 1856+# relations between templates and their instances. 1857+ 1858+TEMPLATE_RELATIONS = NO 1859+ 1860+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 1861+# tags are set to YES then doxygen will generate a graph for each documented 1862+# file showing the direct and indirect include dependencies of the file with 1863+# other documented files. 1864+ 1865+INCLUDE_GRAPH = YES 1866+ 1867+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 1868+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 1869+# documented header file showing the documented files that directly or 1870+# indirectly include this file. 1871+ 1872+INCLUDED_BY_GRAPH = YES 1873+ 1874+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 1875+# doxygen will generate a call dependency graph for every global function 1876+# or class method. Note that enabling this option will significantly increase 1877+# the time of a run. So in most cases it will be better to enable call graphs 1878+# for selected functions only using the \callgraph command. 1879+ 1880+CALL_GRAPH = NO 1881+ 1882+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 1883+# doxygen will generate a caller dependency graph for every global function 1884+# or class method. Note that enabling this option will significantly increase 1885+# the time of a run. So in most cases it will be better to enable caller 1886+# graphs for selected functions only using the \callergraph command. 1887+ 1888+CALLER_GRAPH = NO 1889+ 1890+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 1891+# will graphical hierarchy of all classes instead of a textual one. 1892+ 1893+GRAPHICAL_HIERARCHY = YES 1894+ 1895+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 1896+# then doxygen will show the dependencies a directory has on other directories 1897+# in a graphical way. The dependency relations are determined by the #include 1898+# relations between the files in the directories. 1899+ 1900+DIRECTORY_GRAPH = YES 1901+ 1902+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 1903+# generated by dot. Possible values are png, jpg, or gif 1904+# If left blank png will be used. 1905+ 1906+DOT_IMAGE_FORMAT = png 1907+ 1908+# The tag DOT_PATH can be used to specify the path where the dot tool can be 1909+# found. If left blank, it is assumed the dot tool can be found in the path. 1910+ 1911+DOT_PATH = 1912+ 1913+# The DOTFILE_DIRS tag can be used to specify one or more directories that 1914+# contain dot files that are included in the documentation (see the 1915+# \dotfile command). 1916+ 1917+DOTFILE_DIRS = 1918+ 1919+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 1920+# nodes that will be shown in the graph. If the number of nodes in a graph 1921+# becomes larger than this value, doxygen will truncate the graph, which is 1922+# visualized by representing a node as a red box. Note that doxygen if the 1923+# number of direct children of the root node in a graph is already larger than 1924+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 1925+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. 1926+ 1927+DOT_GRAPH_MAX_NODES = 50 1928+ 1929+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 1930+# graphs generated by dot. A depth value of 3 means that only nodes reachable 1931+# from the root by following a path via at most 3 edges will be shown. Nodes 1932+# that lay further from the root node will be omitted. Note that setting this 1933+# option to 1 or 2 may greatly reduce the computation time needed for large 1934+# code bases. Also note that the size of a graph can be further restricted by 1935+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. 1936+ 1937+MAX_DOT_GRAPH_DEPTH = 0 1938+ 1939+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 1940+# background. This is disabled by default, because dot on Windows does not 1941+# seem to support this out of the box. Warning: Depending on the platform used, 1942+# enabling this option may lead to badly anti-aliased labels on the edges of 1943+# a graph (i.e. they become hard to read). 1944+ 1945+DOT_TRANSPARENT = NO 1946+ 1947+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 1948+# files in one run (i.e. multiple -o and -T options on the command line). This 1949+# makes dot run faster, but since only newer versions of dot (>1.8.10) 1950+# support this, this feature is disabled by default. 1951+ 1952+DOT_MULTI_TARGETS = NO 1953+ 1954+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 1955+# generate a legend page explaining the meaning of the various boxes and 1956+# arrows in the dot generated graphs. 1957+ 1958+GENERATE_LEGEND = YES 1959+ 1960+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 1961+# remove the intermediate dot files that are used to generate 1962+# the various graphs. 1963+ 1964+DOT_CLEANUP = YES 1965diff --git a/benchmark/feature_mos/src/mosaic/AlignFeatures.cpp b/benchmark/feature_mos/src/mosaic/AlignFeatures.cpp 1966new file mode 100644 1967index 00000000..703a5ea5 1968--- /dev/null 1969+++ b/benchmark/feature_mos/src/mosaic/AlignFeatures.cpp 1970@@ -0,0 +1,233 @@ 1971+/* 1972+ * Copyright (C) 2011 The Android Open Source Project 1973+ * 1974+ * Licensed under the Apache License, Version 2.0 (the "License"); 1975+ * you may not use this file except in compliance with the License. 1976+ * You may obtain a copy of the License at 1977+ * 1978+ * http://www.apache.org/licenses/LICENSE-2.0 1979+ * 1980+ * Unless required by applicable law or agreed to in writing, software 1981+ * distributed under the License is distributed on an "AS IS" BASIS, 1982+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1983+ * See the License for the specific language governing permissions and 1984+ * limitations under the License. 1985+ */ 1986+ 1987+/////////////////////////////////////////////////// 1988+// AlignFeatures.cpp 1989+// S.O. # : 1990+// Author(s): zkira, mbansal, bsouthall, narodits 1991+// $Id: AlignFeatures.cpp,v 1.20 2011/06/17 13:35:47 mbansal Exp $ 1992+ 1993+#include <stdio.h> 1994+#include <string.h> 1995+ 1996+#include "trsMatrix.h" 1997+#include "MatrixUtils.h" 1998+#include "AlignFeatures.h" 1999+#include "Log.h" 2000+ 2001+#define LOG_TAG "AlignFeatures" 2002+ 2003+const double Align::DEFAULT_MAX_DISPARITY = 0.1; 2004+ 2005+Align::Align() 2006+{ 2007+ width = height = 0; 2008+ frame_number = 0; 2009+ num_frames_captured = 0; 2010+ reference_frame_index = 0; 2011+ db_Identity3x3(Hcurr); 2012+ db_Identity3x3(Hprev); 2013+} 2014+ 2015+Align::~Align() 2016+{ 2017+ // Free gray-scale image 2018+ if (imageGray != ImageUtils::IMAGE_TYPE_NOIMAGE) 2019+ ImageUtils::freeImage(imageGray); 2020+} 2021+ 2022+char* Align::getRegProfileString() 2023+{ 2024+ return reg.profile_string; 2025+} 2026+ 2027+int Align::initialize(int width, int height, bool _quarter_res, float _thresh_still) 2028+{ 2029+ int nr_corners = DEFAULT_NR_CORNERS; 2030+ double max_disparity = DEFAULT_MAX_DISPARITY; 2031+ int motion_model_type = DEFAULT_MOTION_MODEL; 2032+ int nrsamples = DB_DEFAULT_NR_SAMPLES; 2033+ double scale = DB_POINT_STANDARDDEV; 2034+ int chunk_size = DB_DEFAULT_CHUNK_SIZE; 2035+ int nrhorz = width/48; // Empirically determined number of horizontal 2036+ int nrvert = height/60; // and vertical buckets for harris corner detection. 2037+ bool linear_polish = false; 2038+ unsigned int reference_update_period = DEFAULT_REFERENCE_UPDATE_PERIOD; 2039+ 2040+ const bool DEFAULT_USE_SMALLER_MATCHING_WINDOW = false; 2041+ bool use_smaller_matching_window = DEFAULT_USE_SMALLER_MATCHING_WINDOW; 2042+ 2043+ quarter_res = _quarter_res; 2044+ thresh_still = _thresh_still; 2045+ 2046+ frame_number = 0; 2047+ num_frames_captured = 0; 2048+ reference_frame_index = 0; 2049+ db_Identity3x3(Hcurr); 2050+ db_Identity3x3(Hprev); 2051+ 2052+ if (!reg.Initialized()) 2053+ { 2054+ reg.Init(width, height, motion_model_type, 20, linear_polish, quarter_res, 2055+ scale, reference_update_period, false, 0, nrsamples, chunk_size, 2056+ nr_corners, max_disparity, use_smaller_matching_window, 2057+ nrhorz, nrvert); 2058+ } 2059+ this->width = width; 2060+ this->height = height; 2061+ 2062+ imageGray = ImageUtils::allocateImage(width, height, 1); 2063+ 2064+ if (reg.Initialized()) 2065+ return ALIGN_RET_OK; 2066+ else 2067+ return ALIGN_RET_ERROR; 2068+} 2069+ 2070+int Align::addFrameRGB(ImageType imageRGB) 2071+{ 2072+ ImageUtils::rgb2gray(imageGray, imageRGB, width, height); 2073+ return addFrame(imageGray); 2074+} 2075+ 2076+int Align::addFrame(ImageType imageGray_) 2077+{ 2078+ int ret_code = ALIGN_RET_OK; 2079+ 2080+ // Obtain a vector of pointers to rows in image and pass in to dbreg 2081+ ImageType *m_rows = ImageUtils::imageTypeToRowPointers(imageGray_, width, height); 2082+ 2083+ if (frame_number == 0) 2084+ { 2085+ reg.AddFrame(m_rows, Hcurr, true); // Force this to be a reference frame 2086+ int num_corner_ref = reg.GetNrRefCorners(); 2087+ 2088+ if (num_corner_ref < MIN_NR_REF_CORNERS) 2089+ { 2090+ return ALIGN_RET_LOW_TEXTURE; 2091+ } 2092+ } 2093+ else 2094+ { 2095+ reg.AddFrame(m_rows, Hcurr, false); 2096+ } 2097+ 2098+ // Average translation per frame = 2099+ // [Translation from Frame0 to Frame(n-1)] / [(n-1)] 2100+ average_tx_per_frame = (num_frames_captured < 2) ? 0.0 : 2101+ Hprev[2] / (num_frames_captured - 1); 2102+ 2103+ // Increment the captured frame counter if we already have a reference frame 2104+ num_frames_captured++; 2105+ 2106+ if (frame_number != 0) 2107+ { 2108+ int num_inliers = reg.GetNrInliers(); 2109+ 2110+ if(num_inliers < MIN_NR_INLIERS) 2111+ { 2112+ ret_code = ALIGN_RET_FEW_INLIERS; 2113+ 2114+ Hcurr[0] = 1.0; 2115+ Hcurr[1] = 0.0; 2116+ // Set this as the average per frame translation taking into acccount 2117+ // the separation of the current frame from the reference frame... 2118+ Hcurr[2] = -average_tx_per_frame * 2119+ (num_frames_captured - reference_frame_index); 2120+ Hcurr[3] = 0.0; 2121+ Hcurr[4] = 1.0; 2122+ Hcurr[5] = 0.0; 2123+ Hcurr[6] = 0.0; 2124+ Hcurr[7] = 0.0; 2125+ Hcurr[8] = 1.0; 2126+ } 2127+ 2128+ if(fabs(Hcurr[2])<thresh_still && fabs(Hcurr[5])<thresh_still) // Still camera 2129+ { 2130+ return ALIGN_RET_ERROR; 2131+ } 2132+ 2133+ // compute the homography: 2134+ double Hinv33[3][3]; 2135+ double Hprev33[3][3]; 2136+ double Hcurr33[3][3]; 2137+ 2138+ // Invert and multiple with previous transformation 2139+ Matrix33::convert9to33(Hcurr33, Hcurr); 2140+ Matrix33::convert9to33(Hprev33, Hprev); 2141+ normProjMat33d(Hcurr33); 2142+ 2143+ inv33d(Hcurr33, Hinv33); 2144+ 2145+ mult33d(Hcurr33, Hprev33, Hinv33); 2146+ normProjMat33d(Hcurr33); 2147+ Matrix9::convert33to9(Hprev, Hcurr33); 2148+ // Since we have already factored the current transformation 2149+ // into Hprev, we can reset the Hcurr to identity 2150+ db_Identity3x3(Hcurr); 2151+ 2152+ // Update the reference frame to be the current frame 2153+ reg.UpdateReference(m_rows,quarter_res,false); 2154+ 2155+ // Update the reference frame index 2156+ reference_frame_index = num_frames_captured; 2157+ } 2158+ 2159+ frame_number++; 2160+ 2161+ return ret_code; 2162+} 2163+ 2164+// Get current transformation 2165+int Align::getLastTRS(double trs[3][3]) 2166+{ 2167+ if (frame_number < 1) 2168+ { 2169+ trs[0][0] = 1.0; 2170+ trs[0][1] = 0.0; 2171+ trs[0][2] = 0.0; 2172+ trs[1][0] = 0.0; 2173+ trs[1][1] = 1.0; 2174+ trs[1][2] = 0.0; 2175+ trs[2][0] = 0.0; 2176+ trs[2][1] = 0.0; 2177+ trs[2][2] = 1.0; 2178+ return ALIGN_RET_ERROR; 2179+ } 2180+ 2181+ // Note that the logic here handles the case, where a frame is not used for 2182+ // mosaicing but is captured and used in the preview-rendering. 2183+ // For these frames, we don't set Hcurr to identity in AddFrame() and the 2184+ // logic here appends their transformation to Hprev to render them with the 2185+ // correct transformation. For the frames we do use for mosaicing, we already 2186+ // append their Hcurr to Hprev in AddFrame() and then set Hcurr to identity. 2187+ 2188+ double Hinv33[3][3]; 2189+ double Hprev33[3][3]; 2190+ double Hcurr33[3][3]; 2191+ 2192+ Matrix33::convert9to33(Hcurr33, Hcurr); 2193+ normProjMat33d(Hcurr33); 2194+ inv33d(Hcurr33, Hinv33); 2195+ 2196+ Matrix33::convert9to33(Hprev33, Hprev); 2197+ 2198+ mult33d(trs, Hprev33, Hinv33); 2199+ normProjMat33d(trs); 2200+ 2201+ return ALIGN_RET_OK; 2202+} 2203+ 2204diff --git a/benchmark/feature_mos/src/mosaic/AlignFeatures.h b/benchmark/feature_mos/src/mosaic/AlignFeatures.h 2205new file mode 100644 2206index 00000000..9999f575 2207--- /dev/null 2208+++ b/benchmark/feature_mos/src/mosaic/AlignFeatures.h 2209@@ -0,0 +1,93 @@ 2210+/* 2211+ * Copyright (C) 2011 The Android Open Source Project 2212+ * 2213+ * Licensed under the Apache License, Version 2.0 (the "License"); 2214+ * you may not use this file except in compliance with the License. 2215+ * You may obtain a copy of the License at 2216+ * 2217+ * http://www.apache.org/licenses/LICENSE-2.0 2218+ * 2219+ * Unless required by applicable law or agreed to in writing, software 2220+ * distributed under the License is distributed on an "AS IS" BASIS, 2221+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2222+ * See the License for the specific language governing permissions and 2223+ * limitations under the License. 2224+ */ 2225+ 2226+/////////////////////////////////////////////////// 2227+// Align.h 2228+// S.O. # : 2229+// Author(s): zkira 2230+// $Id: AlignFeatures.h,v 1.13 2011/06/17 13:35:47 mbansal Exp $ 2231+ 2232+#ifndef ALIGN_H 2233+#define ALIGN_H 2234+ 2235+#include "dbreg/dbreg.h" 2236+#include <db_utilities_camera.h> 2237+ 2238+#include "ImageUtils.h" 2239+#include "MatrixUtils.h" 2240+ 2241+class Align { 2242+ 2243+public: 2244+ // Types of alignment possible 2245+ static const int ALIGN_TYPE_PAN = 1; 2246+ 2247+ // Return codes 2248+ static const int ALIGN_RET_LOW_TEXTURE = -2; 2249+ static const int ALIGN_RET_ERROR = -1; 2250+ static const int ALIGN_RET_OK = 0; 2251+ static const int ALIGN_RET_FEW_INLIERS = 1; 2252+ 2253+ ///// Settings for feature-based alignment 2254+ // Number of features to use from corner detection 2255+ static const int DEFAULT_NR_CORNERS=750; 2256+ static const double DEFAULT_MAX_DISPARITY;//0.4; 2257+ // Type of homography to model 2258+ static const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_R_T; 2259+// static const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_PROJECTIVE; 2260+// static const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_AFFINE; 2261+ static const unsigned int DEFAULT_REFERENCE_UPDATE_PERIOD=1500; // Manual reference frame update so set this to a large number 2262+ 2263+ static const int MIN_NR_REF_CORNERS = 25; 2264+ static const int MIN_NR_INLIERS = 10; 2265+ 2266+ Align(); 2267+ ~Align(); 2268+ 2269+ // Initialization of structures, etc. 2270+ int initialize(int width, int height, bool quarter_res, float thresh_still); 2271+ 2272+ // Add a frame. Note: The alignment computation is performed 2273+ // in this function 2274+ int addFrameRGB(ImageType image); 2275+ int addFrame(ImageType image); 2276+ 2277+ // Obtain the TRS matrix from the last two frames 2278+ int getLastTRS(double trs[3][3]); 2279+ char* getRegProfileString(); 2280+ 2281+protected: 2282+ 2283+ db_FrameToReferenceRegistration reg; 2284+ 2285+ int frame_number; 2286+ 2287+ double Hcurr[9]; // Homography from the alignment reference to the frame-t 2288+ double Hprev[9]; // Homography from frame-0 to the frame-(t-1) 2289+ 2290+ int reference_frame_index; // Index of the reference frame from all captured frames 2291+ int num_frames_captured; // Total number of frames captured (different from frame_number) 2292+ double average_tx_per_frame; // Average pixel translation per captured frame 2293+ 2294+ int width,height; 2295+ 2296+ bool quarter_res; // Whether to process at quarter resolution 2297+ float thresh_still; // Translation threshold in pixels to detect still camera 2298+ ImageType imageGray; 2299+}; 2300+ 2301+ 2302+#endif 2303diff --git a/benchmark/feature_mos/src/mosaic/Blend.cpp b/benchmark/feature_mos/src/mosaic/Blend.cpp 2304new file mode 100644 2305index 00000000..625196c6 2306--- /dev/null 2307+++ b/benchmark/feature_mos/src/mosaic/Blend.cpp 2308@@ -0,0 +1,1385 @@ 2309+/* 2310+ * Copyright (C) 2011 The Android Open Source Project 2311+ * 2312+ * Licensed under the Apache License, Version 2.0 (the "License"); 2313+ * you may not use this file except in compliance with the License. 2314+ * You may obtain a copy of the License at 2315+ * 2316+ * http://www.apache.org/licenses/LICENSE-2.0 2317+ * 2318+ * Unless required by applicable law or agreed to in writing, software 2319+ * distributed under the License is distributed on an "AS IS" BASIS, 2320+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2321+ * See the License for the specific language governing permissions and 2322+ * limitations under the License. 2323+ */ 2324+ 2325+/////////////////////////////////////////////////// 2326+// Blend.cpp 2327+// $Id: Blend.cpp,v 1.22 2011/06/24 04:22:14 mbansal Exp $ 2328+ 2329+#include <string.h> 2330+ 2331+#include "Interp.h" 2332+#include "Blend.h" 2333+ 2334+#include "Geometry.h" 2335+#include "trsMatrix.h" 2336+ 2337+const float Blend::LIMIT_SIZE_MULTIPLIER = 50.f * 2.0f; 2338+const float Blend::LIMIT_HEIGHT_MULTIPLIER = 2.5f; 2339+ 2340+Blend::Blend() 2341+{ 2342+ m_wb.blendingType = BLEND_TYPE_NONE; 2343+} 2344+ 2345+Blend::~Blend() 2346+{ 2347+ if (m_pFrameVPyr) free(m_pFrameVPyr); 2348+ if (m_pFrameUPyr) free(m_pFrameUPyr); 2349+ if (m_pFrameYPyr) free(m_pFrameYPyr); 2350+} 2351+ 2352+int Blend::initialize(int blendingType, int stripType, int frame_width, int frame_height) 2353+{ 2354+ this->width = frame_width; 2355+ this->height = frame_height; 2356+ this->m_wb.blendingType = blendingType; 2357+ this->m_wb.stripType = stripType; 2358+ 2359+ m_wb.blendRange = m_wb.blendRangeUV = BLEND_RANGE_DEFAULT; 2360+ m_wb.nlevs = m_wb.blendRange; 2361+ m_wb.nlevsC = m_wb.blendRangeUV; 2362+ 2363+ if (m_wb.nlevs <= 0) m_wb.nlevs = 1; // Need levels for YUV processing 2364+ if (m_wb.nlevsC > m_wb.nlevs) m_wb.nlevsC = m_wb.nlevs; 2365+ 2366+ m_wb.roundoffOverlap = 1.5; 2367+ 2368+ m_pFrameYPyr = NULL; 2369+ m_pFrameUPyr = NULL; 2370+ m_pFrameVPyr = NULL; 2371+ 2372+ m_pFrameYPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevs, (unsigned short) width, (unsigned short) height, BORDER); 2373+ m_pFrameUPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC, (unsigned short) (width), (unsigned short) (height), BORDER); 2374+ m_pFrameVPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC, (unsigned short) (width), (unsigned short) (height), BORDER); 2375+ 2376+ if (!m_pFrameYPyr || !m_pFrameUPyr || !m_pFrameVPyr) 2377+ { 2378+ return BLEND_RET_ERROR_MEMORY; 2379+ } 2380+ 2381+ return BLEND_RET_OK; 2382+} 2383+ 2384+inline double max(double a, double b) { return a > b ? a : b; } 2385+inline double min(double a, double b) { return a < b ? a : b; } 2386+ 2387+void Blend::AlignToMiddleFrame(MosaicFrame **frames, int frames_size) 2388+{ 2389+ // Unwarp this frame and Warp the others to match 2390+ MosaicFrame *mb = NULL; 2391+ MosaicFrame *ref = frames[int(frames_size/2)]; // Middle frame 2392+ 2393+ double invtrs[3][3]; 2394+ inv33d(ref->trs, invtrs); 2395+ 2396+ for(int mfit = 0; mfit < frames_size; mfit++) 2397+ { 2398+ mb = frames[mfit]; 2399+ double temp[3][3]; 2400+ mult33d(temp, invtrs, mb->trs); 2401+ memcpy(mb->trs, temp, sizeof(temp)); 2402+ normProjMat33d(mb->trs); 2403+ } 2404+} 2405+ 2406+int Blend::runBlend(MosaicFrame **oframes, MosaicFrame **rframes, 2407+ int frames_size, 2408+ ImageType &imageMosaicYVU, int &mosaicWidth, int &mosaicHeight, 2409+ float &progress, bool &cancelComputation) 2410+{ 2411+ int ret; 2412+ int numCenters; 2413+ 2414+ MosaicFrame **frames; 2415+ 2416+ // For THIN strip mode, accept all frames for blending 2417+ if (m_wb.stripType == STRIP_TYPE_THIN) 2418+ { 2419+ frames = oframes; 2420+ } 2421+ else // For WIDE strip mode, first select the relevant frames to blend. 2422+ { 2423+ SelectRelevantFrames(oframes, frames_size, rframes, frames_size); 2424+ frames = rframes; 2425+ } 2426+ 2427+ ComputeBlendParameters(frames, frames_size, true); 2428+ numCenters = frames_size; 2429+ 2430+ if (numCenters == 0) 2431+ { 2432+ return BLEND_RET_ERROR; 2433+ } 2434+ 2435+ if (!(m_AllSites = m_Triangulator.allocMemory(numCenters))) 2436+ { 2437+ return BLEND_RET_ERROR_MEMORY; 2438+ } 2439+ 2440+ // Bounding rectangle (real numbers) of the final mosaic computed by projecting 2441+ // each input frame into the mosaic coordinate system. 2442+ BlendRect global_rect; 2443+ 2444+ global_rect.lft = global_rect.bot = 2e30; // min values 2445+ global_rect.rgt = global_rect.top = -2e30; // max values 2446+ MosaicFrame *mb = NULL; 2447+ 2448+ double x0, y0, x1, y1, x2, y2, x3, y3; 2449+ 2450+ // Corners of the left-most and right-most frames respectively in the 2451+ // mosaic coordinate system. 2452+ double xLeftCorners[2] = {2e30, 2e30}; 2453+ double xRightCorners[2] = {-2e30, -2e30}; 2454+ 2455+ // Corners of the top-most and bottom-most frames respectively in the 2456+ // mosaic coordinate system. 2457+ double yTopCorners[2] = {2e30, 2e30}; 2458+ double yBottomCorners[2] = {-2e30, -2e30}; 2459+ 2460+ 2461+ // Determine the extents of the final mosaic 2462+ CSite *csite = m_AllSites ; 2463+ for(int mfit = 0; mfit < frames_size; mfit++) 2464+ { 2465+ mb = frames[mfit]; 2466+ 2467+ // Compute clipping for this frame's rect 2468+ FrameToMosaicRect(mb->width, mb->height, mb->trs, mb->brect); 2469+ // Clip global rect using this frame's rect 2470+ ClipRect(mb->brect, global_rect); 2471+ 2472+ // Calculate the corner points 2473+ FrameToMosaic(mb->trs, 0.0, 0.0, x0, y0); 2474+ FrameToMosaic(mb->trs, 0.0, mb->height-1.0, x1, y1); 2475+ FrameToMosaic(mb->trs, mb->width-1.0, mb->height-1.0, x2, y2); 2476+ FrameToMosaic(mb->trs, mb->width-1.0, 0.0, x3, y3); 2477+ 2478+ if(x0 < xLeftCorners[0] || x1 < xLeftCorners[1]) // If either of the left corners is lower 2479+ { 2480+ xLeftCorners[0] = x0; 2481+ xLeftCorners[1] = x1; 2482+ } 2483+ 2484+ if(x3 > xRightCorners[0] || x2 > xRightCorners[1]) // If either of the right corners is higher 2485+ { 2486+ xRightCorners[0] = x3; 2487+ xRightCorners[1] = x2; 2488+ } 2489+ 2490+ if(y0 < yTopCorners[0] || y3 < yTopCorners[1]) // If either of the top corners is lower 2491+ { 2492+ yTopCorners[0] = y0; 2493+ yTopCorners[1] = y3; 2494+ } 2495+ 2496+ if(y1 > yBottomCorners[0] || y2 > yBottomCorners[1]) // If either of the bottom corners is higher 2497+ { 2498+ yBottomCorners[0] = y1; 2499+ yBottomCorners[1] = y2; 2500+ } 2501+ 2502+ 2503+ // Compute the centroid of the warped region 2504+ FindQuadCentroid(x0, y0, x1, y1, x2, y2, x3, y3, csite->getVCenter().x, csite->getVCenter().y); 2505+ 2506+ csite->setMb(mb); 2507+ csite++; 2508+ } 2509+ 2510+ // Get origin and sizes 2511+ 2512+ // Bounding rectangle (int numbers) of the final mosaic computed by projecting 2513+ // each input frame into the mosaic coordinate system. 2514+ MosaicRect fullRect; 2515+ 2516+ fullRect.left = (int) floor(global_rect.lft); // min-x 2517+ fullRect.top = (int) floor(global_rect.bot); // min-y 2518+ fullRect.right = (int) ceil(global_rect.rgt); // max-x 2519+ fullRect.bottom = (int) ceil(global_rect.top);// max-y 2520+ Mwidth = (unsigned short) (fullRect.right - fullRect.left + 1); 2521+ Mheight = (unsigned short) (fullRect.bottom - fullRect.top + 1); 2522+ 2523+ int xLeftMost, xRightMost; 2524+ int yTopMost, yBottomMost; 2525+ 2526+ // Rounding up, so that we don't include the gray border. 2527+ xLeftMost = max(0, max(xLeftCorners[0], xLeftCorners[1]) - fullRect.left + 1); 2528+ xRightMost = min(Mwidth - 1, min(xRightCorners[0], xRightCorners[1]) - fullRect.left - 1); 2529+ 2530+ yTopMost = max(0, max(yTopCorners[0], yTopCorners[1]) - fullRect.top + 1); 2531+ yBottomMost = min(Mheight - 1, min(yBottomCorners[0], yBottomCorners[1]) - fullRect.top - 1); 2532+ 2533+ if (xRightMost <= xLeftMost || yBottomMost <= yTopMost) 2534+ { 2535+ return BLEND_RET_ERROR; 2536+ } 2537+ 2538+ // Make sure image width is multiple of 4 2539+ Mwidth = (unsigned short) ((Mwidth + 3) & ~3); 2540+ Mheight = (unsigned short) ((Mheight + 3) & ~3); // Round up. 2541+ 2542+ ret = MosaicSizeCheck(LIMIT_SIZE_MULTIPLIER, LIMIT_HEIGHT_MULTIPLIER); 2543+ if (ret != BLEND_RET_OK) 2544+ { 2545+ return ret; 2546+ } 2547+ 2548+ YUVinfo *imgMos = YUVinfo::allocateImage(Mwidth, Mheight); 2549+ if (imgMos == NULL) 2550+ { 2551+ return BLEND_RET_ERROR_MEMORY; 2552+ } 2553+ 2554+ // Set the Y image to 255 so we can distinguish when frame idx are written to it 2555+ memset(imgMos->Y.ptr[0], 255, (imgMos->Y.width * imgMos->Y.height)); 2556+ // Set the v and u images to black 2557+ memset(imgMos->V.ptr[0], 128, (imgMos->V.width * imgMos->V.height) << 1); 2558+ 2559+ // Do the triangulation. It returns a sorted list of edges 2560+ SEdgeVector *edge; 2561+ int n = m_Triangulator.triangulate(&edge, numCenters, width, height); 2562+ m_Triangulator.linkNeighbors(edge, n, numCenters); 2563+ 2564+ // Bounding rectangle that determines the positioning of the rectangle that is 2565+ // cropped out of the computed mosaic to get rid of the gray borders. 2566+ MosaicRect cropping_rect; 2567+ 2568+ if (m_wb.horizontal) 2569+ { 2570+ cropping_rect.left = xLeftMost; 2571+ cropping_rect.right = xRightMost; 2572+ } 2573+ else 2574+ { 2575+ cropping_rect.top = yTopMost; 2576+ cropping_rect.bottom = yBottomMost; 2577+ } 2578+ 2579+ // Do merging and blending : 2580+ ret = DoMergeAndBlend(frames, numCenters, width, height, *imgMos, fullRect, 2581+ cropping_rect, progress, cancelComputation); 2582+ 2583+ if (m_wb.blendingType == BLEND_TYPE_HORZ) 2584+ CropFinalMosaic(*imgMos, cropping_rect); 2585+ 2586+ 2587+ m_Triangulator.freeMemory(); // note: can be called even if delaunay_alloc() wasn't successful 2588+ 2589+ imageMosaicYVU = imgMos->Y.ptr[0]; 2590+ 2591+ 2592+ if (m_wb.blendingType == BLEND_TYPE_HORZ) 2593+ { 2594+ mosaicWidth = cropping_rect.right - cropping_rect.left + 1; 2595+ mosaicHeight = cropping_rect.bottom - cropping_rect.top + 1; 2596+ } 2597+ else 2598+ { 2599+ mosaicWidth = Mwidth; 2600+ mosaicHeight = Mheight; 2601+ } 2602+ 2603+ return ret; 2604+} 2605+ 2606+int Blend::MosaicSizeCheck(float sizeMultiplier, float heightMultiplier) { 2607+ if (Mwidth < width || Mheight < height) { 2608+ return BLEND_RET_ERROR; 2609+ } 2610+ 2611+ if ((Mwidth * Mheight) > (width * height * sizeMultiplier)) { 2612+ return BLEND_RET_ERROR; 2613+ } 2614+ 2615+ // We won't do blending for the cases where users swing the device too much 2616+ // in the secondary direction. We use a short side to determine the 2617+ // secondary direction because users may hold the device in landsape 2618+ // or portrait. 2619+ int shortSide = min(Mwidth, Mheight); 2620+ if (shortSide > height * heightMultiplier) { 2621+ return BLEND_RET_ERROR; 2622+ } 2623+ 2624+ return BLEND_RET_OK; 2625+} 2626+ 2627+int Blend::FillFramePyramid(MosaicFrame *mb) 2628+{ 2629+ ImageType mbY, mbU, mbV; 2630+ // Lay this image, centered into the temporary buffer 2631+ mbY = mb->image; 2632+ mbU = mb->getU(); 2633+ mbV = mb->getV(); 2634+ 2635+ int h, w; 2636+ 2637+ for(h=0; h<height; h++) 2638+ { 2639+ ImageTypeShort yptr = m_pFrameYPyr->ptr[h]; 2640+ ImageTypeShort uptr = m_pFrameUPyr->ptr[h]; 2641+ ImageTypeShort vptr = m_pFrameVPyr->ptr[h]; 2642+ 2643+ for(w=0; w<width; w++) 2644+ { 2645+ yptr[w] = (short) ((*(mbY++)) << 3); 2646+ uptr[w] = (short) ((*(mbU++)) << 3); 2647+ vptr[w] = (short) ((*(mbV++)) << 3); 2648+ } 2649+ } 2650+ 2651+ // Spread the image through the border 2652+ PyramidShort::BorderSpread(m_pFrameYPyr, BORDER, BORDER, BORDER, BORDER); 2653+ PyramidShort::BorderSpread(m_pFrameUPyr, BORDER, BORDER, BORDER, BORDER); 2654+ PyramidShort::BorderSpread(m_pFrameVPyr, BORDER, BORDER, BORDER, BORDER); 2655+ 2656+ // Generate Laplacian pyramids 2657+ if (!PyramidShort::BorderReduce(m_pFrameYPyr, m_wb.nlevs) || !PyramidShort::BorderExpand(m_pFrameYPyr, m_wb.nlevs, -1) || 2658+ !PyramidShort::BorderReduce(m_pFrameUPyr, m_wb.nlevsC) || !PyramidShort::BorderExpand(m_pFrameUPyr, m_wb.nlevsC, -1) || 2659+ !PyramidShort::BorderReduce(m_pFrameVPyr, m_wb.nlevsC) || !PyramidShort::BorderExpand(m_pFrameVPyr, m_wb.nlevsC, -1)) 2660+ { 2661+ return BLEND_RET_ERROR; 2662+ } 2663+ else 2664+ { 2665+ return BLEND_RET_OK; 2666+ } 2667+} 2668+ 2669+int Blend::DoMergeAndBlend(MosaicFrame **frames, int nsite, 2670+ int width, int height, YUVinfo &imgMos, MosaicRect &rect, 2671+ MosaicRect &cropping_rect, float &progress, bool &cancelComputation) 2672+{ 2673+ m_pMosaicYPyr = NULL; 2674+ m_pMosaicUPyr = NULL; 2675+ m_pMosaicVPyr = NULL; 2676+ 2677+ m_pMosaicYPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevs,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER); 2678+ m_pMosaicUPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER); 2679+ m_pMosaicVPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER); 2680+ if (!m_pMosaicYPyr || !m_pMosaicUPyr || !m_pMosaicVPyr) 2681+ { 2682+ return BLEND_RET_ERROR_MEMORY; 2683+ } 2684+ 2685+ MosaicFrame *mb; 2686+ 2687+ CSite *esite = m_AllSites + nsite; 2688+ int site_idx; 2689+ 2690+ // First go through each frame and for each mosaic pixel determine which frame it should come from 2691+ site_idx = 0; 2692+ for(CSite *csite = m_AllSites; csite < esite; csite++) 2693+ { 2694+ if(cancelComputation) 2695+ { 2696+ if (m_pMosaicVPyr) free(m_pMosaicVPyr); 2697+ if (m_pMosaicUPyr) free(m_pMosaicUPyr); 2698+ if (m_pMosaicYPyr) free(m_pMosaicYPyr); 2699+ return BLEND_RET_CANCELLED; 2700+ } 2701+ 2702+ mb = csite->getMb(); 2703+ 2704+ mb->vcrect = mb->brect; 2705+ ClipBlendRect(csite, mb->vcrect); 2706+ 2707+ ComputeMask(csite, mb->vcrect, mb->brect, rect, imgMos, site_idx); 2708+ 2709+ site_idx++; 2710+ } 2711+ 2712+ ////////// imgMos.Y, imgMos.V, imgMos.U are used as follows ////////////// 2713+ ////////////////////// THIN STRIP MODE /////////////////////////////////// 2714+ 2715+ // imgMos.Y is used to store the index of the image from which each pixel 2716+ // in the output mosaic can be read out for the thin-strip mode. Thus, 2717+ // there is no special handling for pixels around the seam. Also, imgMos.Y 2718+ // is set to 255 wherever we can't get its value from any input image e.g. 2719+ // in the gray border areas. imgMos.V and imgMos.U are set to 128 for the 2720+ // thin-strip mode. 2721+ 2722+ ////////////////////// WIDE STRIP MODE /////////////////////////////////// 2723+ 2724+ // imgMos.Y is used the same way as the thin-strip mode. 2725+ // imgMos.V is used to store the index of the neighboring image which 2726+ // should contribute to the color of an output pixel in a band around 2727+ // the seam. Thus, in this band, we will crossfade between the color values 2728+ // from the image index imgMos.Y and image index imgMos.V. imgMos.U is 2729+ // used to store the weight (multiplied by 100) that each image will 2730+ // contribute to the blending process. Thus, we start at 99% contribution 2731+ // from the first image, then go to 50% contribution from each image at 2732+ // the seam. Then, the contribution from the second image goes up to 99%. 2733+ 2734+ // For WIDE mode, set the pixel masks to guide the blender to cross-fade 2735+ // between the images on either side of each seam: 2736+ if (m_wb.stripType == STRIP_TYPE_WIDE) 2737+ { 2738+ if(m_wb.horizontal) 2739+ { 2740+ // Set the number of pixels around the seam to cross-fade between 2741+ // the two component images, 2742+ int tw = STRIP_CROSS_FADE_WIDTH_PXLS; 2743+ 2744+ // Proceed with the image index calculation for cross-fading 2745+ // only if the cross-fading width is larger than 0 2746+ if (tw > 0) 2747+ { 2748+ for(int y = 0; y < imgMos.Y.height; y++) 2749+ { 2750+ // Since we compare two adjecant pixels to determine 2751+ // whether there is a seam, the termination condition of x 2752+ // is set to imgMos.Y.width - tw, so that x+1 below 2753+ // won't exceed the imgMos' boundary. 2754+ for(int x = tw; x < imgMos.Y.width - tw; ) 2755+ { 2756+ // Determine where the seam is... 2757+ if (imgMos.Y.ptr[y][x] != imgMos.Y.ptr[y][x+1] && 2758+ imgMos.Y.ptr[y][x] != 255 && 2759+ imgMos.Y.ptr[y][x+1] != 255) 2760+ { 2761+ // Find the image indices on both sides of the seam 2762+ unsigned char idx1 = imgMos.Y.ptr[y][x]; 2763+ unsigned char idx2 = imgMos.Y.ptr[y][x+1]; 2764+ 2765+ for (int o = tw; o >= 0; o--) 2766+ { 2767+ // Set the image index to use for cross-fading 2768+ imgMos.V.ptr[y][x - o] = idx2; 2769+ // Set the intensity weights to use for cross-fading 2770+ imgMos.U.ptr[y][x - o] = 50 + (99 - 50) * o / tw; 2771+ } 2772+ 2773+ for (int o = 1; o <= tw; o++) 2774+ { 2775+ // Set the image index to use for cross-fading 2776+ imgMos.V.ptr[y][x + o] = idx1; 2777+ // Set the intensity weights to use for cross-fading 2778+ imgMos.U.ptr[y][x + o] = imgMos.U.ptr[y][x - o]; 2779+ } 2780+ 2781+ x += (tw + 1); 2782+ } 2783+ else 2784+ { 2785+ x++; 2786+ } 2787+ } 2788+ } 2789+ } 2790+ } 2791+ else 2792+ { 2793+ // Set the number of pixels around the seam to cross-fade between 2794+ // the two component images, 2795+ int tw = STRIP_CROSS_FADE_WIDTH_PXLS; 2796+ 2797+ // Proceed with the image index calculation for cross-fading 2798+ // only if the cross-fading width is larger than 0 2799+ if (tw > 0) 2800+ { 2801+ for(int x = 0; x < imgMos.Y.width; x++) 2802+ { 2803+ // Since we compare two adjecant pixels to determine 2804+ // whether there is a seam, the termination condition of y 2805+ // is set to imgMos.Y.height - tw, so that y+1 below 2806+ // won't exceed the imgMos' boundary. 2807+ for(int y = tw; y < imgMos.Y.height - tw; ) 2808+ { 2809+ // Determine where the seam is... 2810+ if (imgMos.Y.ptr[y][x] != imgMos.Y.ptr[y+1][x] && 2811+ imgMos.Y.ptr[y][x] != 255 && 2812+ imgMos.Y.ptr[y+1][x] != 255) 2813+ { 2814+ // Find the image indices on both sides of the seam 2815+ unsigned char idx1 = imgMos.Y.ptr[y][x]; 2816+ unsigned char idx2 = imgMos.Y.ptr[y+1][x]; 2817+ 2818+ for (int o = tw; o >= 0; o--) 2819+ { 2820+ // Set the image index to use for cross-fading 2821+ imgMos.V.ptr[y - o][x] = idx2; 2822+ // Set the intensity weights to use for cross-fading 2823+ imgMos.U.ptr[y - o][x] = 50 + (99 - 50) * o / tw; 2824+ } 2825+ 2826+ for (int o = 1; o <= tw; o++) 2827+ { 2828+ // Set the image index to use for cross-fading 2829+ imgMos.V.ptr[y + o][x] = idx1; 2830+ // Set the intensity weights to use for cross-fading 2831+ imgMos.U.ptr[y + o][x] = imgMos.U.ptr[y - o][x]; 2832+ } 2833+ 2834+ y += (tw + 1); 2835+ } 2836+ else 2837+ { 2838+ y++; 2839+ } 2840+ } 2841+ } 2842+ } 2843+ } 2844+ 2845+ } 2846+ 2847+ // Now perform the actual blending using the frame assignment determined above 2848+ site_idx = 0; 2849+ for(CSite *csite = m_AllSites; csite < esite; csite++) 2850+ { 2851+ if(cancelComputation) 2852+ { 2853+ if (m_pMosaicVPyr) free(m_pMosaicVPyr); 2854+ if (m_pMosaicUPyr) free(m_pMosaicUPyr); 2855+ if (m_pMosaicYPyr) free(m_pMosaicYPyr); 2856+ return BLEND_RET_CANCELLED; 2857+ } 2858+ 2859+ mb = csite->getMb(); 2860+ 2861+ 2862+ if(FillFramePyramid(mb)!=BLEND_RET_OK) 2863+ return BLEND_RET_ERROR; 2864+ 2865+ ProcessPyramidForThisFrame(csite, mb->vcrect, mb->brect, rect, imgMos, mb->trs, site_idx); 2866+ 2867+ progress += TIME_PERCENT_BLEND/nsite; 2868+ 2869+ site_idx++; 2870+ } 2871+ 2872+ 2873+ // Blend 2874+ PerformFinalBlending(imgMos, cropping_rect); 2875+ 2876+ if (cropping_rect.Width() <= 0 || cropping_rect.Height() <= 0) 2877+ { 2878+ return BLEND_RET_ERROR; 2879+ } 2880+ 2881+ if (m_pMosaicVPyr) free(m_pMosaicVPyr); 2882+ if (m_pMosaicUPyr) free(m_pMosaicUPyr); 2883+ if (m_pMosaicYPyr) free(m_pMosaicYPyr); 2884+ 2885+ progress += TIME_PERCENT_FINAL; 2886+ 2887+ return BLEND_RET_OK; 2888+} 2889+ 2890+void Blend::CropFinalMosaic(YUVinfo &imgMos, MosaicRect &cropping_rect) 2891+{ 2892+ int i, j, k; 2893+ ImageType yimg; 2894+ ImageType uimg; 2895+ ImageType vimg; 2896+ 2897+ 2898+ yimg = imgMos.Y.ptr[0]; 2899+ uimg = imgMos.U.ptr[0]; 2900+ vimg = imgMos.V.ptr[0]; 2901+ 2902+ k = 0; 2903+ for (j = cropping_rect.top; j <= cropping_rect.bottom; j++) 2904+ { 2905+ for (i = cropping_rect.left; i <= cropping_rect.right; i++) 2906+ { 2907+ yimg[k] = yimg[j*imgMos.Y.width+i]; 2908+ k++; 2909+ } 2910+ } 2911+ for (j = cropping_rect.top; j <= cropping_rect.bottom; j++) 2912+ { 2913+ for (i = cropping_rect.left; i <= cropping_rect.right; i++) 2914+ { 2915+ yimg[k] = vimg[j*imgMos.Y.width+i]; 2916+ k++; 2917+ } 2918+ } 2919+ for (j = cropping_rect.top; j <= cropping_rect.bottom; j++) 2920+ { 2921+ for (i = cropping_rect.left; i <= cropping_rect.right; i++) 2922+ { 2923+ yimg[k] = uimg[j*imgMos.Y.width+i]; 2924+ k++; 2925+ } 2926+ } 2927+} 2928+ 2929+int Blend::PerformFinalBlending(YUVinfo &imgMos, MosaicRect &cropping_rect) 2930+{ 2931+ if (!PyramidShort::BorderExpand(m_pMosaicYPyr, m_wb.nlevs, 1) || !PyramidShort::BorderExpand(m_pMosaicUPyr, m_wb.nlevsC, 1) || 2932+ !PyramidShort::BorderExpand(m_pMosaicVPyr, m_wb.nlevsC, 1)) 2933+ { 2934+ return BLEND_RET_ERROR; 2935+ } 2936+ 2937+ ImageTypeShort myimg; 2938+ ImageTypeShort muimg; 2939+ ImageTypeShort mvimg; 2940+ ImageType yimg; 2941+ ImageType uimg; 2942+ ImageType vimg; 2943+ 2944+ // 2D boolean array that contains true wherever the mosaic image data is 2945+ // invalid (i.e. in the gray border). 2946+ bool **b = new bool*[imgMos.Y.height]; 2947+ 2948+ for(int j=0; j<imgMos.Y.height; j++) 2949+ { 2950+ b[j] = new bool[imgMos.Y.width]; 2951+ } 2952+ 2953+ // Copy the resulting image into the full image using the mask 2954+ int i, j; 2955+ 2956+ yimg = imgMos.Y.ptr[0]; 2957+ uimg = imgMos.U.ptr[0]; 2958+ vimg = imgMos.V.ptr[0]; 2959+ 2960+ for (j = 0; j < imgMos.Y.height; j++) 2961+ { 2962+ myimg = m_pMosaicYPyr->ptr[j]; 2963+ muimg = m_pMosaicUPyr->ptr[j]; 2964+ mvimg = m_pMosaicVPyr->ptr[j]; 2965+ 2966+ for (i = 0; i<imgMos.Y.width; i++) 2967+ { 2968+ // A final mask was set up previously, 2969+ // if the value is zero skip it, otherwise replace it. 2970+ if (*yimg <255) 2971+ { 2972+ short value = (short) ((*myimg) >> 3); 2973+ if (value < 0) value = 0; 2974+ else if (value > 255) value = 255; 2975+ *yimg = (unsigned char) value; 2976+ 2977+ value = (short) ((*muimg) >> 3); 2978+ if (value < 0) value = 0; 2979+ else if (value > 255) value = 255; 2980+ *uimg = (unsigned char) value; 2981+ 2982+ value = (short) ((*mvimg) >> 3); 2983+ if (value < 0) value = 0; 2984+ else if (value > 255) value = 255; 2985+ *vimg = (unsigned char) value; 2986+ 2987+ b[j][i] = false; 2988+ 2989+ } 2990+ else 2991+ { // set border color in here 2992+ *yimg = (unsigned char) 96; 2993+ *uimg = (unsigned char) 128; 2994+ *vimg = (unsigned char) 128; 2995+ 2996+ b[j][i] = true; 2997+ } 2998+ 2999+ yimg++; 3000+ uimg++; 3001+ vimg++; 3002+ myimg++; 3003+ muimg++; 3004+ mvimg++; 3005+ } 3006+ } 3007+ 3008+ if(m_wb.horizontal) 3009+ { 3010+ //Scan through each row and increment top if the row contains any gray 3011+ for (j = 0; j < imgMos.Y.height; j++) 3012+ { 3013+ for (i = cropping_rect.left; i < cropping_rect.right; i++) 3014+ { 3015+ if (b[j][i]) 3016+ { 3017+ break; // to next row 3018+ } 3019+ } 3020+ 3021+ if (i == cropping_rect.right) //no gray pixel in this row! 3022+ { 3023+ cropping_rect.top = j; 3024+ break; 3025+ } 3026+ } 3027+ 3028+ //Scan through each row and decrement bottom if the row contains any gray 3029+ for (j = imgMos.Y.height-1; j >= 0; j--) 3030+ { 3031+ for (i = cropping_rect.left; i < cropping_rect.right; i++) 3032+ { 3033+ if (b[j][i]) 3034+ { 3035+ break; // to next row 3036+ } 3037+ } 3038+ 3039+ if (i == cropping_rect.right) //no gray pixel in this row! 3040+ { 3041+ cropping_rect.bottom = j; 3042+ break; 3043+ } 3044+ } 3045+ } 3046+ else // Vertical Mosaic 3047+ { 3048+ //Scan through each column and increment left if the column contains any gray 3049+ for (i = 0; i < imgMos.Y.width; i++) 3050+ { 3051+ for (j = cropping_rect.top; j < cropping_rect.bottom; j++) 3052+ { 3053+ if (b[j][i]) 3054+ { 3055+ break; // to next column 3056+ } 3057+ } 3058+ 3059+ if (j == cropping_rect.bottom) //no gray pixel in this column! 3060+ { 3061+ cropping_rect.left = i; 3062+ break; 3063+ } 3064+ } 3065+ 3066+ //Scan through each column and decrement right if the column contains any gray 3067+ for (i = imgMos.Y.width-1; i >= 0; i--) 3068+ { 3069+ for (j = cropping_rect.top; j < cropping_rect.bottom; j++) 3070+ { 3071+ if (b[j][i]) 3072+ { 3073+ break; // to next column 3074+ } 3075+ } 3076+ 3077+ if (j == cropping_rect.bottom) //no gray pixel in this column! 3078+ { 3079+ cropping_rect.right = i; 3080+ break; 3081+ } 3082+ } 3083+ 3084+ } 3085+ 3086+ RoundingCroppingSizeToMultipleOf8(cropping_rect); 3087+ 3088+ for(int j=0; j<imgMos.Y.height; j++) 3089+ { 3090+ delete b[j]; 3091+ } 3092+ 3093+ delete[] b; 3094+ 3095+ return BLEND_RET_OK; 3096+} 3097+ 3098+void Blend::RoundingCroppingSizeToMultipleOf8(MosaicRect &rect) { 3099+ int height = rect.bottom - rect.top + 1; 3100+ int residue = height & 7; 3101+ rect.bottom -= residue; 3102+ 3103+ int width = rect.right - rect.left + 1; 3104+ residue = width & 7; 3105+ rect.right -= residue; 3106+} 3107+ 3108+void Blend::ComputeMask(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, int site_idx) 3109+{ 3110+ PyramidShort *dptr = m_pMosaicYPyr; 3111+ 3112+ int l = (int) ((vcrect.lft - rect.left)); 3113+ int b = (int) ((vcrect.bot - rect.top)); 3114+ int r = (int) ((vcrect.rgt - rect.left)); 3115+ int t = (int) ((vcrect.top - rect.top)); 3116+ 3117+ if (vcrect.lft == brect.lft) 3118+ l = (l <= 0) ? -BORDER : l - BORDER; 3119+ else if (l < -BORDER) 3120+ l = -BORDER; 3121+ 3122+ if (vcrect.bot == brect.bot) 3123+ b = (b <= 0) ? -BORDER : b - BORDER; 3124+ else if (b < -BORDER) 3125+ b = -BORDER; 3126+ 3127+ if (vcrect.rgt == brect.rgt) 3128+ r = (r >= dptr->width) ? dptr->width + BORDER - 1 : r + BORDER; 3129+ else if (r >= dptr->width + BORDER) 3130+ r = dptr->width + BORDER - 1; 3131+ 3132+ if (vcrect.top == brect.top) 3133+ t = (t >= dptr->height) ? dptr->height + BORDER - 1 : t + BORDER; 3134+ else if (t >= dptr->height + BORDER) 3135+ t = dptr->height + BORDER - 1; 3136+ 3137+ // Walk the Region of interest and populate the pyramid 3138+ for (int j = b; j <= t; j++) 3139+ { 3140+ int jj = j; 3141+ double sj = jj + rect.top; 3142+ 3143+ for (int i = l; i <= r; i++) 3144+ { 3145+ int ii = i; 3146+ // project point and then triangulate to neighbors 3147+ double si = ii + rect.left; 3148+ 3149+ double dself = hypotSq(csite->getVCenter().x - si, csite->getVCenter().y - sj); 3150+ int inMask = ((unsigned) ii < imgMos.Y.width && 3151+ (unsigned) jj < imgMos.Y.height) ? 1 : 0; 3152+ 3153+ if(!inMask) 3154+ continue; 3155+ 3156+ // scan the neighbors to see if this is a valid position 3157+ SEdgeVector *ce; 3158+ int ecnt; 3159+ for (ce = csite->getNeighbor(), ecnt = csite->getNumNeighbors(); ecnt--; ce++) 3160+ { 3161+ double d1 = hypotSq(m_AllSites[ce->second].getVCenter().x - si, 3162+ m_AllSites[ce->second].getVCenter().y - sj); 3163+ if (d1 < dself) 3164+ { 3165+ break; 3166+ } 3167+ } 3168+ 3169+ if (ecnt >= 0) continue; 3170+ 3171+ imgMos.Y.ptr[jj][ii] = (unsigned char)site_idx; 3172+ } 3173+ } 3174+} 3175+ 3176+void Blend::ProcessPyramidForThisFrame(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, double trs[3][3], int site_idx) 3177+{ 3178+ // Put the Region of interest (for all levels) into m_pMosaicYPyr 3179+ double inv_trs[3][3]; 3180+ inv33d(trs, inv_trs); 3181+ 3182+ // Process each pyramid level 3183+ PyramidShort *sptr = m_pFrameYPyr; 3184+ PyramidShort *suptr = m_pFrameUPyr; 3185+ PyramidShort *svptr = m_pFrameVPyr; 3186+ 3187+ PyramidShort *dptr = m_pMosaicYPyr; 3188+ PyramidShort *duptr = m_pMosaicUPyr; 3189+ PyramidShort *dvptr = m_pMosaicVPyr; 3190+ 3191+ int dscale = 0; // distance scale for the current level 3192+ int nC = m_wb.nlevsC; 3193+ for (int n = m_wb.nlevs; n--; dscale++, dptr++, sptr++, dvptr++, duptr++, svptr++, suptr++, nC--) 3194+ { 3195+ int l = (int) ((vcrect.lft - rect.left) / (1 << dscale)); 3196+ int b = (int) ((vcrect.bot - rect.top) / (1 << dscale)); 3197+ int r = (int) ((vcrect.rgt - rect.left) / (1 << dscale) + .5); 3198+ int t = (int) ((vcrect.top - rect.top) / (1 << dscale) + .5); 3199+ 3200+ if (vcrect.lft == brect.lft) 3201+ l = (l <= 0) ? -BORDER : l - BORDER; 3202+ else if (l < -BORDER) 3203+ l = -BORDER; 3204+ 3205+ if (vcrect.bot == brect.bot) 3206+ b = (b <= 0) ? -BORDER : b - BORDER; 3207+ else if (b < -BORDER) 3208+ b = -BORDER; 3209+ 3210+ if (vcrect.rgt == brect.rgt) 3211+ r = (r >= dptr->width) ? dptr->width + BORDER - 1 : r + BORDER; 3212+ else if (r >= dptr->width + BORDER) 3213+ r = dptr->width + BORDER - 1; 3214+ 3215+ if (vcrect.top == brect.top) 3216+ t = (t >= dptr->height) ? dptr->height + BORDER - 1 : t + BORDER; 3217+ else if (t >= dptr->height + BORDER) 3218+ t = dptr->height + BORDER - 1; 3219+ 3220+ // Walk the Region of interest and populate the pyramid 3221+ for (int j = b; j <= t; j++) 3222+ { 3223+ int jj = (j << dscale); 3224+ double sj = jj + rect.top; 3225+ 3226+ for (int i = l; i <= r; i++) 3227+ { 3228+ int ii = (i << dscale); 3229+ // project point and then triangulate to neighbors 3230+ double si = ii + rect.left; 3231+ 3232+ int inMask = ((unsigned) ii < imgMos.Y.width && 3233+ (unsigned) jj < imgMos.Y.height) ? 1 : 0; 3234+ 3235+ if(inMask && imgMos.Y.ptr[jj][ii] != site_idx && 3236+ imgMos.V.ptr[jj][ii] != site_idx && 3237+ imgMos.Y.ptr[jj][ii] != 255) 3238+ continue; 3239+ 3240+ // Setup weights for cross-fading 3241+ // Weight of the intensity already in the output pixel 3242+ double wt0 = 0.0; 3243+ // Weight of the intensity from the input pixel (current frame) 3244+ double wt1 = 1.0; 3245+ 3246+ if (m_wb.stripType == STRIP_TYPE_WIDE) 3247+ { 3248+ if(inMask && imgMos.Y.ptr[jj][ii] != 255) 3249+ { 3250+ // If not on a seam OR pyramid level exceeds 3251+ // maximum level for cross-fading. 3252+ if((imgMos.V.ptr[jj][ii] == 128) || 3253+ (dscale > STRIP_CROSS_FADE_MAX_PYR_LEVEL)) 3254+ { 3255+ wt0 = 0.0; 3256+ wt1 = 1.0; 3257+ } 3258+ else 3259+ { 3260+ wt0 = 1.0; 3261+ wt1 = ((imgMos.Y.ptr[jj][ii] == site_idx) ? 3262+ (double)imgMos.U.ptr[jj][ii] / 100.0 : 3263+ 1.0 - (double)imgMos.U.ptr[jj][ii] / 100.0); 3264+ } 3265+ } 3266+ } 3267+ 3268+ // Project this mosaic point into the original frame coordinate space 3269+ double xx, yy; 3270+ 3271+ MosaicToFrame(inv_trs, si, sj, xx, yy); 3272+ 3273+ if (xx < 0.0 || yy < 0.0 || xx > width - 1.0 || yy > height - 1.0) 3274+ { 3275+ if(inMask) 3276+ { 3277+ imgMos.Y.ptr[jj][ii] = 255; 3278+ wt0 = 0.0f; 3279+ wt1 = 1.0f; 3280+ } 3281+ } 3282+ 3283+ xx /= (1 << dscale); 3284+ yy /= (1 << dscale); 3285+ 3286+ 3287+ int x1 = (xx >= 0.0) ? (int) xx : (int) floor(xx); 3288+ int y1 = (yy >= 0.0) ? (int) yy : (int) floor(yy); 3289+ 3290+ // Final destination in extended pyramid 3291+#ifndef LINEAR_INTERP 3292+ if(inSegment(x1, sptr->width, BORDER-1) && 3293+ inSegment(y1, sptr->height, BORDER-1)) 3294+ { 3295+ double xfrac = xx - x1; 3296+ double yfrac = yy - y1; 3297+ dptr->ptr[j][i] = (short) (wt0 * dptr->ptr[j][i] + .5 + 3298+ wt1 * ciCalc(sptr, x1, y1, xfrac, yfrac)); 3299+ if (dvptr >= m_pMosaicVPyr && nC > 0) 3300+ { 3301+ duptr->ptr[j][i] = (short) (wt0 * duptr->ptr[j][i] + .5 + 3302+ wt1 * ciCalc(suptr, x1, y1, xfrac, yfrac)); 3303+ dvptr->ptr[j][i] = (short) (wt0 * dvptr->ptr[j][i] + .5 + 3304+ wt1 * ciCalc(svptr, x1, y1, xfrac, yfrac)); 3305+ } 3306+ } 3307+#else 3308+ if(inSegment(x1, sptr->width, BORDER) && inSegment(y1, sptr->height, BORDER)) 3309+ { 3310+ int x2 = x1 + 1; 3311+ int y2 = y1 + 1; 3312+ double xfrac = xx - x1; 3313+ double yfrac = yy - y1; 3314+ double y1val = sptr->ptr[y1][x1] + 3315+ (sptr->ptr[y1][x2] - sptr->ptr[y1][x1]) * xfrac; 3316+ double y2val = sptr->ptr[y2][x1] + 3317+ (sptr->ptr[y2][x2] - sptr->ptr[y2][x1]) * xfrac; 3318+ dptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val)); 3319+ 3320+ if (dvptr >= m_pMosaicVPyr && nC > 0) 3321+ { 3322+ y1val = suptr->ptr[y1][x1] + 3323+ (suptr->ptr[y1][x2] - suptr->ptr[y1][x1]) * xfrac; 3324+ y2val = suptr->ptr[y2][x1] + 3325+ (suptr->ptr[y2][x2] - suptr->ptr[y2][x1]) * xfrac; 3326+ 3327+ duptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val)); 3328+ 3329+ y1val = svptr->ptr[y1][x1] + 3330+ (svptr->ptr[y1][x2] - svptr->ptr[y1][x1]) * xfrac; 3331+ y2val = svptr->ptr[y2][x1] + 3332+ (svptr->ptr[y2][x2] - svptr->ptr[y2][x1]) * xfrac; 3333+ 3334+ dvptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val)); 3335+ } 3336+ } 3337+#endif 3338+ else 3339+ { 3340+ clipToSegment(x1, sptr->width, BORDER); 3341+ clipToSegment(y1, sptr->height, BORDER); 3342+ 3343+ dptr->ptr[j][i] = (short) (wt0 * dptr->ptr[j][i] + 0.5 + 3344+ wt1 * sptr->ptr[y1][x1] ); 3345+ if (dvptr >= m_pMosaicVPyr && nC > 0) 3346+ { 3347+ dvptr->ptr[j][i] = (short) (wt0 * dvptr->ptr[j][i] + 3348+ 0.5 + wt1 * svptr->ptr[y1][x1] ); 3349+ duptr->ptr[j][i] = (short) (wt0 * duptr->ptr[j][i] + 3350+ 0.5 + wt1 * suptr->ptr[y1][x1] ); 3351+ } 3352+ } 3353+ } 3354+ } 3355+ } 3356+} 3357+ 3358+void Blend::MosaicToFrame(double trs[3][3], double x, double y, double &wx, double &wy) 3359+{ 3360+ double X, Y, z; 3361+ if (m_wb.theta == 0.0) 3362+ { 3363+ X = x; 3364+ Y = y; 3365+ } 3366+ else if (m_wb.horizontal) 3367+ { 3368+ double alpha = x * m_wb.direction / m_wb.width; 3369+ double length = (y - alpha * m_wb.correction) * m_wb.direction + m_wb.radius; 3370+ double deltaTheta = m_wb.theta * alpha; 3371+ double sinTheta = sin(deltaTheta); 3372+ double cosTheta = sqrt(1.0 - sinTheta * sinTheta) * m_wb.direction; 3373+ X = length * sinTheta + m_wb.x; 3374+ Y = length * cosTheta + m_wb.y; 3375+ } 3376+ else 3377+ { 3378+ double alpha = y * m_wb.direction / m_wb.width; 3379+ double length = (x - alpha * m_wb.correction) * m_wb.direction + m_wb.radius; 3380+ double deltaTheta = m_wb.theta * alpha; 3381+ double sinTheta = sin(deltaTheta); 3382+ double cosTheta = sqrt(1.0 - sinTheta * sinTheta) * m_wb.direction; 3383+ Y = length * sinTheta + m_wb.y; 3384+ X = length * cosTheta + m_wb.x; 3385+ } 3386+ z = ProjZ(trs, X, Y, 1.0); 3387+ wx = ProjX(trs, X, Y, z, 1.0); 3388+ wy = ProjY(trs, X, Y, z, 1.0); 3389+} 3390+ 3391+void Blend::FrameToMosaic(double trs[3][3], double x, double y, double &wx, double &wy) 3392+{ 3393+ // Project into the intermediate Mosaic coordinate system 3394+ double z = ProjZ(trs, x, y, 1.0); 3395+ double X = ProjX(trs, x, y, z, 1.0); 3396+ double Y = ProjY(trs, x, y, z, 1.0); 3397+ 3398+ if (m_wb.theta == 0.0) 3399+ { 3400+ // No rotation, then this is all we need to do. 3401+ wx = X; 3402+ wy = Y; 3403+ } 3404+ else if (m_wb.horizontal) 3405+ { 3406+ double deltaX = X - m_wb.x; 3407+ double deltaY = Y - m_wb.y; 3408+ double length = sqrt(deltaX * deltaX + deltaY * deltaY); 3409+ double deltaTheta = asin(deltaX / length); 3410+ double alpha = deltaTheta / m_wb.theta; 3411+ wx = alpha * m_wb.width * m_wb.direction; 3412+ wy = (length - m_wb.radius) * m_wb.direction + alpha * m_wb.correction; 3413+ } 3414+ else 3415+ { 3416+ double deltaX = X - m_wb.x; 3417+ double deltaY = Y - m_wb.y; 3418+ double length = sqrt(deltaX * deltaX + deltaY * deltaY); 3419+ double deltaTheta = asin(deltaY / length); 3420+ double alpha = deltaTheta / m_wb.theta; 3421+ wy = alpha * m_wb.width * m_wb.direction; 3422+ wx = (length - m_wb.radius) * m_wb.direction + alpha * m_wb.correction; 3423+ } 3424+} 3425+ 3426+ 3427+ 3428+// Clip the region of interest as small as possible by using the Voronoi edges of 3429+// the neighbors 3430+void Blend::ClipBlendRect(CSite *csite, BlendRect &brect) 3431+{ 3432+ SEdgeVector *ce; 3433+ int ecnt; 3434+ for (ce = csite->getNeighbor(), ecnt = csite->getNumNeighbors(); ecnt--; ce++) 3435+ { 3436+ // calculate the Voronoi bisector intersection 3437+ const double epsilon = 1e-5; 3438+ double dx = (m_AllSites[ce->second].getVCenter().x - m_AllSites[ce->first].getVCenter().x); 3439+ double dy = (m_AllSites[ce->second].getVCenter().y - m_AllSites[ce->first].getVCenter().y); 3440+ double xmid = m_AllSites[ce->first].getVCenter().x + dx/2.0; 3441+ double ymid = m_AllSites[ce->first].getVCenter().y + dy/2.0; 3442+ double inter; 3443+ 3444+ if (dx > epsilon) 3445+ { 3446+ // neighbor is on right 3447+ if ((inter = m_wb.roundoffOverlap + xmid - dy * (((dy >= 0.0) ? brect.bot : brect.top) - ymid) / dx) < brect.rgt) 3448+ brect.rgt = inter; 3449+ } 3450+ else if (dx < -epsilon) 3451+ { 3452+ // neighbor is on left 3453+ if ((inter = -m_wb.roundoffOverlap + xmid - dy * (((dy >= 0.0) ? brect.bot : brect.top) - ymid) / dx) > brect.lft) 3454+ brect.lft = inter; 3455+ } 3456+ if (dy > epsilon) 3457+ { 3458+ // neighbor is above 3459+ if ((inter = m_wb.roundoffOverlap + ymid - dx * (((dx >= 0.0) ? brect.lft : brect.rgt) - xmid) / dy) < brect.top) 3460+ brect.top = inter; 3461+ } 3462+ else if (dy < -epsilon) 3463+ { 3464+ // neighbor is below 3465+ if ((inter = -m_wb.roundoffOverlap + ymid - dx * (((dx >= 0.0) ? brect.lft : brect.rgt) - xmid) / dy) > brect.bot) 3466+ brect.bot = inter; 3467+ } 3468+ } 3469+} 3470+ 3471+void Blend::FrameToMosaicRect(int width, int height, double trs[3][3], BlendRect &brect) 3472+{ 3473+ // We need to walk the perimeter since the borders can be bent. 3474+ brect.lft = brect.bot = 2e30; 3475+ brect.rgt = brect.top = -2e30; 3476+ double xpos, ypos; 3477+ double lasty = height - 1.0; 3478+ double lastx = width - 1.0; 3479+ int i; 3480+ 3481+ for (i = width; i--;) 3482+ { 3483+ 3484+ FrameToMosaic(trs, (double) i, 0.0, xpos, ypos); 3485+ ClipRect(xpos, ypos, brect); 3486+ FrameToMosaic(trs, (double) i, lasty, xpos, ypos); 3487+ ClipRect(xpos, ypos, brect); 3488+ } 3489+ for (i = height; i--;) 3490+ { 3491+ FrameToMosaic(trs, 0.0, (double) i, xpos, ypos); 3492+ ClipRect(xpos, ypos, brect); 3493+ FrameToMosaic(trs, lastx, (double) i, xpos, ypos); 3494+ ClipRect(xpos, ypos, brect); 3495+ } 3496+} 3497+ 3498+void Blend::SelectRelevantFrames(MosaicFrame **frames, int frames_size, 3499+ MosaicFrame **relevant_frames, int &relevant_frames_size) 3500+{ 3501+ MosaicFrame *first = frames[0]; 3502+ MosaicFrame *last = frames[frames_size-1]; 3503+ MosaicFrame *mb; 3504+ 3505+ double midX = last->width / 2.0; 3506+ double midY = last->height / 2.0; 3507+ double z = ProjZ(first->trs, midX, midY, 1.0); 3508+ double firstX, firstY; 3509+ double prevX = firstX = ProjX(first->trs, midX, midY, z, 1.0); 3510+ double prevY = firstY = ProjY(first->trs, midX, midY, z, 1.0); 3511+ 3512+ relevant_frames[0] = first; // Add first frame by default 3513+ relevant_frames_size = 1; 3514+ 3515+ for (int i = 0; i < frames_size - 1; i++) 3516+ { 3517+ mb = frames[i]; 3518+ double currX, currY; 3519+ z = ProjZ(mb->trs, midX, midY, 1.0); 3520+ currX = ProjX(mb->trs, midX, midY, z, 1.0); 3521+ currY = ProjY(mb->trs, midX, midY, z, 1.0); 3522+ double deltaX = currX - prevX; 3523+ double deltaY = currY - prevY; 3524+ 3525+ if (fabs(deltaX) > STRIP_SEPARATION_THRESHOLD_PXLS || 3526+ fabs(deltaY) > STRIP_SEPARATION_THRESHOLD_PXLS) 3527+ { 3528+ relevant_frames[relevant_frames_size] = mb; 3529+ relevant_frames_size++; 3530+ 3531+ prevX = currX; 3532+ prevY = currY; 3533+ } 3534+ } 3535+ 3536+ // Add last frame by default 3537+ relevant_frames[relevant_frames_size] = last; 3538+ relevant_frames_size++; 3539+} 3540+ 3541+void Blend::ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is360) 3542+{ 3543+ // For FULL and PAN modes, we do not unwarp the mosaic into a rectangular coordinate system 3544+ // and so we set the theta to 0 and return. 3545+ if (m_wb.blendingType != BLEND_TYPE_CYLPAN && m_wb.blendingType != BLEND_TYPE_HORZ) 3546+ { 3547+ m_wb.theta = 0.0; 3548+ return; 3549+ } 3550+ 3551+ MosaicFrame *first = frames[0]; 3552+ MosaicFrame *last = frames[frames_size-1]; 3553+ MosaicFrame *mb; 3554+ 3555+ double lxpos = last->trs[0][2], lypos = last->trs[1][2]; 3556+ double fxpos = first->trs[0][2], fypos = first->trs[1][2]; 3557+ 3558+ // Calculate warp to produce proper stitching. 3559+ // get x, y displacement 3560+ double midX = last->width / 2.0; 3561+ double midY = last->height / 2.0; 3562+ double z = ProjZ(first->trs, midX, midY, 1.0); 3563+ double firstX, firstY; 3564+ double prevX = firstX = ProjX(first->trs, midX, midY, z, 1.0); 3565+ double prevY = firstY = ProjY(first->trs, midX, midY, z, 1.0); 3566+ 3567+ double arcLength, lastTheta; 3568+ m_wb.theta = lastTheta = arcLength = 0.0; 3569+ 3570+ // Step through all the frames to compute the total arc-length of the cone 3571+ // swept while capturing the mosaic (in the original conical coordinate system). 3572+ for (int i = 0; i < frames_size; i++) 3573+ { 3574+ mb = frames[i]; 3575+ double currX, currY; 3576+ z = ProjZ(mb->trs, midX, midY, 1.0); 3577+ currX = ProjX(mb->trs, midX, midY, z, 1.0); 3578+ currY = ProjY(mb->trs, midX, midY, z, 1.0); 3579+ double deltaX = currX - prevX; 3580+ double deltaY = currY - prevY; 3581+ 3582+ // The arcLength is computed by summing the lengths of the chords 3583+ // connecting the pairwise projected image centers of the input image frames. 3584+ arcLength += sqrt(deltaY * deltaY + deltaX * deltaX); 3585+ 3586+ if (!is360) 3587+ { 3588+ double thisTheta = asin(mb->trs[1][0]); 3589+ m_wb.theta += thisTheta - lastTheta; 3590+ lastTheta = thisTheta; 3591+ } 3592+ 3593+ prevX = currX; 3594+ prevY = currY; 3595+ } 3596+ 3597+ // Stretch this to end at the proper alignment i.e. the width of the 3598+ // rectangle is determined by the arcLength computed above and the cone 3599+ // sector angle is determined using the rotation of the last frame. 3600+ m_wb.width = arcLength; 3601+ if (is360) m_wb.theta = asin(last->trs[1][0]); 3602+ 3603+ // If there is no rotation, we're done. 3604+ if (m_wb.theta != 0.0) 3605+ { 3606+ double dx = prevX - firstX; 3607+ double dy = prevY - firstY; 3608+ 3609+ // If the mosaic was captured by sweeping horizontally 3610+ if (abs(lxpos - fxpos) > abs(lypos - fypos)) 3611+ { 3612+ m_wb.horizontal = 1; 3613+ // Calculate radius position to make ends exactly the same Y offset 3614+ double radiusTheta = dx / cos(3.14159 / 2.0 - m_wb.theta); 3615+ m_wb.radius = dy + radiusTheta * cos(m_wb.theta); 3616+ if (m_wb.radius < 0.0) m_wb.radius = -m_wb.radius; 3617+ } 3618+ else 3619+ { 3620+ m_wb.horizontal = 0; 3621+ // Calculate radius position to make ends exactly the same Y offset 3622+ double radiusTheta = dy / cos(3.14159 / 2.0 - m_wb.theta); 3623+ m_wb.radius = dx + radiusTheta * cos(m_wb.theta); 3624+ if (m_wb.radius < 0.0) m_wb.radius = -m_wb.radius; 3625+ } 3626+ 3627+ // Determine major direction 3628+ if (m_wb.horizontal) 3629+ { 3630+ // Horizontal strip 3631+ // m_wb.x,y record the origin of the rectangle coordinate system. 3632+ if (is360) m_wb.x = firstX; 3633+ else 3634+ { 3635+ if (lxpos - fxpos < 0) 3636+ { 3637+ m_wb.x = firstX + midX; 3638+ z = ProjZ(last->trs, 0.0, midY, 1.0); 3639+ prevX = ProjX(last->trs, 0.0, midY, z, 1.0); 3640+ prevY = ProjY(last->trs, 0.0, midY, z, 1.0); 3641+ } 3642+ else 3643+ { 3644+ m_wb.x = firstX - midX; 3645+ z = ProjZ(last->trs, last->width - 1.0, midY, 1.0); 3646+ prevX = ProjX(last->trs, last->width - 1.0, midY, z, 1.0); 3647+ prevY = ProjY(last->trs, last->width - 1.0, midY, z, 1.0); 3648+ } 3649+ } 3650+ dy = prevY - firstY; 3651+ if (dy < 0.0) m_wb.direction = 1.0; 3652+ else m_wb.direction = -1.0; 3653+ m_wb.y = firstY - m_wb.radius * m_wb.direction; 3654+ if (dy * m_wb.theta > 0.0) m_wb.width = -m_wb.width; 3655+ } 3656+ else 3657+ { 3658+ // Vertical strip 3659+ if (is360) m_wb.y = firstY; 3660+ else 3661+ { 3662+ if (lypos - fypos < 0) 3663+ { 3664+ m_wb.x = firstY + midY; 3665+ z = ProjZ(last->trs, midX, 0.0, 1.0); 3666+ prevX = ProjX(last->trs, midX, 0.0, z, 1.0); 3667+ prevY = ProjY(last->trs, midX, 0.0, z, 1.0); 3668+ } 3669+ else 3670+ { 3671+ m_wb.x = firstX - midX; 3672+ z = ProjZ(last->trs, midX, last->height - 1.0, 1.0); 3673+ prevX = ProjX(last->trs, midX, last->height - 1.0, z, 1.0); 3674+ prevY = ProjY(last->trs, midX, last->height - 1.0, z, 1.0); 3675+ } 3676+ } 3677+ dx = prevX - firstX; 3678+ if (dx < 0.0) m_wb.direction = 1.0; 3679+ else m_wb.direction = -1.0; 3680+ m_wb.x = firstX - m_wb.radius * m_wb.direction; 3681+ if (dx * m_wb.theta > 0.0) m_wb.width = -m_wb.width; 3682+ } 3683+ 3684+ // Calculate the correct correction factor 3685+ double deltaX = prevX - m_wb.x; 3686+ double deltaY = prevY - m_wb.y; 3687+ double length = sqrt(deltaX * deltaX + deltaY * deltaY); 3688+ double deltaTheta = (m_wb.horizontal) ? deltaX : deltaY; 3689+ deltaTheta = asin(deltaTheta / length); 3690+ m_wb.correction = ((m_wb.radius - length) * m_wb.direction) / 3691+ (deltaTheta / m_wb.theta); 3692+ } 3693+} 3694diff --git a/benchmark/feature_mos/src/mosaic/Blend.h b/benchmark/feature_mos/src/mosaic/Blend.h 3695new file mode 100644 3696index 00000000..175eacd4 3697--- /dev/null 3698+++ b/benchmark/feature_mos/src/mosaic/Blend.h 3699@@ -0,0 +1,128 @@ 3700+/* 3701+ * Copyright (C) 2011 The Android Open Source Project 3702+ * 3703+ * Licensed under the Apache License, Version 2.0 (the "License"); 3704+ * you may not use this file except in compliance with the License. 3705+ * You may obtain a copy of the License at 3706+ * 3707+ * http://www.apache.org/licenses/LICENSE-2.0 3708+ * 3709+ * Unless required by applicable law or agreed to in writing, software 3710+ * distributed under the License is distributed on an "AS IS" BASIS, 3711+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3712+ * See the License for the specific language governing permissions and 3713+ * limitations under the License. 3714+ */ 3715+ 3716+/////////////////////////////////////////////////// 3717+// Blend.h 3718+// $Id: Blend.h,v 1.23 2011/06/24 04:22:14 mbansal Exp $ 3719+ 3720+#ifndef BLEND_H 3721+#define BLEND_H 3722+ 3723+#include "MosaicTypes.h" 3724+#include "Pyramid.h" 3725+#include "Delaunay.h" 3726+ 3727+#define BLEND_RANGE_DEFAULT 6 3728+#define BORDER 8 3729+ 3730+// Percent of total mosaicing time spent on each of the following operations 3731+const float TIME_PERCENT_ALIGN = 20.0; 3732+const float TIME_PERCENT_BLEND = 75.0; 3733+const float TIME_PERCENT_FINAL = 5.0; 3734+ 3735+// This threshold determines the minimum separation between the image centers 3736+// of the input image frames for them to be accepted for blending in the 3737+// STRIP_TYPE_WIDE mode. 3738+const float STRIP_SEPARATION_THRESHOLD_PXLS = 10; 3739+ 3740+// This threshold determines the number of pixels on either side of the strip 3741+// to cross-fade using the images contributing to each seam. 3742+const float STRIP_CROSS_FADE_WIDTH_PXLS = 2; 3743+// This specifies the maximum pyramid level to which cross-fading is applied. 3744+// The original image resolution is Level-0, half of that size is Level-1 and 3745+// so on. BLEND_RANGE_DEFAULT specifies the number of pyramid levels used by 3746+// the blending algorithm. 3747+const int STRIP_CROSS_FADE_MAX_PYR_LEVEL = 2; 3748+ 3749+/** 3750+ * Class for pyramid blending a mosaic. 3751+ */ 3752+class Blend { 3753+ 3754+public: 3755+ 3756+ static const int BLEND_TYPE_NONE = -1; 3757+ static const int BLEND_TYPE_FULL = 0; 3758+ static const int BLEND_TYPE_PAN = 1; 3759+ static const int BLEND_TYPE_CYLPAN = 2; 3760+ static const int BLEND_TYPE_HORZ = 3; 3761+ 3762+ static const int STRIP_TYPE_THIN = 0; 3763+ static const int STRIP_TYPE_WIDE = 1; 3764+ 3765+ static const int BLEND_RET_ERROR = -1; 3766+ static const int BLEND_RET_OK = 0; 3767+ static const int BLEND_RET_ERROR_MEMORY = 1; 3768+ static const int BLEND_RET_CANCELLED = -2; 3769+ 3770+ Blend(); 3771+ ~Blend(); 3772+ 3773+ int initialize(int blendingType, int stripType, int frame_width, int frame_height); 3774+ 3775+ int runBlend(MosaicFrame **frames, MosaicFrame **rframes, int frames_size, ImageType &imageMosaicYVU, 3776+ int &mosaicWidth, int &mosaicHeight, float &progress, bool &cancelComputation); 3777+ 3778+protected: 3779+ 3780+ PyramidShort *m_pFrameYPyr; 3781+ PyramidShort *m_pFrameUPyr; 3782+ PyramidShort *m_pFrameVPyr; 3783+ 3784+ PyramidShort *m_pMosaicYPyr; 3785+ PyramidShort *m_pMosaicUPyr; 3786+ PyramidShort *m_pMosaicVPyr; 3787+ 3788+ CDelaunay m_Triangulator; 3789+ CSite *m_AllSites; 3790+ 3791+ BlendParams m_wb; 3792+ 3793+ // Height and width of individual frames 3794+ int width, height; 3795+ 3796+ // Height and width of mosaic 3797+ unsigned short Mwidth, Mheight; 3798+ 3799+ // Helper functions 3800+ void FrameToMosaic(double trs[3][3], double x, double y, double &wx, double &wy); 3801+ void MosaicToFrame(double trs[3][3], double x, double y, double &wx, double &wy); 3802+ void FrameToMosaicRect(int width, int height, double trs[3][3], BlendRect &brect); 3803+ void ClipBlendRect(CSite *csite, BlendRect &brect); 3804+ void AlignToMiddleFrame(MosaicFrame **frames, int frames_size); 3805+ 3806+ int DoMergeAndBlend(MosaicFrame **frames, int nsite, int width, int height, YUVinfo &imgMos, MosaicRect &rect, MosaicRect &cropping_rect, float &progress, bool &cancelComputation); 3807+ void ComputeMask(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, int site_idx); 3808+ void ProcessPyramidForThisFrame(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, double trs[3][3], int site_idx); 3809+ 3810+ int FillFramePyramid(MosaicFrame *mb); 3811+ 3812+ // TODO: need to add documentation about the parameters 3813+ void ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is360); 3814+ void SelectRelevantFrames(MosaicFrame **frames, int frames_size, 3815+ MosaicFrame **relevant_frames, int &relevant_frames_size); 3816+ 3817+ int PerformFinalBlending(YUVinfo &imgMos, MosaicRect &cropping_rect); 3818+ void CropFinalMosaic(YUVinfo &imgMos, MosaicRect &cropping_rect); 3819+ 3820+private: 3821+ static const float LIMIT_SIZE_MULTIPLIER; 3822+ static const float LIMIT_HEIGHT_MULTIPLIER; 3823+ int MosaicSizeCheck(float sizeMultiplier, float heightMultiplier); 3824+ void RoundingCroppingSizeToMultipleOf8(MosaicRect& rect); 3825+}; 3826+ 3827+#endif 3828diff --git a/benchmark/feature_mos/src/mosaic/CSite.h b/benchmark/feature_mos/src/mosaic/CSite.h 3829new file mode 100644 3830index 00000000..928c1734 3831--- /dev/null 3832+++ b/benchmark/feature_mos/src/mosaic/CSite.h 3833@@ -0,0 +1,63 @@ 3834+/* 3835+ * Copyright (C) 2011 The Android Open Source Project 3836+ * 3837+ * Licensed under the Apache License, Version 2.0 (the "License"); 3838+ * you may not use this file except in compliance with the License. 3839+ * You may obtain a copy of the License at 3840+ * 3841+ * http://www.apache.org/licenses/LICENSE-2.0 3842+ * 3843+ * Unless required by applicable law or agreed to in writing, software 3844+ * distributed under the License is distributed on an "AS IS" BASIS, 3845+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3846+ * See the License for the specific language governing permissions and 3847+ * limitations under the License. 3848+ */ 3849+ 3850+/////////////////////////////////////////////////// 3851+// CSite.h 3852+// $Id: CSite.h,v 1.3 2011/06/17 13:35:47 mbansal Exp $ 3853+ 3854+#ifndef TRIDEL_H 3855+#define TRIDEL_H 3856+ 3857+#include "MosaicTypes.h" 3858+ 3859+typedef struct 3860+{ 3861+ short first; 3862+ short second; 3863+} SEdgeVector; 3864+ 3865+typedef struct 3866+{ 3867+ double x; 3868+ double y; 3869+} SVec2d; 3870+ 3871+class CSite 3872+{ 3873+private: 3874+ MosaicFrame *mosaicFrame; 3875+ SEdgeVector *neighbor; 3876+ int numNeighbors; 3877+ SVec2d voronoiCenter; 3878+ 3879+public: 3880+ CSite(); 3881+ ~CSite(); 3882+ 3883+ inline MosaicFrame* getMb() { return mosaicFrame; } 3884+ inline SEdgeVector* getNeighbor() { return neighbor; } 3885+ inline int getNumNeighbors() { return numNeighbors; } 3886+ inline SVec2d& getVCenter() { return voronoiCenter; } 3887+ inline double X() { return voronoiCenter.x; } 3888+ inline double Y() { return voronoiCenter.y; } 3889+ 3890+ inline void incrNumNeighbors() { numNeighbors++; } 3891+ inline void setNumNeighbors(int num) { numNeighbors = num; } 3892+ inline void setNeighbor(SEdgeVector *nb) { neighbor = nb; } 3893+ inline void setMb(MosaicFrame *mb) { mosaicFrame = mb; } 3894+}; 3895+ 3896+#endif 3897diff --git a/benchmark/feature_mos/src/mosaic/Delaunay.cpp b/benchmark/feature_mos/src/mosaic/Delaunay.cpp 3898new file mode 100644 3899index 00000000..e8015dfd 3900--- /dev/null 3901+++ b/benchmark/feature_mos/src/mosaic/Delaunay.cpp 3902@@ -0,0 +1,631 @@ 3903+/* 3904+ * Copyright (C) 2011 The Android Open Source Project 3905+ * 3906+ * Licensed under the Apache License, Version 2.0 (the "License"); 3907+ * you may not use this file except in compliance with the License. 3908+ * You may obtain a copy of the License at 3909+ * 3910+ * http://www.apache.org/licenses/LICENSE-2.0 3911+ * 3912+ * Unless required by applicable law or agreed to in writing, software 3913+ * distributed under the License is distributed on an "AS IS" BASIS, 3914+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3915+ * See the License for the specific language governing permissions and 3916+ * limitations under the License. 3917+ */ 3918+ 3919+// Delaunay.cpp 3920+// $Id: Delaunay.cpp,v 1.10 2011/06/17 13:35:48 mbansal Exp $ 3921+ 3922+#include <stdio.h> 3923+#include <stdlib.h> 3924+#include <memory.h> 3925+#include "Delaunay.h" 3926+ 3927+#define QQ 9 // Optimal value as determined by testing 3928+#define DM 38 // 2^(1+DM/2) element sort capability. DM=38 for >10^6 elements 3929+#define NYL -1 3930+#define valid(l) ccw(orig(basel), dest(l), dest(basel)) 3931+ 3932+ 3933+CDelaunay::CDelaunay() 3934+{ 3935+} 3936+ 3937+CDelaunay::~CDelaunay() 3938+{ 3939+} 3940+ 3941+// Allocate storage, construct triangulation, compute voronoi corners 3942+int CDelaunay::triangulate(SEdgeVector **edges, int n_sites, int width, int height) 3943+{ 3944+ EdgePointer cep; 3945+ 3946+ deleteAllEdges(); 3947+ buildTriangulation(n_sites); 3948+ cep = consolidateEdges(); 3949+ *edges = ev; 3950+ 3951+ // Note: construction_list will change ev 3952+ return constructList(cep, width, height); 3953+} 3954+ 3955+// builds delaunay triangulation 3956+void CDelaunay::buildTriangulation(int size) 3957+{ 3958+ int i, rows; 3959+ EdgePointer lefte, righte; 3960+ 3961+ rows = (int)( 0.5 + sqrt( (double) size / log( (double) size ))); 3962+ 3963+ // Sort the pointers by x-coordinate of site 3964+ for ( i=0 ; i < size ; i++ ) { 3965+ sp[i] = (SitePointer) i; 3966+ } 3967+ 3968+ spsortx( sp, 0, size-1 ); 3969+ build( 0, size-1, &lefte, &righte, rows ); 3970+ oneBndryEdge = lefte; 3971+} 3972+ 3973+// Recursive Delaunay Triangulation Procedure 3974+// Contains modifications for axis-switching division. 3975+void CDelaunay::build(int lo, int hi, EdgePointer *le, EdgePointer *re, int rows) 3976+{ 3977+ EdgePointer a, b, c, ldo, rdi, ldi, rdo, maxx, minx; 3978+ int split, lowrows; 3979+ int low, high; 3980+ SitePointer s1, s2, s3; 3981+ low = lo; 3982+ high = hi; 3983+ 3984+ if ( low < (high-2) ) { 3985+ // more than three elements; do recursion 3986+ minx = sp[low]; 3987+ maxx = sp[high]; 3988+ if (rows == 1) { // time to switch axis of division 3989+ spsorty( sp, low, high); 3990+ rows = 65536; 3991+ } 3992+ lowrows = rows/2; 3993+ split = low - 1 + (int) 3994+ (0.5 + ((double)(high-low+1) * ((double)lowrows / (double)rows))); 3995+ build( low, split, &ldo, &ldi, lowrows ); 3996+ build( split+1, high, &rdi, &rdo, (rows-lowrows) ); 3997+ doMerge(&ldo, ldi, rdi, &rdo); 3998+ while (orig(ldo) != minx) { 3999+ ldo = rprev(ldo); 4000+ } 4001+ while (orig(rdo) != maxx) { 4002+ rdo = (SitePointer) lprev(rdo); 4003+ } 4004+ *le = ldo; 4005+ *re = rdo; 4006+ } 4007+ else if (low >= (high - 1)) { // two or one points 4008+ a = makeEdge(sp[low], sp[high]); 4009+ *le = a; 4010+ *re = (EdgePointer) sym(a); 4011+ } else { // three points 4012+ // 3 cases: triangles of 2 orientations, and 3 points on a line 4013+ a = makeEdge((s1 = sp[low]), (s2 = sp[low+1])); 4014+ b = makeEdge(s2, (s3 = sp[high])); 4015+ splice((EdgePointer) sym(a), b); 4016+ if (ccw(s1, s3, s2)) { 4017+ c = connectLeft(b, a); 4018+ *le = (EdgePointer) sym(c); 4019+ *re = c; 4020+ } else { 4021+ *le = a; 4022+ *re = (EdgePointer) sym(b); 4023+ if (ccw(s1, s2, s3)) { 4024+ // not colinear 4025+ c = connectLeft(b, a); 4026+ } 4027+ } 4028+ } 4029+} 4030+ 4031+// Quad-edge manipulation primitives 4032+EdgePointer CDelaunay::makeEdge(SitePointer origin, SitePointer destination) 4033+{ 4034+ EdgePointer temp, ans; 4035+ temp = allocEdge(); 4036+ ans = temp; 4037+ 4038+ onext(temp) = ans; 4039+ orig(temp) = origin; 4040+ onext(++temp) = (EdgePointer) (ans + 3); 4041+ onext(++temp) = (EdgePointer) (ans + 2); 4042+ orig(temp) = destination; 4043+ onext(++temp) = (EdgePointer) (ans + 1); 4044+ 4045+ return(ans); 4046+} 4047+ 4048+void CDelaunay::splice(EdgePointer a, EdgePointer b) 4049+{ 4050+ EdgePointer alpha, beta, temp; 4051+ alpha = (EdgePointer) rot(onext(a)); 4052+ beta = (EdgePointer) rot(onext(b)); 4053+ temp = onext(alpha); 4054+ onext(alpha) = onext(beta); 4055+ onext(beta) = temp; 4056+ temp = onext(a); 4057+ onext(a) = onext(b); 4058+ onext(b) = temp; 4059+} 4060+ 4061+EdgePointer CDelaunay::connectLeft(EdgePointer a, EdgePointer b) 4062+{ 4063+ EdgePointer ans; 4064+ ans = makeEdge(dest(a), orig(b)); 4065+ splice(ans, (EdgePointer) lnext(a)); 4066+ splice((EdgePointer) sym(ans), b); 4067+ return(ans); 4068+} 4069+ 4070+EdgePointer CDelaunay::connectRight(EdgePointer a, EdgePointer b) 4071+{ 4072+ EdgePointer ans; 4073+ ans = makeEdge(dest(a), orig(b)); 4074+ splice(ans, (EdgePointer) sym(a)); 4075+ splice((EdgePointer) sym(ans), (EdgePointer) oprev(b)); 4076+ return(ans); 4077+} 4078+ 4079+// disconnects e from the rest of the structure and destroys it 4080+void CDelaunay::deleteEdge(EdgePointer e) 4081+{ 4082+ splice(e, (EdgePointer) oprev(e)); 4083+ splice((EdgePointer) sym(e), (EdgePointer) oprev(sym(e))); 4084+ freeEdge(e); 4085+} 4086+ 4087+// 4088+// Overall storage allocation 4089+// 4090+ 4091+// Quad-edge storage allocation 4092+CSite *CDelaunay::allocMemory(int n) 4093+{ 4094+ unsigned int size; 4095+ 4096+ size = ((sizeof(CSite) + sizeof(SitePointer)) * n + 4097+ (sizeof(SitePointer) + sizeof(EdgePointer)) * 12 4098+ ) * n; 4099+ if (!(sa = (CSite*) malloc(size))) { 4100+ return NULL; 4101+ } 4102+ sp = (SitePointer *) (sa + n); 4103+ ev = (SEdgeVector *) (org = sp + n); 4104+ next = (EdgePointer *) (org + 12 * n); 4105+ ei = (struct EDGE_INFO *) (next + 12 * n); 4106+ return sa; 4107+} 4108+ 4109+void CDelaunay::freeMemory() 4110+{ 4111+ if (sa) { 4112+ free(sa); 4113+ sa = (CSite*)NULL; 4114+ } 4115+} 4116+ 4117+// 4118+// Edge storage management 4119+// 4120+ 4121+void CDelaunay::deleteAllEdges() 4122+{ 4123+ nextEdge = 0; 4124+ availEdge = NYL; 4125+} 4126+ 4127+EdgePointer CDelaunay::allocEdge() 4128+{ 4129+ EdgePointer ans; 4130+ 4131+ if (availEdge == NYL) { 4132+ ans = nextEdge, nextEdge += 4; 4133+ } else { 4134+ ans = availEdge, availEdge = onext(availEdge); 4135+ } 4136+ return(ans); 4137+} 4138+ 4139+void CDelaunay::freeEdge(EdgePointer e) 4140+{ 4141+ e ^= e & 3; 4142+ onext(e) = availEdge; 4143+ availEdge = e; 4144+} 4145+ 4146+EdgePointer CDelaunay::consolidateEdges() 4147+{ 4148+ EdgePointer e; 4149+ int i,j; 4150+ 4151+ while (availEdge != NYL) { 4152+ nextEdge -= 4; e = availEdge; availEdge = onext(availEdge); 4153+ 4154+ if (e==nextEdge) { 4155+ continue; // the one deleted was the last one anyway 4156+ } 4157+ if ((oneBndryEdge&~3) == nextEdge) { 4158+ oneBndryEdge = (EdgePointer) (e | (oneBndryEdge&3)); 4159+ } 4160+ for (i=0,j=3; i<4; i++,j=rot(j)) { 4161+ onext(e+i) = onext(nextEdge+i); 4162+ onext(rot(onext(e+i))) = (EdgePointer) (e+j); 4163+ } 4164+ } 4165+ return nextEdge; 4166+} 4167+ 4168+// 4169+// Sorting Routines 4170+// 4171+ 4172+int CDelaunay::xcmpsp(int i, int j) 4173+{ 4174+ double d = sa[(i>=0)?sp[i]:sp1].X() - sa[(j>=0)?sp[j]:sp1].X(); 4175+ if ( d > 0. ) { 4176+ return 1; 4177+ } 4178+ if ( d < 0. ) { 4179+ return -1; 4180+ } 4181+ d = sa[(i>=0)?sp[i]:sp1].Y() - sa[(j>=0)?sp[j]:sp1].Y(); 4182+ if ( d > 0. ) { 4183+ return 1; 4184+ } 4185+ if ( d < 0. ) { 4186+ return -1; 4187+ } 4188+ return 0; 4189+} 4190+ 4191+int CDelaunay::ycmpsp(int i, int j) 4192+{ 4193+ double d = sa[(i>=0)?sp[i]:sp1].Y() - sa[(j>=0)?sp[j]:sp1].Y(); 4194+ if ( d > 0. ) { 4195+ return 1; 4196+ } 4197+ if ( d < 0. ) { 4198+ return -1; 4199+ } 4200+ d = sa[(i>=0)?sp[i]:sp1].X() - sa[(j>=0)?sp[j]:sp1].X(); 4201+ if ( d > 0. ) { 4202+ return 1; 4203+ } 4204+ if ( d < 0. ) { 4205+ return -1; 4206+ } 4207+ return 0; 4208+} 4209+ 4210+int CDelaunay::cmpev(int i, int j) 4211+{ 4212+ return (ev[i].first - ev[j].first); 4213+} 4214+ 4215+void CDelaunay::swapsp(int i, int j) 4216+{ 4217+ int t; 4218+ t = (i>=0) ? sp[i] : sp1; 4219+ 4220+ if (i>=0) { 4221+ sp[i] = (j>=0)?sp[j]:sp1; 4222+ } else { 4223+ sp1 = (j>=0)?sp[j]:sp1; 4224+ } 4225+ 4226+ if (j>=0) { 4227+ sp[j] = (SitePointer) t; 4228+ } else { 4229+ sp1 = (SitePointer) t; 4230+ } 4231+} 4232+ 4233+void CDelaunay::swapev(int i, int j) 4234+{ 4235+ SEdgeVector temp; 4236+ 4237+ temp = ev[i]; 4238+ ev[i] = ev[j]; 4239+ ev[j] = temp; 4240+} 4241+ 4242+void CDelaunay::copysp(int i, int j) 4243+{ 4244+ if (j>=0) { 4245+ sp[j] = (i>=0)?sp[i]:sp1; 4246+ } else { 4247+ sp1 = (i>=0)?sp[i]:sp1; 4248+ } 4249+} 4250+ 4251+void CDelaunay::copyev(int i, int j) 4252+{ 4253+ ev[j] = ev[i]; 4254+} 4255+ 4256+void CDelaunay::spsortx(SitePointer *sp_in, int low, int high) 4257+{ 4258+ sp = sp_in; 4259+ rcssort(low,high,-1,&CDelaunay::xcmpsp,&CDelaunay::swapsp,&CDelaunay::copysp); 4260+} 4261+ 4262+void CDelaunay::spsorty(SitePointer *sp_in, int low, int high ) 4263+{ 4264+ sp = sp_in; 4265+ rcssort(low,high,-1,&CDelaunay::ycmpsp,&CDelaunay::swapsp,&CDelaunay::copysp); 4266+} 4267+ 4268+void CDelaunay::rcssort(int lowelt, int highelt, int temp, 4269+ int (CDelaunay::*comparison)(int,int), 4270+ void (CDelaunay::*swap)(int,int), 4271+ void (CDelaunay::*copy)(int,int)) 4272+{ 4273+ int m,sij,si,sj,sL,sk; 4274+ int stack[DM]; 4275+ 4276+ if (highelt-lowelt<=1) { 4277+ return; 4278+ } 4279+ if (highelt-lowelt>QQ) { 4280+ m = 0; 4281+ si = lowelt; sj = highelt; 4282+ for (;;) { // partition [si,sj] about median-of-3. 4283+ sij = (sj+si) >> 1; 4284+ 4285+ // Now to sort elements si,sij,sj into order & set temp=their median 4286+ if ( (this->*comparison)( si,sij ) > 0 ) { 4287+ (this->*swap)( si,sij ); 4288+ } 4289+ if ( (this->*comparison)( sij,sj ) > 0 ) { 4290+ (this->*swap)( sj,sij ); 4291+ if ( (this->*comparison)( si,sij ) > 0 ) { 4292+ (this->*swap)( si,sij ); 4293+ } 4294+ } 4295+ (this->*copy)( sij,temp ); 4296+ 4297+ // Now to partition into elements <=temp, >=temp, and ==temp. 4298+ sk = si; sL = sj; 4299+ do { 4300+ do { 4301+ sL--; 4302+ } while( (this->*comparison)( sL,temp ) > 0 ); 4303+ do { 4304+ sk++; 4305+ } while( (this->*comparison)( temp,sk ) > 0 ); 4306+ if ( sk < sL ) { 4307+ (this->*swap)( sL,sk ); 4308+ } 4309+ } while(sk <= sL); 4310+ 4311+ // Now to recurse on shorter partition, store longer partition on stack 4312+ if ( sL-si > sj-sk ) { 4313+ if ( sL-si < QQ ) { 4314+ if( m==0 ) { 4315+ break; // empty stack && both partitions < QQ so break 4316+ } else { 4317+ sj = stack[--m]; 4318+ si = stack[--m]; 4319+ } 4320+ } 4321+ else { 4322+ if ( sj-sk < QQ ) { 4323+ sj = sL; 4324+ } else { 4325+ stack[m++] = si; 4326+ stack[m++] = sL; 4327+ si = sk; 4328+ } 4329+ } 4330+ } 4331+ else { 4332+ if ( sj-sk < QQ ) { 4333+ if ( m==0 ) { 4334+ break; // empty stack && both partitions < QQ so break 4335+ } else { 4336+ sj = stack[--m]; 4337+ si = stack[--m]; 4338+ } 4339+ } 4340+ else { 4341+ if ( sL-si < QQ ) { 4342+ si = sk; 4343+ } else { 4344+ stack[m++] = sk; 4345+ stack[m++] = sj; 4346+ sj = sL; 4347+ } 4348+ } 4349+ } 4350+ } 4351+ } 4352+ 4353+ // Now for 0 or Data bounded "straight insertion" sort of [0,nels-1]; if it is 4354+ // known that el[-1] = -INF, then can omit the "sk>=0" test and save time. 4355+ for (si=lowelt; si<highelt; si++) { 4356+ if ( (this->*comparison)( si,si+1 ) > 0 ) { 4357+ (this->*copy)( si+1,temp ); 4358+ sj = sk = si; 4359+ sj++; 4360+ do { 4361+ (this->*copy)( sk,sj ); 4362+ sj = sk; 4363+ sk--; 4364+ } while ( (this->*comparison)( sk,temp ) > 0 && sk>=lowelt ); 4365+ (this->*copy)( temp,sj ); 4366+ } 4367+ } 4368+} 4369+ 4370+// 4371+// Geometric primitives 4372+// 4373+ 4374+// incircle, as in the Guibas-Stolfi paper. 4375+int CDelaunay::incircle(SitePointer a, SitePointer b, SitePointer c, SitePointer d) 4376+{ 4377+ double adx, ady, bdx, bdy, cdx, cdy, dx, dy, nad, nbd, ncd; 4378+ dx = sa[d].X(); 4379+ dy = sa[d].Y(); 4380+ adx = sa[a].X() - dx; 4381+ ady = sa[a].Y() - dy; 4382+ bdx = sa[b].X() - dx; 4383+ bdy = sa[b].Y() - dy; 4384+ cdx = sa[c].X() - dx; 4385+ cdy = sa[c].Y() - dy; 4386+ nad = adx*adx+ady*ady; 4387+ nbd = bdx*bdx+bdy*bdy; 4388+ ncd = cdx*cdx+cdy*cdy; 4389+ return( (0.0 < (nad * (bdx * cdy - bdy * cdx) 4390+ + nbd * (cdx * ady - cdy * adx) 4391+ + ncd * (adx * bdy - ady * bdx))) ? TRUE : FALSE ); 4392+} 4393+ 4394+// TRUE iff A, B, C form a counterclockwise oriented triangle 4395+int CDelaunay::ccw(SitePointer a, SitePointer b, SitePointer c) 4396+{ 4397+ double ax = sa[a].X(); 4398+ double bx = sa[b].X(); 4399+ double cx = sa[c].X(); 4400+ double ay = sa[a].Y(); 4401+ double by = sa[b].Y(); 4402+ double cy = sa[c].Y(); 4403+ 4404+ double val = (ax - cx)*(by - cy) - (bx - cx)*(ay - cy); 4405+ if ( val > 0.0) { 4406+ return true; 4407+ } 4408+ 4409+ return false; 4410+} 4411+ 4412+// 4413+// The Merge Procedure. 4414+// 4415+ 4416+void CDelaunay::doMerge(EdgePointer *ldo, EdgePointer ldi, EdgePointer rdi, EdgePointer *rdo) 4417+{ 4418+ int rvalid, lvalid; 4419+ EdgePointer basel,lcand,rcand,t; 4420+ 4421+ for (;;) { 4422+ while (ccw(orig(ldi), dest(ldi), orig(rdi))) { 4423+ ldi = (EdgePointer) lnext(ldi); 4424+ } 4425+ if (ccw(dest(rdi), orig(rdi), orig(ldi))) { 4426+ rdi = (EdgePointer)rprev(rdi); 4427+ } else { 4428+ break; 4429+ } 4430+ } 4431+ 4432+ basel = connectLeft((EdgePointer) sym(rdi), ldi); 4433+ lcand = rprev(basel); 4434+ rcand = (EdgePointer) oprev(basel); 4435+ if (orig(basel) == orig(*rdo)) { 4436+ *rdo = basel; 4437+ } 4438+ if (dest(basel) == orig(*ldo)) { 4439+ *ldo = (EdgePointer) sym(basel); 4440+ } 4441+ 4442+ for (;;) { 4443+#if 1 4444+ if (valid(t=onext(lcand))) { 4445+#else 4446+ t = (EdgePointer)onext(lcand); 4447+ if (valid(basel, t)) { 4448+#endif 4449+ while (incircle(dest(lcand), dest(t), orig(lcand), orig(basel))) { 4450+ deleteEdge(lcand); 4451+ lcand = t; 4452+ t = onext(lcand); 4453+ } 4454+ } 4455+#if 1 4456+ if (valid(t=(EdgePointer)oprev(rcand))) { 4457+#else 4458+ t = (EdgePointer)oprev(rcand); 4459+ if (valid(basel, t)) { 4460+#endif 4461+ while (incircle(dest(t), dest(rcand), orig(rcand), dest(basel))) { 4462+ deleteEdge(rcand); 4463+ rcand = t; 4464+ t = (EdgePointer)oprev(rcand); 4465+ } 4466+ } 4467+ 4468+#if 1 4469+ lvalid = valid(lcand); 4470+ rvalid = valid(rcand); 4471+#else 4472+ lvalid = valid(basel, lcand); 4473+ rvalid = valid(basel, rcand); 4474+#endif 4475+ if ((! lvalid) && (! rvalid)) { 4476+ return; 4477+ } 4478+ 4479+ if (!lvalid || 4480+ (rvalid && incircle(dest(lcand), orig(lcand), orig(rcand), dest(rcand)))) { 4481+ basel = connectLeft(rcand, (EdgePointer) sym(basel)); 4482+ rcand = (EdgePointer) lnext(sym(basel)); 4483+ } else { 4484+ basel = (EdgePointer) sym(connectRight(lcand, basel)); 4485+ lcand = rprev(basel); 4486+ } 4487+ } 4488+} 4489+ 4490+int CDelaunay::constructList(EdgePointer last, int width, int height) 4491+{ 4492+ int c, i; 4493+ EdgePointer curr, src, nex; 4494+ SEdgeVector *currv, *prevv; 4495+ 4496+ c = (int) ((curr = (EdgePointer) ((last & ~3))) >> 1); 4497+ 4498+ for (last -= 4; last >= 0; last -= 4) { 4499+ src = orig(last); 4500+ nex = dest(last); 4501+ orig(--curr) = src; 4502+ orig(--curr) = nex; 4503+ orig(--curr) = nex; 4504+ orig(--curr) = src; 4505+ } 4506+ rcssort(0, c - 1, -1, &CDelaunay::cmpev, &CDelaunay::swapev, &CDelaunay::copyev); 4507+ 4508+ // Throw out any edges that are too far apart 4509+ currv = prevv = ev; 4510+ for (i = c; i--; currv++) { 4511+ if ((int) fabs(sa[currv->first].getVCenter().x - sa[currv->second].getVCenter().x) <= width && 4512+ (int) fabs(sa[currv->first].getVCenter().y - sa[currv->second].getVCenter().y) <= height) { 4513+ *(prevv++) = *currv; 4514+ } else { 4515+ c--; 4516+ } 4517+ } 4518+ return c; 4519+} 4520+ 4521+// Fill in site neighbor information 4522+void CDelaunay::linkNeighbors(SEdgeVector *edge, int nedge, int nsite) 4523+{ 4524+ int i; 4525+ 4526+ for (i = 0; i < nsite; i++) { 4527+ sa[i].setNeighbor(edge); 4528+ sa[i].setNumNeighbors(0); 4529+ for (; edge->first == i && nedge; edge++, nedge--) { 4530+ sa[i].incrNumNeighbors(); 4531+ } 4532+ } 4533+} 4534diff --git a/benchmark/feature_mos/src/mosaic/Delaunay.h b/benchmark/feature_mos/src/mosaic/Delaunay.h 4535new file mode 100644 4536index 00000000..7a450b5e 4537--- /dev/null 4538+++ b/benchmark/feature_mos/src/mosaic/Delaunay.h 4539@@ -0,0 +1,126 @@ 4540+/* 4541+ * Copyright (C) 2011 The Android Open Source Project 4542+ * 4543+ * Licensed under the Apache License, Version 2.0 (the "License"); 4544+ * you may not use this file except in compliance with the License. 4545+ * You may obtain a copy of the License at 4546+ * 4547+ * http://www.apache.org/licenses/LICENSE-2.0 4548+ * 4549+ * Unless required by applicable law or agreed to in writing, software 4550+ * distributed under the License is distributed on an "AS IS" BASIS, 4551+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4552+ * See the License for the specific language governing permissions and 4553+ * limitations under the License. 4554+ */ 4555+ 4556+// Delaunay.h 4557+// $Id: Delaunay.h,v 1.9 2011/06/17 13:35:48 mbansal Exp $ 4558+ 4559+#ifndef DELAUNAY_H 4560+#define DELAUNAY_H 4561+#include <stdio.h> 4562+#include <math.h> 4563+#include "CSite.h" 4564+#include "EdgePointerUtil.h" 4565+ 4566+#ifndef TRUE 4567+#define TRUE 1==1 4568+#define FALSE 0==1 4569+#endif 4570+ 4571+//****************************************************************************** 4572+// Reference for Quad-edge data structure: 4573+// 4574+// Leonidas Guibas and Jorge Stolfi, "Primitives for the manipulation of general 4575+// subdivisions and the computations of Voronoi diagrams", 4576+// ACM Transactions on Graphics 4, 74-123 (1985). 4577+// 4578+//****************************************************************************** 4579+ 4580+// 4581+// Common data structures 4582+// 4583+ 4584+typedef short SitePointer; 4585+typedef short TrianglePointer; 4586+ 4587+class CDelaunay 4588+{ 4589+private: 4590+ CSite *sa; 4591+ EdgePointer oneBndryEdge; 4592+ EdgePointer *next; 4593+ SitePointer *org; 4594+ struct EDGE_INFO *ei; 4595+ SitePointer *sp; 4596+ SEdgeVector *ev; 4597+ 4598+ SitePointer sp1; 4599+ EdgePointer nextEdge; 4600+ EdgePointer availEdge; 4601+ 4602+private: 4603+ void build(int lo, int hi, EdgePointer *le, EdgePointer *re, int rows); 4604+ void buildTriangulation(int size); 4605+ 4606+ EdgePointer allocEdge(); 4607+ void freeEdge(EdgePointer e); 4608+ 4609+ EdgePointer makeEdge(SitePointer origin, SitePointer destination); 4610+ void deleteEdge(EdgePointer e); 4611+ 4612+ void splice(EdgePointer, EdgePointer); 4613+ EdgePointer consolidateEdges(); 4614+ void deleteAllEdges(); 4615+ 4616+ void spsortx(SitePointer *, int, int); 4617+ void spsorty(SitePointer *, int, int); 4618+ 4619+ int cmpev(int i, int j); 4620+ int xcmpsp(int i, int j); 4621+ int ycmpsp(int i, int j); 4622+ 4623+ void swapsp(int i, int j); 4624+ void swapev(int i, int j); 4625+ 4626+ void copysp(int i, int j); 4627+ void copyev(int i, int j); 4628+ 4629+ void rcssort(int lowelt, int highelt, int temp, 4630+ int (CDelaunay::*comparison)(int,int), 4631+ void (CDelaunay::*swap)(int,int), 4632+ void (CDelaunay::*copy)(int,int)); 4633+ 4634+ void doMerge(EdgePointer *ldo, EdgePointer ldi, EdgePointer rdi, EdgePointer *rdo); 4635+ EdgePointer connectLeft(EdgePointer a, EdgePointer b); 4636+ EdgePointer connectRight(EdgePointer a, EdgePointer b); 4637+ int ccw(SitePointer a, SitePointer b, SitePointer c); 4638+ int incircle(SitePointer a, SitePointer b, SitePointer c, SitePointer d); 4639+ int constructList(EdgePointer e, int width, int height); 4640+ 4641+public: 4642+ CDelaunay(); 4643+ ~CDelaunay(); 4644+ 4645+ CSite *allocMemory(int nsite); 4646+ void freeMemory(); 4647+ int triangulate(SEdgeVector **edge, int nsite, int width, int height); 4648+ void linkNeighbors(SEdgeVector *edge, int nedge, int nsite); 4649+}; 4650+ 4651+#define onext(a) next[a] 4652+#define oprev(a) rot(onext(rot(a))) 4653+#define lnext(a) rot(onext(rotinv(a))) 4654+#define lprev(a) sym(onext(a)) 4655+#define rnext(a) rotinv(onext(rot(a))) 4656+#define rprev(a) onext(sym(a)) 4657+#define dnext(a) sym(onext(sym(a))) 4658+#define dprev(a) rotinv(onext(rotinv(a))) 4659+ 4660+#define orig(a) org[a] 4661+#define dest(a) orig(sym(a)) 4662+#define left(a) orig(rotinv(a)) 4663+#define right(a) orig(rot(a)) 4664+ 4665+#endif 4666diff --git a/benchmark/feature_mos/src/mosaic/EdgePointerUtil.h b/benchmark/feature_mos/src/mosaic/EdgePointerUtil.h 4667new file mode 100644 4668index 00000000..fad05d7e 4669--- /dev/null 4670+++ b/benchmark/feature_mos/src/mosaic/EdgePointerUtil.h 4671@@ -0,0 +1,37 @@ 4672+/* 4673+ * Copyright (C) 2011 The Android Open Source Project 4674+ * 4675+ * Licensed under the Apache License, Version 2.0 (the "License"); 4676+ * you may not use this file except in compliance with the License. 4677+ * You may obtain a copy of the License at 4678+ * 4679+ * http://www.apache.org/licenses/LICENSE-2.0 4680+ * 4681+ * Unless required by applicable law or agreed to in writing, software 4682+ * distributed under the License is distributed on an "AS IS" BASIS, 4683+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4684+ * See the License for the specific language governing permissions and 4685+ * limitations under the License. 4686+ */ 4687+ 4688+#ifndef _EDGEPOINTERUTIL_H_ 4689+#define _EDGEPOINTERUTIL_H_ 4690+ 4691+typedef short EdgePointer; 4692+ 4693+inline EdgePointer sym(EdgePointer a) 4694+{ 4695+ return a ^ 2; 4696+} 4697+ 4698+inline EdgePointer rot(EdgePointer a) 4699+{ 4700+ return (((a) + 1) & 3) | ((a) & ~3); 4701+} 4702+ 4703+inline EdgePointer rotinv(EdgePointer a) 4704+{ 4705+ return (((a) + 3) & 3) | ((a) & ~3); 4706+} 4707+ 4708+#endif //_EDGEPOINTERUTIL_H_ 4709diff --git a/benchmark/feature_mos/src/mosaic/Geometry.h b/benchmark/feature_mos/src/mosaic/Geometry.h 4710new file mode 100644 4711index 00000000..0efa0f4a 4712--- /dev/null 4713+++ b/benchmark/feature_mos/src/mosaic/Geometry.h 4714@@ -0,0 +1,156 @@ 4715+/* 4716+ * Copyright (C) 2011 The Android Open Source Project 4717+ * 4718+ * Licensed under the Apache License, Version 2.0 (the "License"); 4719+ * you may not use this file except in compliance with the License. 4720+ * You may obtain a copy of the License at 4721+ * 4722+ * http://www.apache.org/licenses/LICENSE-2.0 4723+ * 4724+ * Unless required by applicable law or agreed to in writing, software 4725+ * distributed under the License is distributed on an "AS IS" BASIS, 4726+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4727+ * See the License for the specific language governing permissions and 4728+ * limitations under the License. 4729+ */ 4730+ 4731+///////////////////////////// 4732+// Geometry.h 4733+// $Id: Geometry.h,v 1.2 2011/06/17 13:35:48 mbansal Exp $ 4734+ 4735+#pragma once 4736+#include "MosaicTypes.h" 4737+ 4738+/////////////////////////////////////////////////////////////// 4739+///////////////// BEG GLOBAL ROUTINES ///////////////////////// 4740+/////////////////////////////////////////////////////////////// 4741+ 4742+ 4743+inline double hypotSq(double a, double b) 4744+{ 4745+ return ((a)*(a)+(b)*(b)); 4746+} 4747+ 4748+inline void ClipRect(double x, double y, BlendRect &brect) 4749+{ 4750+ if (y < brect.bot) brect.bot = y; 4751+ if (y > brect.top) brect.top = y; 4752+ if (x < brect.lft) brect.lft = x; 4753+ if (x > brect.rgt) brect.rgt = x; 4754+} 4755+ 4756+inline void ClipRect(BlendRect rrect, BlendRect &brect) 4757+{ 4758+ if (rrect.bot < brect.bot) brect.bot = rrect.bot; 4759+ if (rrect.top > brect.top) brect.top = rrect.top; 4760+ if (rrect.lft < brect.lft) brect.lft = rrect.lft; 4761+ if (rrect.rgt > brect.rgt) brect.rgt = rrect.rgt; 4762+} 4763+ 4764+// Clip x to be within [-border,width+border-1] 4765+inline void clipToSegment(int &x, int width, int border) 4766+{ 4767+ if(x < -border) 4768+ x = -border; 4769+ else if(x >= width+border) 4770+ x = width + border - 1; 4771+} 4772+ 4773+// Return true if x within [-border,width+border-1] 4774+inline bool inSegment(int x, int width, int border) 4775+{ 4776+ return (x >= -border && x < width + border - 1); 4777+} 4778+ 4779+inline void FindTriangleCentroid(double x0, double y0, double x1, double y1, 4780+ double x2, double y2, 4781+ double &mass, double ¢X, double ¢Y) 4782+{ 4783+ // Calculate the centroid of the triangle 4784+ centX = (x0 + x1 + x2) / 3.0; 4785+ centY = (y0 + y1 + y2) / 3.0; 4786+ 4787+ // Calculate 2*Area for the triangle 4788+ if (y0 == y2) 4789+ { 4790+ if (x0 == x1) 4791+ { 4792+ mass = fabs((y1 - y0) * (x2 - x0)); // Special case 1a 4793+ } 4794+ else 4795+ { 4796+ mass = fabs((y1 - y0) * (x1 - x0)); // Special case 1b 4797+ } 4798+ } 4799+ else if (x0 == x2) 4800+ { 4801+ if (x0 == x1) 4802+ { 4803+ mass = fabs((x2 - x0) * (y2 - y0)); // Special case 2a 4804+ } 4805+ else 4806+ { 4807+ mass = fabs((x1 - x0) * (y2 - y0)); // Special case 2a 4808+ } 4809+ } 4810+ else if (x1 == x2) 4811+ { 4812+ mass = fabs((x1 - x0) * (y2 - y0)); // Special case 3 4813+ } 4814+ else 4815+ { 4816+ // Calculate line equation from x0,y0 to x2,y2 4817+ double dx = x2 - x0; 4818+ double dy = y2 - y0; 4819+ // Calculate the length of the side 4820+ double len1 = sqrt(dx * dx + dy * dy); 4821+ double m1 = dy / dx; 4822+ double b1 = y0 - m1 * x0; 4823+ // Calculate the line that goes through x1,y1 and is perpendicular to 4824+ // the other line 4825+ double m2 = 1.0 / m1; 4826+ double b2 = y1 - m2 * x1; 4827+ // Calculate the intersection of the two lines 4828+ if (fabs( m1 - m2 ) > 1.e-6) 4829+ { 4830+ double x = (b2 - b1) / (m1 - m2); 4831+ // the mass is the base * height 4832+ dx = x1 - x; 4833+ dy = y1 - m1 * x + b1; 4834+ mass = len1 * sqrt(dx * dx + dy * dy); 4835+ } 4836+ else 4837+ { 4838+ mass = fabs( (y1 - y0) * (x2 - x0) ); 4839+ } 4840+ } 4841+} 4842+ 4843+inline void FindQuadCentroid(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3, 4844+ double ¢X, double ¢Y) 4845+ 4846+{ 4847+ // To find the centroid: 4848+ // 1) Divide the quadrilateral into two triangles by scribing a diagonal 4849+ // 2) Calculate the centroid of each triangle (the intersection of the angle bisections). 4850+ // 3) Find the centroid of the quad by weighting each triangle centroids by their area. 4851+ 4852+ // Calculate the corner points 4853+ double z; 4854+ 4855+ // The quad is split from x0,y0 to x2,y2 4856+ double mass1, mass2, cent1x, cent2x, cent1y, cent2y; 4857+ FindTriangleCentroid(x0, y0, x1, y1, x2, y2, mass1, cent1x, cent1y); 4858+ FindTriangleCentroid(x0, y0, x3, y3, x2, y2, mass2, cent2x, cent2y); 4859+ 4860+ // determine position of quad centroid 4861+ z = mass2 / (mass1 + mass2); 4862+ centX = cent1x + (cent2x - cent1x) * z; 4863+ centY = cent1y + (cent2y - cent1y) * z; 4864+} 4865+ 4866+/////////////////////////////////////////////////////////////// 4867+////////////////// END GLOBAL ROUTINES //////////////////////// 4868+/////////////////////////////////////////////////////////////// 4869+ 4870+ 4871diff --git a/benchmark/feature_mos/src/mosaic/ImageUtils.cpp b/benchmark/feature_mos/src/mosaic/ImageUtils.cpp 4872new file mode 100644 4873index 00000000..28629d34 4874--- /dev/null 4875+++ b/benchmark/feature_mos/src/mosaic/ImageUtils.cpp 4876@@ -0,0 +1,406 @@ 4877+/* 4878+ * Copyright (C) 2011 The Android Open Source Project 4879+ * 4880+ * Licensed under the Apache License, Version 2.0 (the "License"); 4881+ * you may not use this file except in compliance with the License. 4882+ * You may obtain a copy of the License at 4883+ * 4884+ * http://www.apache.org/licenses/LICENSE-2.0 4885+ * 4886+ * Unless required by applicable law or agreed to in writing, software 4887+ * distributed under the License is distributed on an "AS IS" BASIS, 4888+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4889+ * See the License for the specific language governing permissions and 4890+ * limitations under the License. 4891+ */ 4892+ 4893+/////////////////////////////////////////////////// 4894+// ImageUtils.cpp 4895+// $Id: ImageUtils.cpp,v 1.12 2011/06/17 13:35:48 mbansal Exp $ 4896+ 4897+ 4898+#include <stdio.h> 4899+#include <stdlib.h> 4900+#include <sys/time.h> 4901+ 4902+#include "ImageUtils.h" 4903+ 4904+void ImageUtils::rgba2yvu(ImageType out, ImageType in, int width, int height) 4905+{ 4906+ int r,g,b, a; 4907+ ImageType yimg = out; 4908+ ImageType vimg = yimg + width*height; 4909+ ImageType uimg = vimg + width*height; 4910+ ImageType image = in; 4911+ 4912+ for (int ii = 0; ii < height; ii++) { 4913+ for (int ij = 0; ij < width; ij++) { 4914+ r = (*image++); 4915+ g = (*image++); 4916+ b = (*image++); 4917+ a = (*image++); 4918+ 4919+ if (r < 0) r = 0; 4920+ if (r > 255) r = 255; 4921+ if (g < 0) g = 0; 4922+ if (g > 255) g = 255; 4923+ if (b < 0) b = 0; 4924+ if (b > 255) b = 255; 4925+ 4926+ int val = (int) (REDY * r + GREENY * g + BLUEY * b) / 1000 + 16; 4927+ if (val < 0) val = 0; 4928+ if (val > 255) val = 255; 4929+ *(yimg) = val; 4930+ 4931+ val = (int) (REDV * r - GREENV * g - BLUEV * b) / 1000 + 128; 4932+ if (val < 0) val = 0; 4933+ if (val > 255) val = 255; 4934+ *(vimg) = val; 4935+ 4936+ val = (int) (-REDU * r - GREENU * g + BLUEU * b) / 1000 + 128; 4937+ if (val < 0) val = 0; 4938+ if (val > 255) val = 255; 4939+ *(uimg) = val; 4940+ 4941+ yimg++; 4942+ uimg++; 4943+ vimg++; 4944+ } 4945+ } 4946+} 4947+ 4948+ 4949+void ImageUtils::rgb2yvu(ImageType out, ImageType in, int width, int height) 4950+{ 4951+ int r,g,b; 4952+ ImageType yimg = out; 4953+ ImageType vimg = yimg + width*height; 4954+ ImageType uimg = vimg + width*height; 4955+ ImageType image = in; 4956+ 4957+ for (int ii = 0; ii < height; ii++) { 4958+ for (int ij = 0; ij < width; ij++) { 4959+ r = (*image++); 4960+ g = (*image++); 4961+ b = (*image++); 4962+ 4963+ if (r < 0) r = 0; 4964+ if (r > 255) r = 255; 4965+ if (g < 0) g = 0; 4966+ if (g > 255) g = 255; 4967+ if (b < 0) b = 0; 4968+ if (b > 255) b = 255; 4969+ 4970+ int val = (int) (REDY * r + GREENY * g + BLUEY * b) / 1000 + 16; 4971+ if (val < 0) val = 0; 4972+ if (val > 255) val = 255; 4973+ *(yimg) = val; 4974+ 4975+ val = (int) (REDV * r - GREENV * g - BLUEV * b) / 1000 + 128; 4976+ if (val < 0) val = 0; 4977+ if (val > 255) val = 255; 4978+ *(vimg) = val; 4979+ 4980+ val = (int) (-REDU * r - GREENU * g + BLUEU * b) / 1000 + 128; 4981+ if (val < 0) val = 0; 4982+ if (val > 255) val = 255; 4983+ *(uimg) = val; 4984+ 4985+ yimg++; 4986+ uimg++; 4987+ vimg++; 4988+ } 4989+ } 4990+} 4991+ 4992+ImageType ImageUtils::rgb2gray(ImageType in, int width, int height) 4993+{ 4994+ int r,g,b; 4995+ ImageType image = in; 4996+ ImageType out = ImageUtils::allocateImage(width, height, 1); 4997+ ImageType outCopy = out; 4998+ 4999+ for (int ii = 0; ii < height; ii++) { 5000+ for (int ij = 0; ij < width; ij++) { 5001+ r = (*image++); 5002+ g = (*image++); 5003+ b = (*image++); 5004+ 5005+ if (r < 0) r = 0; 5006+ if (r > 255) r = 255; 5007+ if (g < 0) g = 0; 5008+ if (g > 255) g = 255; 5009+ if (b < 0) b = 0; 5010+ if (b > 255) b = 255; 5011+ 5012+ (*outCopy) = ( 0.3*r + 0.59*g + 0.11*b); 5013+ 5014+ outCopy++; 5015+ } 5016+ } 5017+ 5018+ return out; 5019+} 5020+ 5021+ImageType ImageUtils::rgb2gray(ImageType out, ImageType in, int width, int height) 5022+{ 5023+ int r,g,b; 5024+ ImageType image = in; 5025+ ImageType outCopy = out; 5026+ 5027+ for (int ii = 0; ii < height; ii++) { 5028+ for (int ij = 0; ij < width; ij++) { 5029+ r = (*image++); 5030+ g = (*image++); 5031+ b = (*image++); 5032+ 5033+ if (r < 0) r = 0; 5034+ if (r > 255) r = 255; 5035+ if (g < 0) g = 0; 5036+ if (g > 255) g = 255; 5037+ if (b < 0) b = 0; 5038+ if (b > 255) b = 255; 5039+ 5040+ (*outCopy) = ( 0.3*r + 0.59*g + 0.11*b); 5041+ 5042+ outCopy++; 5043+ } 5044+ } 5045+ 5046+ return out; 5047+ 5048+} 5049+ 5050+ImageType *ImageUtils::imageTypeToRowPointers(ImageType in, int width, int height) 5051+{ 5052+ int i; 5053+ int m_h = height; 5054+ int m_w = width; 5055+ 5056+ ImageType *m_rows = new ImageType[m_h]; 5057+ 5058+ for (i=0;i<m_h;i++) { 5059+ m_rows[i] = &in[(m_w)*i]; 5060+ } 5061+ return m_rows; 5062+} 5063+ 5064+void ImageUtils::yvu2rgb(ImageType out, ImageType in, int width, int height) 5065+{ 5066+ int y,v,u, r, g, b; 5067+ unsigned char *yimg = in; 5068+ unsigned char *vimg = yimg + width*height; 5069+ unsigned char *uimg = vimg + width*height; 5070+ unsigned char *image = out; 5071+ 5072+ for (int i = 0; i < height; i++) { 5073+ for (int j = 0; j < width; j++) { 5074+ 5075+ y = (*yimg); 5076+ v = (*vimg); 5077+ u = (*uimg); 5078+ 5079+ if (y < 0) y = 0; 5080+ if (y > 255) y = 255; 5081+ if (u < 0) u = 0; 5082+ if (u > 255) u = 255; 5083+ if (v < 0) v = 0; 5084+ if (v > 255) v = 255; 5085+ 5086+ b = (int) ( 1.164*(y - 16) + 2.018*(u-128)); 5087+ g = (int) ( 1.164*(y - 16) - 0.813*(v-128) - 0.391*(u-128)); 5088+ r = (int) ( 1.164*(y - 16) + 1.596*(v-128)); 5089+ 5090+ if (r < 0) r = 0; 5091+ if (r > 255) r = 255; 5092+ if (g < 0) g = 0; 5093+ if (g > 255) g = 255; 5094+ if (b < 0) b = 0; 5095+ if (b > 255) b = 255; 5096+ 5097+ *(image++) = r; 5098+ *(image++) = g; 5099+ *(image++) = b; 5100+ 5101+ yimg++; 5102+ uimg++; 5103+ vimg++; 5104+ 5105+ } 5106+ } 5107+} 5108+ 5109+void ImageUtils::yvu2bgr(ImageType out, ImageType in, int width, int height) 5110+{ 5111+ int y,v,u, r, g, b; 5112+ unsigned char *yimg = in; 5113+ unsigned char *vimg = yimg + width*height; 5114+ unsigned char *uimg = vimg + width*height; 5115+ unsigned char *image = out; 5116+ 5117+ for (int i = 0; i < height; i++) { 5118+ for (int j = 0; j < width; j++) { 5119+ 5120+ y = (*yimg); 5121+ v = (*vimg); 5122+ u = (*uimg); 5123+ 5124+ if (y < 0) y = 0; 5125+ if (y > 255) y = 255; 5126+ if (u < 0) u = 0; 5127+ if (u > 255) u = 255; 5128+ if (v < 0) v = 0; 5129+ if (v > 255) v = 255; 5130+ 5131+ b = (int) ( 1.164*(y - 16) + 2.018*(u-128)); 5132+ g = (int) ( 1.164*(y - 16) - 0.813*(v-128) - 0.391*(u-128)); 5133+ r = (int) ( 1.164*(y - 16) + 1.596*(v-128)); 5134+ 5135+ if (r < 0) r = 0; 5136+ if (r > 255) r = 255; 5137+ if (g < 0) g = 0; 5138+ if (g > 255) g = 255; 5139+ if (b < 0) b = 0; 5140+ if (b > 255) b = 255; 5141+ 5142+ *(image++) = b; 5143+ *(image++) = g; 5144+ *(image++) = r; 5145+ 5146+ yimg++; 5147+ uimg++; 5148+ vimg++; 5149+ 5150+ } 5151+ } 5152+} 5153+ 5154+ 5155+ImageType ImageUtils::readBinaryPPM(const char *filename, int &width, int &height) 5156+{ 5157+ 5158+ FILE *imgin = NULL; 5159+ int mval=0, format=0, eret; 5160+ ImageType ret = NULL;//IMAGE_TYPE_NOIMAGE; 5161+ 5162+ imgin = fopen(filename, "r"); 5163+ if (imgin == NULL) { 5164+ fprintf(stderr, "Error: Filename %s not found\n", filename); 5165+ return ret; 5166+ } 5167+ 5168+ eret = fscanf(imgin, "P%d\n", &format); 5169+ if (format != 6) { 5170+ fprintf(stderr, "Error: readBinaryPPM only supports PPM format (P6)\n"); 5171+ return ret; 5172+ } 5173+ 5174+ eret = fscanf(imgin, "%d %d\n", &width, &height); 5175+ eret = fscanf(imgin, "%d\n", &mval); 5176+ ret = allocateImage(width, height, IMAGE_TYPE_NUM_CHANNELS); 5177+ eret = fread(ret, sizeof(ImageTypeBase), IMAGE_TYPE_NUM_CHANNELS*width*height, imgin); 5178+ 5179+ fclose(imgin); 5180+ 5181+ return ret; 5182+ 5183+} 5184+ 5185+void ImageUtils::writeBinaryPPM(ImageType image, const char *filename, int width, int height, int numChannels) 5186+{ 5187+ FILE *imgout = fopen(filename, "w"); 5188+ 5189+ if (imgout == NULL) { 5190+ fprintf(stderr, "Error: Filename %s could not be opened for writing\n", filename); 5191+ return; 5192+ } 5193+ 5194+ if (numChannels == 3) { 5195+ fprintf(imgout, "P6\n%d %d\n255\n", width, height); 5196+ } else if (numChannels == 1) { 5197+ fprintf(imgout, "P5\n%d %d\n255\n", width, height); 5198+ } else { 5199+ fprintf(stderr, "Error: writeBinaryPPM: Unsupported number of channels\n"); 5200+ } 5201+ fwrite(image, sizeof(ImageTypeBase), numChannels*width*height, imgout); 5202+ 5203+ fclose(imgout); 5204+ 5205+} 5206+ 5207+ImageType ImageUtils::allocateImage(int width, int height, int numChannels, short int border) 5208+{ 5209+ int overallocation = 256; 5210+ return (ImageType) calloc(width*height*numChannels+overallocation, sizeof(ImageTypeBase)); 5211+} 5212+ 5213+ 5214+void ImageUtils::freeImage(ImageType image) 5215+{ 5216+ free(image); 5217+} 5218+ 5219+ 5220+// allocation of one color image used for tmp buffers, etc. 5221+// format of contiguous memory block: 5222+// YUVInfo struct (type + BimageInfo for Y,U, and V), 5223+// Y row pointers 5224+// U row pointers 5225+// V row pointers 5226+// Y image pixels 5227+// U image pixels 5228+// V image pixels 5229+YUVinfo *YUVinfo::allocateImage(unsigned short width, unsigned short height) 5230+{ 5231+ unsigned short heightUV, widthUV; 5232+ 5233+ widthUV = width; 5234+ heightUV = height; 5235+ 5236+ // figure out how much space to hold all pixels... 5237+ int size = ((width * height * 3) + 8); 5238+ unsigned char *position = 0; 5239+ 5240+ // VC 8 does not like calling free on yuv->Y.ptr since it is in 5241+ // the middle of a block. So rearrange the memory layout so after 5242+ // calling mapYUVInforToImage yuv->Y.ptr points to the begginning 5243+ // of the calloc'ed block. 5244+ YUVinfo *yuv = (YUVinfo *) calloc(sizeof(YUVinfo), 1); 5245+ if (yuv) { 5246+ yuv->Y.width = yuv->Y.pitch = width; 5247+ yuv->Y.height = height; 5248+ yuv->Y.border = yuv->U.border = yuv->V.border = (unsigned short) 0; 5249+ yuv->U.width = yuv->U.pitch = yuv->V.width = yuv->V.pitch = widthUV; 5250+ yuv->U.height = yuv->V.height = heightUV; 5251+ 5252+ unsigned char* block = (unsigned char*) calloc( 5253+ sizeof(unsigned char *) * (height + heightUV + heightUV) + 5254+ sizeof(unsigned char) * size, 1); 5255+ 5256+ position = block; 5257+ unsigned char **y = (unsigned char **) (block + size); 5258+ 5259+ /* Initialize and assign row pointers */ 5260+ yuv->Y.ptr = y; 5261+ yuv->V.ptr = &y[height]; 5262+ yuv->U.ptr = &y[height + heightUV]; 5263+ } 5264+ if (size) 5265+ mapYUVInfoToImage(yuv, position); 5266+ return yuv; 5267+} 5268+ 5269+// wrap YUVInfo row pointers around 3 contiguous image (color component) planes. 5270+// position = starting pixel in image. 5271+void YUVinfo::mapYUVInfoToImage(YUVinfo *img, unsigned char *position) 5272+{ 5273+ int i; 5274+ for (i = 0; i < img->Y.height; i++, position += img->Y.width) 5275+ img->Y.ptr[i] = position; 5276+ for (i = 0; i < img->V.height; i++, position += img->V.width) 5277+ img->V.ptr[i] = position; 5278+ for (i = 0; i < img->U.height; i++, position += img->U.width) 5279+ img->U.ptr[i] = position; 5280+} 5281+ 5282+ 5283diff --git a/benchmark/feature_mos/src/mosaic/ImageUtils.h b/benchmark/feature_mos/src/mosaic/ImageUtils.h 5284new file mode 100644 5285index 00000000..92965ca8 5286--- /dev/null 5287+++ b/benchmark/feature_mos/src/mosaic/ImageUtils.h 5288@@ -0,0 +1,173 @@ 5289+/* 5290+ * Copyright (C) 2011 The Android Open Source Project 5291+ * 5292+ * Licensed under the Apache License, Version 2.0 (the "License"); 5293+ * you may not use this file except in compliance with the License. 5294+ * You may obtain a copy of the License at 5295+ * 5296+ * http://www.apache.org/licenses/LICENSE-2.0 5297+ * 5298+ * Unless required by applicable law or agreed to in writing, software 5299+ * distributed under the License is distributed on an "AS IS" BASIS, 5300+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5301+ * See the License for the specific language governing permissions and 5302+ * limitations under the License. 5303+ */ 5304+ 5305+/////////////////////////////////////////////////// 5306+// ImageUtils.h 5307+// $Id: ImageUtils.h,v 1.9 2011/05/16 15:33:06 mbansal Exp $ 5308+ 5309+#ifndef IMAGE_UTILS_H 5310+#define IMAGE_UTILS_H 5311+ 5312+#include <stdlib.h> 5313+ 5314+/** 5315+ * Definition of basic image types 5316+ */ 5317+typedef unsigned char ImageTypeBase; 5318+typedef ImageTypeBase *ImageType; 5319+ 5320+typedef short ImageTypeShortBase; 5321+typedef ImageTypeShortBase *ImageTypeShort; 5322+ 5323+typedef float ImageTypeFloatBase; 5324+typedef ImageTypeFloatBase *ImageTypeFloat; 5325+ 5326+ 5327+class ImageUtils { 5328+public: 5329+ 5330+ /** 5331+ * Default number of channels in image. 5332+ */ 5333+ static const int IMAGE_TYPE_NUM_CHANNELS = 3; 5334+ 5335+ /** 5336+ * Definition of an empty image. 5337+ */ 5338+ static const int IMAGE_TYPE_NOIMAGE = 0; 5339+ 5340+ /** 5341+ * Convert image from BGR (interlaced) to YVU (non-interlaced) 5342+ * 5343+ * Arguments: 5344+ * out: Resulting image (note must be preallocated before 5345+ * call) 5346+ * in: Input image 5347+ * width: Width of input image 5348+ * height: Height of input image 5349+ */ 5350+ static void rgb2yvu(ImageType out, ImageType in, int width, int height); 5351+ 5352+ static void rgba2yvu(ImageType out, ImageType in, int width, int height); 5353+ 5354+ /** 5355+ * Convert image from YVU (non-interlaced) to BGR (interlaced) 5356+ * 5357+ * Arguments: 5358+ * out: Resulting image (note must be preallocated before 5359+ * call) 5360+ * in: Input image 5361+ * width: Width of input image 5362+ * height: Height of input image 5363+ */ 5364+ static void yvu2rgb(ImageType out, ImageType in, int width, int height); 5365+ static void yvu2bgr(ImageType out, ImageType in, int width, int height); 5366+ 5367+ /** 5368+ * Convert image from BGR to grayscale 5369+ * 5370+ * Arguments: 5371+ * in: Input image 5372+ * width: Width of input image 5373+ * height: Height of input image 5374+ * 5375+ * Return: 5376+ * Pointer to resulting image (allocation is done here, free 5377+ * must be done by caller) 5378+ */ 5379+ static ImageType rgb2gray(ImageType in, int width, int height); 5380+ static ImageType rgb2gray(ImageType out, ImageType in, int width, int height); 5381+ 5382+ /** 5383+ * Read a binary PPM image 5384+ */ 5385+ static ImageType readBinaryPPM(const char *filename, int &width, int &height); 5386+ 5387+ /** 5388+ * Write a binary PPM image 5389+ */ 5390+ static void writeBinaryPPM(ImageType image, const char *filename, int width, int height, int numChannels = IMAGE_TYPE_NUM_CHANNELS); 5391+ 5392+ /** 5393+ * Allocate space for a standard image. 5394+ */ 5395+ static ImageType allocateImage(int width, int height, int numChannels, short int border = 0); 5396+ 5397+ /** 5398+ * Free memory of image 5399+ */ 5400+ static void freeImage(ImageType image); 5401+ 5402+ static ImageType *imageTypeToRowPointers(ImageType out, int width, int height); 5403+ /** 5404+ * Get time. 5405+ */ 5406+ static double getTime(); 5407+ 5408+protected: 5409+ 5410+ /** 5411+ * Constants for YVU/RGB conversion 5412+ */ 5413+ static const int REDY = 257; 5414+ static const int REDV = 439; 5415+ static const int REDU = 148; 5416+ static const int GREENY = 504; 5417+ static const int GREENV = 368; 5418+ static const int GREENU = 291; 5419+ static const int BLUEY = 98; 5420+ static const int BLUEV = 71; 5421+ static const int BLUEU = 439; 5422+ 5423+}; 5424+ 5425+/** 5426+ * Structure containing an image and other bookkeeping items. 5427+ * Used in YUVinfo to store separate YVU image planes. 5428+ */ 5429+typedef struct { 5430+ ImageType *ptr; 5431+ unsigned short width; 5432+ unsigned short height; 5433+ unsigned short border; 5434+ unsigned short pitch; 5435+} BimageInfo; 5436+ 5437+/** 5438+ * A YUV image container, 5439+ */ 5440+class YUVinfo { 5441+public: 5442+ static YUVinfo *allocateImage(unsigned short width, unsigned short height); 5443+ static void mapYUVInfoToImage(YUVinfo *img, unsigned char *position); 5444+ 5445+ /** 5446+ * Y Plane 5447+ */ 5448+ BimageInfo Y; 5449+ 5450+ /** 5451+ * V (1st color) plane 5452+ */ 5453+ BimageInfo V; 5454+ 5455+ /** 5456+ * U (1st color) plane 5457+ */ 5458+ BimageInfo U; 5459+}; 5460+ 5461+#endif 5462diff --git a/benchmark/feature_mos/src/mosaic/Interp.h b/benchmark/feature_mos/src/mosaic/Interp.h 5463new file mode 100644 5464index 00000000..19c4a40c 5465--- /dev/null 5466+++ b/benchmark/feature_mos/src/mosaic/Interp.h 5467@@ -0,0 +1,80 @@ 5468+/* 5469+ * Copyright (C) 2011 The Android Open Source Project 5470+ * 5471+ * Licensed under the Apache License, Version 2.0 (the "License"); 5472+ * you may not use this file except in compliance with the License. 5473+ * You may obtain a copy of the License at 5474+ * 5475+ * http://www.apache.org/licenses/LICENSE-2.0 5476+ * 5477+ * Unless required by applicable law or agreed to in writing, software 5478+ * distributed under the License is distributed on an "AS IS" BASIS, 5479+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5480+ * See the License for the specific language governing permissions and 5481+ * limitations under the License. 5482+ */ 5483+ 5484+/////////////////////////////////////////////////////////// 5485+// Interp.h 5486+// $Id: Interp.h,v 1.2 2011/06/17 13:35:48 mbansal Exp $ 5487+ 5488+#ifndef INTERP_H 5489+#define INTERP_H 5490+ 5491+#include "Pyramid.h" 5492+ 5493+#define CTAPS 40 5494+static double ciTable[81] = { 5495+ 1, 0.998461, 0.993938, 0.98657, 0.9765, 5496+ 0.963867, 0.948813, 0.931477, 0.912, 0.890523, 5497+ 0.867188, 0.842133, 0.8155, 0.78743, 0.758062, 5498+ 0.727539, 0.696, 0.663586, 0.630437, 0.596695, 5499+ 0.5625, 0.527992, 0.493312, 0.458602, 0.424, 5500+ 0.389648, 0.355687, 0.322258, 0.2895, 0.257555, 5501+ 0.226562, 0.196664, 0.168, 0.140711, 0.114937, 5502+ 0.0908203, 0.0685, 0.0481172, 0.0298125, 0.0137266, 5503+ 0, -0.0118828, -0.0225625, -0.0320859, -0.0405, 5504+ -0.0478516, -0.0541875, -0.0595547, -0.064, -0.0675703, 5505+ -0.0703125, -0.0722734, -0.0735, -0.0740391, -0.0739375, 5506+ -0.0732422, -0.072, -0.0702578, -0.0680625, -0.0654609, 5507+ -0.0625, -0.0592266, -0.0556875, -0.0519297, -0.048, 5508+ -0.0439453, -0.0398125, -0.0356484, -0.0315, -0.0274141, 5509+ -0.0234375, -0.0196172, -0.016, -0.0126328, -0.0095625, 5510+ -0.00683594, -0.0045, -0.00260156, -0.0011875, -0.000304687, 0.0 5511+}; 5512+ 5513+inline double ciCalc(PyramidShort *img, int xi, int yi, double xfrac, double yfrac) 5514+{ 5515+ double tmpf[4]; 5516+ 5517+ // Interpolate using 16 points 5518+ ImageTypeShortBase *in = img->ptr[yi-1] + xi - 1; 5519+ int off = (int)(xfrac * CTAPS); 5520+ 5521+ tmpf[0] = in[0] * ciTable[off + 40]; 5522+ tmpf[0] += in[1] * ciTable[off]; 5523+ tmpf[0] += in[2] * ciTable[40 - off]; 5524+ tmpf[0] += in[3] * ciTable[80 - off]; 5525+ in += img->pitch; 5526+ tmpf[1] = in[0] * ciTable[off + 40]; 5527+ tmpf[1] += in[1] * ciTable[off]; 5528+ tmpf[1] += in[2] * ciTable[40 - off]; 5529+ tmpf[1] += in[3] * ciTable[80 - off]; 5530+ in += img->pitch; 5531+ tmpf[2] = in[0] * ciTable[off + 40]; 5532+ tmpf[2] += in[1] * ciTable[off]; 5533+ tmpf[2] += in[2] * ciTable[40 - off]; 5534+ tmpf[2] += in[3] * ciTable[80 - off]; 5535+ in += img->pitch; 5536+ tmpf[3] = in[0] * ciTable[off + 40]; 5537+ tmpf[3] += in[1] * ciTable[off]; 5538+ tmpf[3] += in[2] * ciTable[40 - off]; 5539+ tmpf[3] += in[3] * ciTable[80 - off]; 5540+ 5541+ // this is the final interpolation 5542+ off = (int)(yfrac * CTAPS); 5543+ return (ciTable[off + 40] * tmpf[0] + ciTable[off] * tmpf[1] + 5544+ ciTable[40 - off] * tmpf[2] + ciTable[80 - off] * tmpf[3]); 5545+} 5546+ 5547+#endif 5548diff --git a/benchmark/feature_mos/src/mosaic/Log.h b/benchmark/feature_mos/src/mosaic/Log.h 5549new file mode 100644 5550index 00000000..2adfeda9 5551--- /dev/null 5552+++ b/benchmark/feature_mos/src/mosaic/Log.h 5553@@ -0,0 +1,24 @@ 5554+/* 5555+ * Copyright (C) 2011 The Android Open Source Project 5556+ * 5557+ * Licensed under the Apache License, Version 2.0 (the "License"); 5558+ * you may not use this file except in compliance with the License. 5559+ * You may obtain a copy of the License at 5560+ * 5561+ * http://www.apache.org/licenses/LICENSE-2.0 5562+ * 5563+ * Unless required by applicable law or agreed to in writing, software 5564+ * distributed under the License is distributed on an "AS IS" BASIS, 5565+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5566+ * See the License for the specific language governing permissions and 5567+ * limitations under the License. 5568+ */ 5569+#ifndef LOG_H_ 5570+#define LOG_H_ 5571+ 5572+#include <android/log.h> 5573+#define LOGV(...) __android_log_print(ANDROID_LOG_SILENT, LOG_TAG, __VA_ARGS__) 5574+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 5575+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 5576+ 5577+#endif 5578diff --git a/benchmark/feature_mos/src/mosaic/MatrixUtils.h b/benchmark/feature_mos/src/mosaic/MatrixUtils.h 5579new file mode 100644 5580index 00000000..a0b84d81 5581--- /dev/null 5582+++ b/benchmark/feature_mos/src/mosaic/MatrixUtils.h 5583@@ -0,0 +1,141 @@ 5584+/* 5585+ * Copyright (C) 2011 The Android Open Source Project 5586+ * 5587+ * Licensed under the Apache License, Version 2.0 (the "License"); 5588+ * you may not use this file except in compliance with the License. 5589+ * You may obtain a copy of the License at 5590+ * 5591+ * http://www.apache.org/licenses/LICENSE-2.0 5592+ * 5593+ * Unless required by applicable law or agreed to in writing, software 5594+ * distributed under the License is distributed on an "AS IS" BASIS, 5595+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5596+ * See the License for the specific language governing permissions and 5597+ * limitations under the License. 5598+ */ 5599+ 5600+/////////////////////////////////////////////////// 5601+// Matrixutils.h 5602+// $Id: MatrixUtils.h,v 1.5 2011/05/16 15:33:06 mbansal Exp $ 5603+ 5604+ 5605+#ifndef MATRIX_UTILS_H 5606+#define MATRIX_UTILS_H 5607+ 5608+/* Simple class for 3x3 matrix, mainly used to convert from 9x1 5609+ * to 3x3 5610+ */ 5611+class Matrix33 { 5612+public: 5613+ 5614+ /** 5615+ * Empty constructor 5616+ */ 5617+ Matrix33() { 5618+ initialize(); 5619+ } 5620+ 5621+ /** 5622+ * Constructor with identity initialization 5623+ * Arguments: 5624+ * identity: Specifies wether to initialize matrix to 5625+ * identity or zeros 5626+ */ 5627+ Matrix33(bool identity) { 5628+ initialize(identity); 5629+ } 5630+ 5631+ /** 5632+ * Initialize to identity matrix 5633+ */ 5634+ void initialize(bool identity = false) { 5635+ mat[0][1] = mat[0][2] = mat[1][0] = mat[1][2] = mat[2][0] = mat[2][1] = 0.0; 5636+ if (identity) { 5637+ mat[0][0] = mat[1][1] = mat[2][2] = 1.0; 5638+ } else { 5639+ mat[0][0] = mat[1][1] = mat[2][2] = 0.0; 5640+ } 5641+ } 5642+ 5643+ /** 5644+ * Conver ta 9x1 matrix to a 3x3 matrix 5645+ */ 5646+ static void convert9to33(double out[3][3], double in[9]) { 5647+ out[0][0] = in[0]; 5648+ out[0][1] = in[1]; 5649+ out[0][2] = in[2]; 5650+ 5651+ out[1][0] = in[3]; 5652+ out[1][1] = in[4]; 5653+ out[1][2] = in[5]; 5654+ 5655+ out[2][0] = in[6]; 5656+ out[2][1] = in[7]; 5657+ out[2][2] = in[8]; 5658+ 5659+ } 5660+ 5661+ /* Matrix data */ 5662+ double mat[3][3]; 5663+ 5664+}; 5665+ 5666+/* Simple class for 9x1 matrix, mainly used to convert from 3x3 5667+ * to 9x1 5668+ */ 5669+class Matrix9 { 5670+public: 5671+ 5672+ /** 5673+ * Empty constructor 5674+ */ 5675+ Matrix9() { 5676+ initialize(); 5677+ } 5678+ 5679+ /** 5680+ * Constructor with identity initialization 5681+ * Arguments: 5682+ * identity: Specifies wether to initialize matrix to 5683+ * identity or zeros 5684+ */ 5685+ Matrix9(bool identity) { 5686+ initialize(identity); 5687+ } 5688+ 5689+ /** 5690+ * Initialize to identity matrix 5691+ */ 5692+ void initialize(bool identity = false) { 5693+ mat[1] = mat[2] = mat[3] = mat[5] = mat[6] = mat[7] = 0.0; 5694+ if (identity) { 5695+ mat[0] = mat[4] = mat[8] = 1.0; 5696+ } else { 5697+ mat[0] = mat[4] = mat[8] = 0.0; 5698+ } 5699+ } 5700+ 5701+ /** 5702+ * Conver ta 3x3 matrix to a 9x1 matrix 5703+ */ 5704+ static void convert33to9(double out[9], double in[3][3]) { 5705+ out[0] = in[0][0]; 5706+ out[1] = in[0][1]; 5707+ out[2] = in[0][2]; 5708+ 5709+ out[3] = in[1][0]; 5710+ out[4] = in[1][1]; 5711+ out[5] = in[1][2]; 5712+ 5713+ out[6] = in[2][0]; 5714+ out[7] = in[2][1]; 5715+ out[8] = in[2][2]; 5716+ 5717+ } 5718+ 5719+ /* Matrix data */ 5720+ double mat[9]; 5721+ 5722+}; 5723+ 5724+#endif 5725diff --git a/benchmark/feature_mos/src/mosaic/Mosaic.cpp b/benchmark/feature_mos/src/mosaic/Mosaic.cpp 5726new file mode 100644 5727index 00000000..4abc6f68 5728--- /dev/null 5729+++ b/benchmark/feature_mos/src/mosaic/Mosaic.cpp 5730@@ -0,0 +1,255 @@ 5731+/* 5732+ * Copyright (C) 2011 The Android Open Source Project 5733+ * 5734+ * Licensed under the Apache License, Version 2.0 (the "License"); 5735+ * you may not use this file except in compliance with the License. 5736+ * You may obtain a copy of the License at 5737+ * 5738+ * http://www.apache.org/licenses/LICENSE-2.0 5739+ * 5740+ * Unless required by applicable law or agreed to in writing, software 5741+ * distributed under the License is distributed on an "AS IS" BASIS, 5742+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5743+ * See the License for the specific language governing permissions and 5744+ * limitations under the License. 5745+ */ 5746+ 5747+/////////////////////////////////////////////////// 5748+// Mosaic.pp 5749+// S.O. # : 5750+// Author(s): zkira 5751+// $Id: Mosaic.cpp,v 1.20 2011/06/24 04:22:14 mbansal Exp $ 5752+ 5753+#include <stdio.h> 5754+#include <string.h> 5755+ 5756+#include "Mosaic.h" 5757+#include "trsMatrix.h" 5758+ 5759+Mosaic::Mosaic() 5760+{ 5761+ initialized = false; 5762+ imageMosaicYVU = NULL; 5763+ frames_size = 0; 5764+ max_frames = 200; 5765+} 5766+ 5767+Mosaic::~Mosaic() 5768+{ 5769+ for (int i = 0; i < frames_size; i++) 5770+ { 5771+ if (frames[i]) 5772+ delete frames[i]; 5773+ } 5774+ delete frames; 5775+ delete rframes; 5776+ 5777+ for (int j = 0; j < owned_size; j++) 5778+ delete owned_frames[j]; 5779+ delete owned_frames; 5780+ 5781+ if (aligner != NULL) 5782+ delete aligner; 5783+ if (blender != NULL) 5784+ delete blender; 5785+} 5786+ 5787+int Mosaic::initialize(int blendingType, int stripType, int width, int height, int nframes, bool quarter_res, float thresh_still) 5788+{ 5789+ this->blendingType = blendingType; 5790+ 5791+ // TODO: Review this logic if enabling FULL or PAN mode 5792+ if (blendingType == Blend::BLEND_TYPE_FULL || 5793+ blendingType == Blend::BLEND_TYPE_PAN) 5794+ { 5795+ stripType = Blend::STRIP_TYPE_THIN; 5796+ } 5797+ 5798+ this->stripType = stripType; 5799+ this->width = width; 5800+ this->height = height; 5801+ 5802+ 5803+ mosaicWidth = mosaicHeight = 0; 5804+ imageMosaicYVU = NULL; 5805+ 5806+ frames = new MosaicFrame *[max_frames]; 5807+ rframes = new MosaicFrame *[max_frames]; 5808+ 5809+ if(nframes>-1) 5810+ { 5811+ for(int i=0; i<nframes; i++) 5812+ { 5813+ frames[i] = new MosaicFrame(this->width,this->height,false); // Do no allocate memory for YUV data 5814+ } 5815+ } 5816+ else 5817+ { 5818+ for(int i=0; i<max_frames; i++) 5819+ { 5820+ frames[i] = NULL; 5821+ } 5822+ } 5823+ 5824+ owned_frames = new ImageType[max_frames]; 5825+ owned_size = 0; 5826+ 5827+ aligner = new Align(); 5828+ aligner->initialize(width, height,quarter_res,thresh_still); 5829+ 5830+ if (blendingType == Blend::BLEND_TYPE_FULL || 5831+ blendingType == Blend::BLEND_TYPE_PAN || 5832+ blendingType == Blend::BLEND_TYPE_CYLPAN || 5833+ blendingType == Blend::BLEND_TYPE_HORZ) { 5834+ blender = new Blend(); 5835+ blender->initialize(blendingType, stripType, width, height); 5836+ } else { 5837+ blender = NULL; 5838+ return MOSAIC_RET_ERROR; 5839+ } 5840+ 5841+ initialized = true; 5842+ 5843+ return MOSAIC_RET_OK; 5844+} 5845+ 5846+int Mosaic::addFrameRGB(ImageType imageRGB) 5847+{ 5848+ ImageType imageYVU; 5849+ // Convert to YVU24 which is used by blending 5850+ imageYVU = ImageUtils::allocateImage(this->width, this->height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS); 5851+ ImageUtils::rgb2yvu(imageYVU, imageRGB, width, height); 5852+ 5853+ int existing_frames_size = frames_size; 5854+ int ret = addFrame(imageYVU); 5855+ 5856+ if (frames_size > existing_frames_size) 5857+ owned_frames[owned_size++] = imageYVU; 5858+ else 5859+ ImageUtils::freeImage(imageYVU); 5860+ 5861+ return ret; 5862+} 5863+ 5864+int Mosaic::addFrame(ImageType imageYVU) 5865+{ 5866+ if(frames[frames_size]==NULL) 5867+ frames[frames_size] = new MosaicFrame(this->width,this->height,false); 5868+ 5869+ MosaicFrame *frame = frames[frames_size]; 5870+ 5871+ frame->image = imageYVU; 5872+ 5873+ // Add frame to aligner 5874+ int ret = MOSAIC_RET_ERROR; 5875+ if (aligner != NULL) 5876+ { 5877+ // Note aligner takes in RGB images 5878+ int align_flag = Align::ALIGN_RET_OK; 5879+ align_flag = aligner->addFrame(frame->image); 5880+ aligner->getLastTRS(frame->trs); 5881+ 5882+ if (frames_size >= max_frames) 5883+ { 5884+ return MOSAIC_RET_ERROR; 5885+ } 5886+ 5887+ switch (align_flag) 5888+ { 5889+ case Align::ALIGN_RET_OK: 5890+ frames_size++; 5891+ ret = MOSAIC_RET_OK; 5892+ break; 5893+ case Align::ALIGN_RET_FEW_INLIERS: 5894+ frames_size++; 5895+ ret = MOSAIC_RET_FEW_INLIERS; 5896+ break; 5897+ case Align::ALIGN_RET_LOW_TEXTURE: 5898+ ret = MOSAIC_RET_LOW_TEXTURE; 5899+ break; 5900+ case Align::ALIGN_RET_ERROR: 5901+ ret = MOSAIC_RET_ERROR; 5902+ break; 5903+ default: 5904+ break; 5905+ } 5906+ } 5907+ 5908+ return ret; 5909+} 5910+ 5911+ 5912+int Mosaic::createMosaic(float &progress, bool &cancelComputation) 5913+{ 5914+ if (frames_size <= 0) 5915+ { 5916+ // Haven't accepted any frame in aligner. No need to do blending. 5917+ progress = TIME_PERCENT_ALIGN + TIME_PERCENT_BLEND 5918+ + TIME_PERCENT_FINAL; 5919+ return MOSAIC_RET_OK; 5920+ } 5921+ 5922+ if (blendingType == Blend::BLEND_TYPE_PAN) 5923+ { 5924+ 5925+ balanceRotations(); 5926+ 5927+ } 5928+ 5929+ int ret = Blend::BLEND_RET_ERROR; 5930+ 5931+ // Blend the mosaic (alignment has already been done) 5932+ if (blender != NULL) 5933+ { 5934+ ret = blender->runBlend((MosaicFrame **) frames, (MosaicFrame **) rframes, 5935+ frames_size, imageMosaicYVU, 5936+ mosaicWidth, mosaicHeight, progress, cancelComputation); 5937+ } 5938+ 5939+ switch(ret) 5940+ { 5941+ case Blend::BLEND_RET_ERROR: 5942+ case Blend::BLEND_RET_ERROR_MEMORY: 5943+ ret = MOSAIC_RET_ERROR; 5944+ break; 5945+ case Blend::BLEND_RET_CANCELLED: 5946+ ret = MOSAIC_RET_CANCELLED; 5947+ break; 5948+ case Blend::BLEND_RET_OK: 5949+ ret = MOSAIC_RET_OK; 5950+ } 5951+ return ret; 5952+} 5953+ 5954+ImageType Mosaic::getMosaic(int &width, int &height) 5955+{ 5956+ width = mosaicWidth; 5957+ height = mosaicHeight; 5958+ 5959+ return imageMosaicYVU; 5960+} 5961+ 5962+ 5963+ 5964+int Mosaic::balanceRotations() 5965+{ 5966+ // Normalize to the mean angle of rotation (Smiley face) 5967+ double sineAngle = 0.0; 5968+ 5969+ for (int i = 0; i < frames_size; i++) sineAngle += frames[i]->trs[0][1]; 5970+ sineAngle /= frames_size; 5971+ // Calculate the cosineAngle (1 - sineAngle*sineAngle) = cosineAngle*cosineAngle 5972+ double cosineAngle = sqrt(1.0 - sineAngle*sineAngle); 5973+ double m[3][3] = { 5974+ { cosineAngle, -sineAngle, 0 }, 5975+ { sineAngle, cosineAngle, 0}, 5976+ { 0, 0, 1}}; 5977+ double tmp[3][3]; 5978+ 5979+ for (int i = 0; i < frames_size; i++) { 5980+ memcpy(tmp, frames[i]->trs, sizeof(tmp)); 5981+ mult33d(frames[i]->trs, m, tmp); 5982+ } 5983+ 5984+ return MOSAIC_RET_OK; 5985+} 5986diff --git a/benchmark/feature_mos/src/mosaic/Mosaic.h b/benchmark/feature_mos/src/mosaic/Mosaic.h 5987new file mode 100644 5988index 00000000..9dea6642 5989--- /dev/null 5990+++ b/benchmark/feature_mos/src/mosaic/Mosaic.h 5991@@ -0,0 +1,226 @@ 5992+/* 5993+ * Copyright (C) 2011 The Android Open Source Project 5994+ * 5995+ * Licensed under the Apache License, Version 2.0 (the "License"); 5996+ * you may not use this file except in compliance with the License. 5997+ * You may obtain a copy of the License at 5998+ * 5999+ * http://www.apache.org/licenses/LICENSE-2.0 6000+ * 6001+ * Unless required by applicable law or agreed to in writing, software 6002+ * distributed under the License is distributed on an "AS IS" BASIS, 6003+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6004+ * See the License for the specific language governing permissions and 6005+ * limitations under the License. 6006+ */ 6007+ 6008+/////////////////////////////////////////////////// 6009+// Mosaic.h 6010+// S.O. # : 6011+// Author(s): zkira 6012+// $Id: Mosaic.h,v 1.16 2011/06/24 04:22:14 mbansal Exp $ 6013+ 6014+#ifndef MOSAIC_H 6015+#define MOSAIC_H 6016+ 6017+#include "ImageUtils.h" 6018+#include "AlignFeatures.h" 6019+#include "Blend.h" 6020+#include "MosaicTypes.h" 6021+ 6022+/*! \mainpage Mosaic 6023+ 6024+ \section intro Introduction 6025+ The class Mosaic provides a simple interface to the panoramic mosaicing algorithm. The class allows passing in individual image frames to be stitched together, computes the alignment transformation between them, and then stitches and blends them together into a single panoramic output which can then be accessed as a single image. \ 6026+ 6027+ \section usage Usage 6028+ The class methods need to be called as outlined in the sample application which is created from the mosaic_main.cpp file in the directory src/mosaic/. A brief snapshot of the flow is given below: 6029+ 6030+ \code 6031+ Mosaic mosaic; 6032+ // Define blending types to use, and the frame dimensions 6033+ int blendingType = Blend::BLEND_TYPE_CYLPAN; 6034+ int stripType = Blend::STRIP_TYPE_THIN; 6035+ int width = 640; 6036+ int height = 480; 6037+ 6038+ while (<image frames are available>) 6039+ { 6040+ // Check for initialization and if not, initialize 6041+ if (!mosaic.isInitialized()) 6042+ { 6043+ // Initialize mosaic processing 6044+ mosaic.initialize(blendingType, stripType, width, height, -1, false, 5.0f); 6045+ } 6046+ 6047+ // Add to list of frames 6048+ mosaic.addFrameRGB(imageRGB); 6049+ 6050+ // Free image 6051+ ImageUtils::freeImage(imageRGB); 6052+ } 6053+ 6054+ // Create the mosaic 6055+ ret = mosaic.createMosaic(); 6056+ 6057+ // Get back the result 6058+ resultYVU = mosaic.getMosaic(mosaicWidth, mosaicHeight); 6059+ 6060+ printf("Got mosaic of size %d,%d\n", mosaicWidth, mosaicHeight); 6061+ 6062+ \endcode 6063+*/ 6064+ 6065+/*! 6066+ * Main class that creates a mosaic by creating an aligner and blender. 6067+ */ 6068+class Mosaic 6069+{ 6070+ 6071+public: 6072+ 6073+ Mosaic(); 6074+ ~Mosaic(); 6075+ 6076+ /*! 6077+ * Creates the aligner and blender and initializes state. 6078+ * \param blendingType Type of blending to perform 6079+ * \param stripType Type of strip to use. 0: thin, 1: wide. stripType 6080+ * is effective only when blendingType is CylPan or 6081+ * Horz. Otherwise, it is set to thin irrespective of the input. 6082+ * \param width Width of input images (note: all images must be same size) 6083+ * \param height Height of input images (note: all images must be same size) 6084+ * \param nframes Number of frames to pre-allocate; default value -1 will allocate each frame as it comes 6085+ * \param quarter_res Whether to compute alignment at quarter the input resolution (default = false) 6086+ * \param thresh_still Minimum number of pixels of translation detected between the new frame and the last frame before this frame is added to be mosaiced. For the low-res processing at 320x180 resolution input, we set this to 5 pixels. To reject no frames, set this to 0.0 (default value). 6087+ * \return Return code signifying success or failure. 6088+ */ 6089+ int initialize(int blendingType, int stripType, int width, int height, int nframes = -1, bool quarter_res = false, float thresh_still = 0.0); 6090+ 6091+ /*! 6092+ * Adds a YVU frame to the mosaic. 6093+ * \param imageYVU Pointer to a YVU image. 6094+ * \return Return code signifying success or failure. 6095+ */ 6096+ int addFrame(ImageType imageYVU); 6097+ 6098+ /*! 6099+ * Adds a RGB frame to the mosaic. 6100+ * \param imageRGB Pointer to a RGB image. 6101+ * \return Return code signifying success or failure. 6102+ */ 6103+ int addFrameRGB(ImageType imageRGB); 6104+ 6105+ /*! 6106+ * After adding all frames, call this function to perform the final blending. 6107+ * \param progress Variable to set the current progress in. 6108+ * \return Return code signifying success or failure. 6109+ */ 6110+ int createMosaic(float &progress, bool &cancelComputation); 6111+ 6112+ /*! 6113+ * Obtains the resulting mosaic and its dimensions. 6114+ * \param width Width of the resulting mosaic (returned) 6115+ * \param height Height of the resulting mosaic (returned) 6116+ * \return Pointer to image. 6117+ */ 6118+ ImageType getMosaic(int &width, int &height); 6119+ 6120+ /*! 6121+ * Provides access to the internal alignment object pointer. 6122+ * \return Pointer to the aligner object. 6123+ */ 6124+ Align* getAligner() { return aligner; } 6125+ 6126+ /*! 6127+ * Obtain initialization state. 6128+ * 6129+ * return Returns true if initialized, false otherwise. 6130+ */ 6131+ bool isInitialized() { return initialized; } 6132+ 6133+ 6134+ /*! 6135+ * Return codes for mosaic. 6136+ */ 6137+ static const int MOSAIC_RET_OK = 1; 6138+ static const int MOSAIC_RET_ERROR = -1; 6139+ static const int MOSAIC_RET_CANCELLED = -2; 6140+ static const int MOSAIC_RET_LOW_TEXTURE = -3; 6141+ static const int MOSAIC_RET_FEW_INLIERS = 2; 6142+ 6143+protected: 6144+ 6145+ /** 6146+ * Size of image frames making up mosaic 6147+ */ 6148+ int width, height; 6149+ 6150+ /** 6151+ * Size of actual mosaic 6152+ */ 6153+ int mosaicWidth, mosaicHeight; 6154+ 6155+ /** 6156+ * Bounding box to crop the mosaic when the gray border is not desired. 6157+ */ 6158+ MosaicRect mosaicCroppingRect; 6159+ 6160+ ImageType imageMosaicYVU; 6161+ 6162+ /** 6163+ * Collection of frames that will make up mosaic. 6164+ */ 6165+ MosaicFrame **frames; 6166+ 6167+ /** 6168+ * Subset of frames that are considered as relevant. 6169+ */ 6170+ MosaicFrame **rframes; 6171+ 6172+ int frames_size; 6173+ int max_frames; 6174+ 6175+ /** 6176+ * Implicitly created frames, should be freed by Mosaic. 6177+ */ 6178+ ImageType *owned_frames; 6179+ int owned_size; 6180+ 6181+ /** 6182+ * Initialization state. 6183+ */ 6184+ bool initialized; 6185+ 6186+ /** 6187+ * Type of blending to perform. 6188+ */ 6189+ int blendingType; 6190+ 6191+ /** 6192+ * Type of strip to use. 0: thin (default), 1: wide 6193+ */ 6194+ int stripType; 6195+ 6196+ /** 6197+ * Pointer to aligner. 6198+ */ 6199+ Align *aligner; 6200+ 6201+ /** 6202+ * Pointer to blender. 6203+ */ 6204+ Blend *blender; 6205+ 6206+ /** 6207+ * Modifies TRS matrices so that rotations are balanced 6208+ * about center of mosaic 6209+ * 6210+ * Side effect: TRS matrices of all mosaic frames 6211+ * are modified 6212+ */ 6213+ int balanceRotations(); 6214+ 6215+}; 6216+ 6217+#endif 6218diff --git a/benchmark/feature_mos/src/mosaic/MosaicTypes.h b/benchmark/feature_mos/src/mosaic/MosaicTypes.h 6219new file mode 100644 6220index 00000000..395ec458 6221--- /dev/null 6222+++ b/benchmark/feature_mos/src/mosaic/MosaicTypes.h 6223@@ -0,0 +1,154 @@ 6224+/* 6225+ * Copyright (C) 2011 The Android Open Source Project 6226+ * 6227+ * Licensed under the Apache License, Version 2.0 (the "License"); 6228+ * you may not use this file except in compliance with the License. 6229+ * You may obtain a copy of the License at 6230+ * 6231+ * http://www.apache.org/licenses/LICENSE-2.0 6232+ * 6233+ * Unless required by applicable law or agreed to in writing, software 6234+ * distributed under the License is distributed on an "AS IS" BASIS, 6235+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6236+ * See the License for the specific language governing permissions and 6237+ * limitations under the License. 6238+ */ 6239+ 6240+/////////////////////////////////////////////////// 6241+// MosaicTypes.h 6242+// S.O. # : 6243+// Author(s): zkira 6244+// $Id: MosaicTypes.h,v 1.15 2011/06/17 13:35:48 mbansal Exp $ 6245+ 6246+ 6247+#ifndef MOSAIC_TYPES_H 6248+#define MOSAIC_TYPES_H 6249+ 6250+#include "ImageUtils.h" 6251+ 6252+/** 6253+ * Definition of rectangle in a mosaic. 6254+ */ 6255+class MosaicRect 6256+{ 6257+ public: 6258+ MosaicRect() 6259+ { 6260+ left = right = top = bottom = 0.0; 6261+ } 6262+ 6263+ inline int Width() 6264+ { 6265+ return right - left; 6266+ } 6267+ 6268+ inline int Height() 6269+ { 6270+ return bottom - top; 6271+ } 6272+ 6273+ /** 6274+ * Bounds of the rectangle 6275+ */ 6276+ int left, right, top, bottom; 6277+}; 6278+ 6279+class BlendRect 6280+{ 6281+ public: 6282+ double lft, rgt, top, bot; 6283+}; 6284+ 6285+/** 6286+ * A frame making up the mosaic. 6287+ * Note: Currently assumes a YVU image 6288+ * containing separate Y,V, and U planes 6289+ * in contiguous memory (in that order). 6290+ */ 6291+class MosaicFrame { 6292+public: 6293+ ImageType image; 6294+ double trs[3][3]; 6295+ int width, height; 6296+ BlendRect brect; // This frame warped to the Mosaic coordinate system 6297+ BlendRect vcrect; // brect clipped using the voronoi neighbors 6298+ bool internal_allocation; 6299+ 6300+ MosaicFrame() { }; 6301+ MosaicFrame(int _width, int _height, bool allocate=true) 6302+ { 6303+ width = _width; 6304+ height = _height; 6305+ internal_allocation = allocate; 6306+ if(internal_allocation) 6307+ image = ImageUtils::allocateImage(width, height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS); 6308+ } 6309+ 6310+ 6311+ ~MosaicFrame() 6312+ { 6313+ if(internal_allocation) 6314+ if (image) 6315+ free(image); 6316+ } 6317+ 6318+ /** 6319+ * Get the V plane of the image. 6320+ */ 6321+ inline ImageType getV() 6322+ { 6323+ return (image + (width*height)); 6324+ } 6325+ 6326+ /** 6327+ * Get the U plane of the image. 6328+ */ 6329+ inline ImageType getU() 6330+ { 6331+ return (image + (width*height*2)); 6332+ } 6333+ 6334+ /** 6335+ * Get a pixel from the V plane of the image. 6336+ */ 6337+ inline int getV(int y, int x) 6338+ { 6339+ ImageType U = image + (width*height); 6340+ return U[y*width+x]; 6341+ } 6342+ 6343+ /** 6344+ * Get a pixel from the U plane of the image. 6345+ */ 6346+ inline int getU(int y, int x) 6347+ { 6348+ ImageType U = image + (width*height*2); 6349+ return U[y*width+x]; 6350+ } 6351+ 6352+}; 6353+ 6354+/** 6355+ * Structure for describing a warp. 6356+ */ 6357+typedef struct { 6358+ int horizontal; 6359+ double theta; 6360+ double x; 6361+ double y; 6362+ double width; 6363+ double radius; 6364+ double direction; 6365+ double correction; 6366+ int blendRange; 6367+ int blendRangeUV; 6368+ int nlevs; 6369+ int nlevsC; 6370+ int blendingType; 6371+ int stripType; 6372+ // Add an overlap to prevent a gap between pictures due to roundoffs 6373+ double roundoffOverlap;// 1.5 6374+ 6375+} BlendParams; 6376+ 6377+#endif 6378diff --git a/benchmark/feature_mos/src/mosaic/Pyramid.cpp b/benchmark/feature_mos/src/mosaic/Pyramid.cpp 6379new file mode 100644 6380index 00000000..b022d73d 6381--- /dev/null 6382+++ b/benchmark/feature_mos/src/mosaic/Pyramid.cpp 6383@@ -0,0 +1,270 @@ 6384+/* 6385+ * Copyright (C) 2011 The Android Open Source Project 6386+ * 6387+ * Licensed under the Apache License, Version 2.0 (the "License"); 6388+ * you may not use this file except in compliance with the License. 6389+ * You may obtain a copy of the License at 6390+ * 6391+ * http://www.apache.org/licenses/LICENSE-2.0 6392+ * 6393+ * Unless required by applicable law or agreed to in writing, software 6394+ * distributed under the License is distributed on an "AS IS" BASIS, 6395+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6396+ * See the License for the specific language governing permissions and 6397+ * limitations under the License. 6398+ */ 6399+ 6400+// pyramid.cpp 6401+ 6402+#include <stdio.h> 6403+#include <string.h> 6404+ 6405+#include "Pyramid.h" 6406+ 6407+// We allocate the entire pyramid into one contiguous storage. This makes 6408+// cleanup easier than fragmented stuff. In addition, we added a "pitch" 6409+// field, so pointer manipulation is much simpler when it would be faster. 6410+PyramidShort *PyramidShort::allocatePyramidPacked(real levels, 6411+ real width, real height, real border) 6412+{ 6413+ real border2 = (real) (border << 1); 6414+ int lines, size = calcStorage(width, height, border2, levels, &lines); 6415+ 6416+ PyramidShort *img = (PyramidShort *) calloc(sizeof(PyramidShort) * levels 6417+ + sizeof(short *) * lines + 6418+ + sizeof(short) * size, 1); 6419+ 6420+ if (img) { 6421+ PyramidShort *curr, *last; 6422+ ImageTypeShort *y = (ImageTypeShort *) &img[levels]; 6423+ ImageTypeShort position = (ImageTypeShort) &y[lines]; 6424+ for (last = (curr = img) + levels; curr < last; curr++) { 6425+ curr->width = width; 6426+ curr->height = height; 6427+ curr->border = border; 6428+ curr->pitch = (real) (width + border2); 6429+ curr->ptr = y + border; 6430+ 6431+ // Assign row pointers 6432+ for (int j = height + border2; j--; y++, position += curr->pitch) { 6433+ *y = position + border; 6434+ } 6435+ 6436+ width >>= 1; 6437+ height >>= 1; 6438+ } 6439+ } 6440+ 6441+ return img; 6442+} 6443+ 6444+// Allocate an image of type short 6445+PyramidShort *PyramidShort::allocateImage(real width, real height, real border) 6446+{ 6447+ real border2 = (real) (border << 1); 6448+ PyramidShort *img = (PyramidShort *) 6449+ calloc(sizeof(PyramidShort) + sizeof(short *) * (height + border2) + 6450+ sizeof(short) * (width + border2) * (height + border2), 1); 6451+ 6452+ if (img) { 6453+ short **y = (short **) &img[1]; 6454+ short *position = (short *) &y[height + border2]; 6455+ img->width = width; 6456+ img->height = height; 6457+ img->border = border; 6458+ img->pitch = (real) (width + border2); 6459+ img->ptr = y + border; 6460+ position += border; // Move position down to origin of real image 6461+ 6462+ // Assign row pointers 6463+ for (int j = height + border2; j--; y++, position += img->pitch) { 6464+ *y = position; 6465+ } 6466+ } 6467+ 6468+ return img; 6469+} 6470+ 6471+// Free the images 6472+void PyramidShort::freeImage(PyramidShort *image) 6473+{ 6474+ if (image != NULL) 6475+ free(image); 6476+} 6477+ 6478+// Calculate amount of storage needed taking into account the borders, etc. 6479+unsigned int PyramidShort::calcStorage(real width, real height, real border2, int levels, int *lines) 6480+{ 6481+ int size; 6482+ 6483+ *lines = size = 0; 6484+ 6485+ while(levels--) { 6486+ size += (width + border2) * (height + border2); 6487+ *lines += height + border2; 6488+ width >>= 1; 6489+ height >>= 1; 6490+ } 6491+ 6492+ return size; 6493+} 6494+ 6495+void PyramidShort::BorderSpread(PyramidShort *pyr, int left, int right, 6496+ int top, int bot) 6497+{ 6498+ int off, off2, height, h, w; 6499+ ImageTypeShort base; 6500+ 6501+ if (left || right) { 6502+ off = pyr->border - left; 6503+ off2 = pyr->width + off + pyr->border - right - 1; 6504+ h = pyr->border - top; 6505+ height = pyr->height + (h << 1); 6506+ base = pyr->ptr[-h] - off; 6507+ 6508+ // spread in X 6509+ for (h = height; h--; base += pyr->pitch) { 6510+ for (w = left; w--;) 6511+ base[-1 - w] = base[0]; 6512+ for (w = right; w--;) 6513+ base[off2 + w + 1] = base[off2]; 6514+ } 6515+ } 6516+ 6517+ if (top || bot) { 6518+ // spread in Y 6519+ base = pyr->ptr[top - pyr->border] - pyr->border; 6520+ for (h = top; h--; base -= pyr->pitch) { 6521+ memcpy(base - pyr->pitch, base, pyr->pitch * sizeof(short)); 6522+ } 6523+ 6524+ base = pyr->ptr[pyr->height + pyr->border - bot] - pyr->border; 6525+ for (h = bot; h--; base += pyr->pitch) { 6526+ memcpy(base, base - pyr->pitch, pyr->pitch * sizeof(short)); 6527+ } 6528+ } 6529+} 6530+ 6531+void PyramidShort::BorderExpandOdd(PyramidShort *in, PyramidShort *out, PyramidShort *scr, 6532+ int mode) 6533+{ 6534+ int i,j; 6535+ int off = in->border / 2; 6536+ 6537+ // Vertical Filter 6538+ for (j = -off; j < in->height + off; j++) { 6539+ int j2 = j * 2; 6540+ int limit = scr->width + scr->border; 6541+ for (i = -scr->border; i < limit; i++) { 6542+ int t1 = in->ptr[j][i]; 6543+ int t2 = in->ptr[j+1][i]; 6544+ scr->ptr[j2][i] = (short) 6545+ ((6 * t1 + (in->ptr[j-1][i] + t2) + 4) >> 3); 6546+ scr->ptr[j2+1][i] = (short)((t1 + t2 + 1) >> 1); 6547+ } 6548+ } 6549+ 6550+ BorderSpread(scr, 0, 0, 3, 3); 6551+ 6552+ // Horizontal Filter 6553+ int limit = out->height + out->border; 6554+ for (j = -out->border; j < limit; j++) { 6555+ for (i = -off; i < scr->width + off; i++) { 6556+ int i2 = i * 2; 6557+ int t1 = scr->ptr[j][i]; 6558+ int t2 = scr->ptr[j][i+1]; 6559+ out->ptr[j][i2] = (short) (out->ptr[j][i2] + 6560+ (mode * ((6 * t1 + 6561+ scr->ptr[j][i-1] + t2 + 4) >> 3))); 6562+ out->ptr[j][i2+1] = (short) (out->ptr[j][i2+1] + 6563+ (mode * ((t1 + t2 + 1) >> 1))); 6564+ } 6565+ } 6566+ 6567+} 6568+ 6569+int PyramidShort::BorderExpand(PyramidShort *pyr, int nlev, int mode) 6570+{ 6571+ PyramidShort *tpyr = pyr + nlev - 1; 6572+ PyramidShort *scr = allocateImage(pyr[1].width, pyr[0].height, pyr->border); 6573+ if (scr == NULL) return 0; 6574+ 6575+ if (mode > 0) { 6576+ // Expand and add (reconstruct from Laplacian) 6577+ for (; tpyr > pyr; tpyr--) { 6578+ scr->width = tpyr[0].width; 6579+ scr->height = tpyr[-1].height; 6580+ BorderExpandOdd(tpyr, tpyr - 1, scr, 1); 6581+ } 6582+ } 6583+ else if (mode < 0) { 6584+ // Expand and subtract (build Laplacian) 6585+ while ((pyr++) < tpyr) { 6586+ scr->width = pyr[0].width; 6587+ scr->height = pyr[-1].height; 6588+ BorderExpandOdd(pyr, pyr - 1, scr, -1); 6589+ } 6590+ } 6591+ 6592+ freeImage(scr); 6593+ return 1; 6594+} 6595+ 6596+void PyramidShort::BorderReduceOdd(PyramidShort *in, PyramidShort *out, PyramidShort *scr) 6597+{ 6598+ ImageTypeShortBase *s, *ns, *ls, *p, *np; 6599+ 6600+ int off = scr->border - 2; 6601+ s = scr->ptr[-scr->border] - (off >> 1); 6602+ ns = s + scr->pitch; 6603+ ls = scr->ptr[scr->height + scr->border - 1] + scr->pitch - (off >> 1); 6604+ int width = scr->width + scr->border; 6605+ p = in->ptr[-scr->border] - off; 6606+ np = p + in->pitch; 6607+ 6608+ // treat it as if the whole thing were the image 6609+ for (; s < ls; s = ns, ns += scr->pitch, p = np, np += in->pitch) { 6610+ for (int w = width; w--; s++, p += 2) { 6611+ *s = (short)((((int) p[-2]) + ((int) p[2]) + 8 + // 1 6612+ ((((int) p[-1]) + ((int) p[1])) << 2) + // 4 6613+ ((int) *p) * 6) >> 4); // 6 6614+ } 6615+ } 6616+ 6617+ BorderSpread(scr, 5, 4 + ((in->width ^ 1) & 1), 0, 0); // 6618+ 6619+ s = out->ptr[-(off >> 1)] - out->border; 6620+ ns = s + out->pitch; 6621+ ls = s + out->pitch * (out->height + off); 6622+ p = scr->ptr[-off] - out->border; 6623+ int pitch = scr->pitch; 6624+ int pitch2 = pitch << 1; 6625+ np = p + pitch2; 6626+ for (; s < ls; s = ns, ns += out->pitch, p = np, np += pitch2) { 6627+ for (int w = out->pitch; w--; s++, p++) { 6628+ *s = (short)((((int) p[-pitch2]) + ((int) p[pitch2]) + 8 + // 1 6629+ ((((int) p[-pitch]) + ((int) p[pitch])) << 2) + // 4 6630+ ((int) *p) * 6) >> 4); // 6 6631+ } 6632+ } 6633+ BorderSpread(out, 0, 0, 5, 5); 6634+ 6635+} 6636+ 6637+int PyramidShort::BorderReduce(PyramidShort *pyr, int nlev) 6638+{ 6639+ PyramidShort *scr = allocateImage(pyr[1].width, pyr[0].height, pyr->border); 6640+ if (scr == NULL) 6641+ return 0; 6642+ 6643+ BorderSpread(pyr, pyr->border, pyr->border, pyr->border, pyr->border); 6644+ while (--nlev) { 6645+ BorderReduceOdd(pyr, pyr + 1, scr); 6646+ pyr++; 6647+ scr->width = pyr[1].width; 6648+ scr->height = pyr[0].height; 6649+ } 6650+ 6651+ freeImage(scr); 6652+ return 1; 6653+} 6654diff --git a/benchmark/feature_mos/src/mosaic/Pyramid.h b/benchmark/feature_mos/src/mosaic/Pyramid.h 6655new file mode 100644 6656index 00000000..c5fe9071 6657--- /dev/null 6658+++ b/benchmark/feature_mos/src/mosaic/Pyramid.h 6659@@ -0,0 +1,54 @@ 6660+/* 6661+ * Copyright (C) 2011 The Android Open Source Project 6662+ * 6663+ * Licensed under the Apache License, Version 2.0 (the "License"); 6664+ * you may not use this file except in compliance with the License. 6665+ * You may obtain a copy of the License at 6666+ * 6667+ * http://www.apache.org/licenses/LICENSE-2.0 6668+ * 6669+ * Unless required by applicable law or agreed to in writing, software 6670+ * distributed under the License is distributed on an "AS IS" BASIS, 6671+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6672+ * See the License for the specific language governing permissions and 6673+ * limitations under the License. 6674+ */ 6675+ 6676+// Pyramid.h 6677+ 6678+#ifndef PYRAMID_H 6679+#define PYRAMID_H 6680+ 6681+#include "ImageUtils.h" 6682+ 6683+typedef unsigned short int real; 6684+ 6685+// Structure containing a packed pyramid of type ImageTypeShort. Used for pyramid 6686+// blending, among other things. 6687+ 6688+class PyramidShort 6689+{ 6690+ 6691+public: 6692+ 6693+ ImageTypeShort *ptr; // Pointer containing the image 6694+ real width, height; // Width and height of input images 6695+ real numChannels; // Number of channels in input images 6696+ real border; // border size 6697+ real pitch; // Pitch. Used for moving through image efficiently. 6698+ 6699+ static PyramidShort *allocatePyramidPacked(real width, real height, real levels, real border = 0); 6700+ static PyramidShort *allocateImage(real width, real height, real border); 6701+ static void createPyramid(ImageType image, PyramidShort *pyramid, int last = 3 ); 6702+ static void freeImage(PyramidShort *image); 6703+ 6704+ static unsigned int calcStorage(real width, real height, real border2, int levels, int *lines); 6705+ 6706+ static void BorderSpread(PyramidShort *pyr, int left, int right, int top, int bot); 6707+ static void BorderExpandOdd(PyramidShort *in, PyramidShort *out, PyramidShort *scr, int mode); 6708+ static int BorderExpand(PyramidShort *pyr, int nlev, int mode); 6709+ static int BorderReduce(PyramidShort *pyr, int nlev); 6710+ static void BorderReduceOdd(PyramidShort *in, PyramidShort *out, PyramidShort *scr); 6711+}; 6712+ 6713+#endif 6714diff --git a/benchmark/feature_mos/src/mosaic/trsMatrix.cpp b/benchmark/feature_mos/src/mosaic/trsMatrix.cpp 6715new file mode 100644 6716index 00000000..4c04e6c3 6717--- /dev/null 6718+++ b/benchmark/feature_mos/src/mosaic/trsMatrix.cpp 6719@@ -0,0 +1,93 @@ 6720+/* 6721+ * Copyright (C) 2011 The Android Open Source Project 6722+ * 6723+ * Licensed under the Apache License, Version 2.0 (the "License"); 6724+ * you may not use this file except in compliance with the License. 6725+ * You may obtain a copy of the License at 6726+ * 6727+ * http://www.apache.org/licenses/LICENSE-2.0 6728+ * 6729+ * Unless required by applicable law or agreed to in writing, software 6730+ * distributed under the License is distributed on an "AS IS" BASIS, 6731+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6732+ * See the License for the specific language governing permissions and 6733+ * limitations under the License. 6734+ */ 6735+ 6736+// trsMatrix.cpp 6737+// $Id: trsMatrix.cpp,v 1.9 2011/06/17 13:35:48 mbansal Exp $ 6738+ 6739+#include "stdio.h" 6740+#include <math.h> 6741+#include "trsMatrix.h" 6742+ 6743+void mult33d(double a[3][3], double b[3][3], double c[3][3]) 6744+{ 6745+ a[0][0] = b[0][0]*c[0][0] + b[0][1]*c[1][0] + b[0][2]*c[2][0]; 6746+ a[0][1] = b[0][0]*c[0][1] + b[0][1]*c[1][1] + b[0][2]*c[2][1]; 6747+ a[0][2] = b[0][0]*c[0][2] + b[0][1]*c[1][2] + b[0][2]*c[2][2]; 6748+ a[1][0] = b[1][0]*c[0][0] + b[1][1]*c[1][0] + b[1][2]*c[2][0]; 6749+ a[1][1] = b[1][0]*c[0][1] + b[1][1]*c[1][1] + b[1][2]*c[2][1]; 6750+ a[1][2] = b[1][0]*c[0][2] + b[1][1]*c[1][2] + b[1][2]*c[2][2]; 6751+ a[2][0] = b[2][0]*c[0][0] + b[2][1]*c[1][0] + b[2][2]*c[2][0]; 6752+ a[2][1] = b[2][0]*c[0][1] + b[2][1]*c[1][1] + b[2][2]*c[2][1]; 6753+ a[2][2] = b[2][0]*c[0][2] + b[2][1]*c[1][2] + b[2][2]*c[2][2]; 6754+} 6755+ 6756+ 6757+// normProjMat33d 6758+// m = input matrix 6759+// return: result if successful 6760+int normProjMat33d(double m[3][3]) 6761+{ 6762+ 6763+ if(m[2][2] == 0.0) 6764+ { 6765+ return 0; 6766+} 6767+ 6768+ m[0][0] /= m[2][2]; 6769+ m[0][1] /= m[2][2]; 6770+ m[0][2] /= m[2][2]; 6771+ m[1][0] /= m[2][2]; 6772+ m[1][1] /= m[2][2]; 6773+ m[1][2] /= m[2][2]; 6774+ m[2][0] /= m[2][2]; 6775+ m[2][1] /= m[2][2]; 6776+ m[2][2] = 1.0; 6777+ 6778+ return 1; 6779+} 6780+ 6781+// det33d 6782+// m = input matrix 6783+// returns: determinant 6784+double det33d(const double m[3][3]) 6785+{ 6786+ double result; 6787+ 6788+ result = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); 6789+ result += m[0][1] * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); 6790+ result += m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); 6791+ 6792+ return result; 6793+} 6794+ 6795+// inv33d 6796+// 6797+void inv33d(const double m[3][3], double out[3][3]) 6798+{ 6799+ double det = det33d(m); 6800+ 6801+ out[0][0] = (m[1][1]*m[2][2] - m[1][2]*m[2][1]) / det; 6802+ out[1][0] = (m[1][2]*m[2][0] - m[1][0]*m[2][2]) / det; 6803+ out[2][0] = (m[1][0]*m[2][1] - m[1][1]*m[2][0]) / det; 6804+ 6805+ out[0][1] = (m[0][2]*m[2][1] - m[0][1]*m[2][2]) / det; 6806+ out[1][1] = (m[0][0]*m[2][2] - m[0][2]*m[2][0]) / det; 6807+ out[2][1] = (m[0][1]*m[2][0] - m[0][0]*m[2][1]) / det; 6808+ 6809+ out[0][2] = (m[0][1]*m[1][2] - m[0][2]*m[1][1]) / det; 6810+ out[1][2] = (m[0][2]*m[1][0] - m[0][0]*m[1][2]) / det; 6811+ out[2][2] = (m[0][0]*m[1][1] - m[0][1]*m[1][0]) / det; 6812+} 6813diff --git a/benchmark/feature_mos/src/mosaic/trsMatrix.h b/benchmark/feature_mos/src/mosaic/trsMatrix.h 6814new file mode 100644 6815index 00000000..054cc333 6816--- /dev/null 6817+++ b/benchmark/feature_mos/src/mosaic/trsMatrix.h 6818@@ -0,0 +1,53 @@ 6819+/* 6820+ * Copyright (C) 2011 The Android Open Source Project 6821+ * 6822+ * Licensed under the Apache License, Version 2.0 (the "License"); 6823+ * you may not use this file except in compliance with the License. 6824+ * You may obtain a copy of the License at 6825+ * 6826+ * http://www.apache.org/licenses/LICENSE-2.0 6827+ * 6828+ * Unless required by applicable law or agreed to in writing, software 6829+ * distributed under the License is distributed on an "AS IS" BASIS, 6830+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6831+ * See the License for the specific language governing permissions and 6832+ * limitations under the License. 6833+ */ 6834+ 6835+/////////////////////////////////////////////////// 6836+// trsMatrix.h 6837+// $Id: trsMatrix.h,v 1.8 2011/06/17 13:35:48 mbansal Exp $ 6838+ 6839+#ifndef TRSMATRIX_H_ 6840+#define TRSMATRIX_H_ 6841+ 6842+ 6843+// Calculate the determinant of a matrix 6844+double det33d(const double m[3][3]); 6845+ 6846+// Invert a matrix 6847+void inv33d(const double m[3][3], double out[3][3]); 6848+ 6849+// Multiply a = b * c 6850+void mult33d(double a[3][3], double b[3][3], double c[3][3]); 6851+ 6852+// Normalize matrix so matrix[2][2] is '1' 6853+int normProjMat33d(double m[3][3]); 6854+ 6855+inline double ProjZ(double trs[3][3], double x, double y, double f) 6856+{ 6857+ return ((trs)[2][0]*(x) + (trs)[2][1]*(y) + (trs)[2][2]*(f)); 6858+} 6859+ 6860+inline double ProjX(double trs[3][3], double x, double y, double z, double f) 6861+{ 6862+ return (((trs)[0][0]*(x) + (trs)[0][1]*(y) + (trs)[0][2]*(f)) / (z)); 6863+} 6864+ 6865+inline double ProjY(double trs[3][3], double x, double y, double z, double f) 6866+{ 6867+ return (((trs)[1][0]*(x) + (trs)[1][1]*(y) + (trs)[1][2]*(f)) / (z)); 6868+} 6869+ 6870+ 6871+#endif 6872diff --git a/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.cpp b/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.cpp 6873new file mode 100755 6874index 00000000..a956f23b 6875--- /dev/null 6876+++ b/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.cpp 6877@@ -0,0 +1,98 @@ 6878+#include "FrameBuffer.h" 6879+ 6880+FrameBuffer::FrameBuffer() 6881+{ 6882+ Reset(); 6883+} 6884+ 6885+FrameBuffer::~FrameBuffer() { 6886+} 6887+ 6888+void FrameBuffer::Reset() { 6889+ mFrameBufferName = -1; 6890+ mTextureName = -1; 6891+ mWidth = 0; 6892+ mHeight = 0; 6893+ mFormat = -1; 6894+} 6895+ 6896+bool FrameBuffer::InitializeGLContext() { 6897+ Reset(); 6898+ return CreateBuffers(); 6899+} 6900+ 6901+bool FrameBuffer::Init(int width, int height, GLenum format) { 6902+ if (mFrameBufferName == (GLuint)-1) { 6903+ if (!CreateBuffers()) { 6904+ return false; 6905+ } 6906+ } 6907+ glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferName); 6908+ glBindTexture(GL_TEXTURE_2D, mTextureName); 6909+ 6910+ glTexImage2D(GL_TEXTURE_2D, 6911+ 0, 6912+ format, 6913+ width, 6914+ height, 6915+ 0, 6916+ format, 6917+ GL_UNSIGNED_BYTE, 6918+ NULL); 6919+ if (!checkGlError("bind/teximage")) { 6920+ return false; 6921+ } 6922+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6923+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 6924+ // This is necessary to work with user-generated frame buffers with 6925+ // dimensions that are NOT powers of 2. 6926+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 6927+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 6928+ 6929+ // Attach texture to frame buffer. 6930+ glFramebufferTexture2D(GL_FRAMEBUFFER, 6931+ GL_COLOR_ATTACHMENT0, 6932+ GL_TEXTURE_2D, 6933+ mTextureName, 6934+ 0); 6935+ checkFramebufferStatus("FrameBuffer.cpp"); 6936+ checkGlError("framebuffertexture2d"); 6937+ 6938+ if (!checkGlError("texture setup")) { 6939+ return false; 6940+ } 6941+ mWidth = width; 6942+ mHeight = height; 6943+ mFormat = format; 6944+ glBindFramebuffer(GL_FRAMEBUFFER, 0); 6945+ return true; 6946+} 6947+ 6948+bool FrameBuffer::CreateBuffers() { 6949+ glGenFramebuffers(1, &mFrameBufferName); 6950+ glGenTextures(1, &mTextureName); 6951+ if (!checkGlError("texture generation")) { 6952+ return false; 6953+ } 6954+ return true; 6955+} 6956+ 6957+GLuint FrameBuffer::GetTextureName() const { 6958+ return mTextureName; 6959+} 6960+ 6961+GLuint FrameBuffer::GetFrameBufferName() const { 6962+ return mFrameBufferName; 6963+} 6964+ 6965+GLenum FrameBuffer::GetFormat() const { 6966+ return mFormat; 6967+} 6968+ 6969+int FrameBuffer::GetWidth() const { 6970+ return mWidth; 6971+} 6972+ 6973+int FrameBuffer::GetHeight() const { 6974+ return mHeight; 6975+} 6976diff --git a/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.h b/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.h 6977new file mode 100755 6978index 00000000..314b1262 6979--- /dev/null 6980+++ b/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.h 6981@@ -0,0 +1,34 @@ 6982+#pragma once 6983+ 6984+#include <EGL/egl.h> 6985+#include <GLES2/gl2.h> 6986+#include <GLES2/gl2ext.h> 6987+ 6988+#define checkGlError(op) checkGLErrorDetail(__FILE__, __LINE__, (op)) 6989+ 6990+extern bool checkGLErrorDetail(const char* file, int line, const char* op); 6991+extern void checkFramebufferStatus(const char* name); 6992+ 6993+class FrameBuffer { 6994+ public: 6995+ FrameBuffer(); 6996+ virtual ~FrameBuffer(); 6997+ 6998+ bool InitializeGLContext(); 6999+ bool Init(int width, int height, GLenum format); 7000+ GLuint GetTextureName() const; 7001+ GLuint GetFrameBufferName() const; 7002+ GLenum GetFormat() const; 7003+ 7004+ int GetWidth() const; 7005+ int GetHeight() const; 7006+ 7007+ private: 7008+ void Reset(); 7009+ bool CreateBuffers(); 7010+ GLuint mFrameBufferName; 7011+ GLuint mTextureName; 7012+ int mWidth; 7013+ int mHeight; 7014+ GLenum mFormat; 7015+}; 7016diff --git a/benchmark/feature_mos/src/mosaic_renderer/Renderer.cpp b/benchmark/feature_mos/src/mosaic_renderer/Renderer.cpp 7017new file mode 100755 7018index 00000000..b9938eb6 7019--- /dev/null 7020+++ b/benchmark/feature_mos/src/mosaic_renderer/Renderer.cpp 7021@@ -0,0 +1,226 @@ 7022+/* 7023+ * Copyright (C) 2011 The Android Open Source Project 7024+ * 7025+ * Licensed under the Apache License, Version 2.0 (the "License"); 7026+ * you may not use this file except in compliance with the License. 7027+ * You may obtain a copy of the License at 7028+ * 7029+ * http://www.apache.org/licenses/LICENSE-2.0 7030+ * 7031+ * Unless required by applicable law or agreed to in writing, software 7032+ * distributed under the License is distributed on an "AS IS" BASIS, 7033+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7034+ * See the License for the specific language governing permissions and 7035+ * limitations under the License. 7036+ */ 7037+ 7038+#include "Renderer.h" 7039+ 7040+#include "mosaic/Log.h" 7041+#define LOG_TAG "Renderer" 7042+ 7043+#include <GLES2/gl2ext.h> 7044+ 7045+Renderer::Renderer() 7046+ : mGlProgram(0), 7047+ mInputTextureName(-1), 7048+ mInputTextureWidth(0), 7049+ mInputTextureHeight(0), 7050+ mSurfaceWidth(0), 7051+ mSurfaceHeight(0) 7052+{ 7053+ InitializeGLContext(); 7054+} 7055+ 7056+Renderer::~Renderer() { 7057+} 7058+ 7059+GLuint Renderer::loadShader(GLenum shaderType, const char* pSource) { 7060+ GLuint shader = glCreateShader(shaderType); 7061+ if (shader) { 7062+ glShaderSource(shader, 1, &pSource, NULL); 7063+ glCompileShader(shader); 7064+ GLint compiled = 0; 7065+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 7066+ if (!compiled) { 7067+ GLint infoLen = 0; 7068+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); 7069+ if (infoLen) { 7070+ char* buf = (char*) malloc(infoLen); 7071+ if (buf) { 7072+ glGetShaderInfoLog(shader, infoLen, NULL, buf); 7073+ LOGE("Could not compile shader %d:\n%s\n", 7074+ shaderType, buf); 7075+ free(buf); 7076+ } 7077+ glDeleteShader(shader); 7078+ shader = 0; 7079+ } 7080+ } 7081+ } 7082+ return shader; 7083+} 7084+ 7085+GLuint Renderer::createProgram(const char* pVertexSource, const char* pFragmentSource) 7086+{ 7087+ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); 7088+ if (!vertexShader) 7089+ { 7090+ return 0; 7091+ } 7092+ 7093+ GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); 7094+ if (!pixelShader) 7095+ { 7096+ return 0; 7097+ } 7098+ 7099+ GLuint program = glCreateProgram(); 7100+ if (program) 7101+ { 7102+ glAttachShader(program, vertexShader); 7103+ checkGlError("glAttachShader"); 7104+ glAttachShader(program, pixelShader); 7105+ checkGlError("glAttachShader"); 7106+ 7107+ glLinkProgram(program); 7108+ GLint linkStatus = GL_FALSE; 7109+ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); 7110+ 7111+ LOGI("Program Linked (%d)!", program); 7112+ 7113+ if (linkStatus != GL_TRUE) 7114+ { 7115+ GLint bufLength = 0; 7116+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); 7117+ if (bufLength) 7118+ { 7119+ char* buf = (char*) malloc(bufLength); 7120+ if (buf) 7121+ { 7122+ glGetProgramInfoLog(program, bufLength, NULL, buf); 7123+ LOGE("Could not link program:\n%s\n", buf); 7124+ free(buf); 7125+ } 7126+ } 7127+ glDeleteProgram(program); 7128+ program = 0; 7129+ } 7130+ } 7131+ return program; 7132+} 7133+ 7134+// Set this renderer to use the default frame-buffer (screen) and 7135+// set the viewport size to be the given width and height (pixels). 7136+bool Renderer::SetupGraphics(int width, int height) 7137+{ 7138+ bool succeeded = false; 7139+ do { 7140+ if (mGlProgram == 0) 7141+ { 7142+ if (!InitializeGLProgram()) 7143+ { 7144+ break; 7145+ } 7146+ } 7147+ glUseProgram(mGlProgram); 7148+ if (!checkGlError("glUseProgram")) break; 7149+ 7150+ glBindFramebuffer(GL_FRAMEBUFFER, 0); 7151+ 7152+ mFrameBuffer = NULL; 7153+ mSurfaceWidth = width; 7154+ mSurfaceHeight = height; 7155+ 7156+ glViewport(0, 0, mSurfaceWidth, mSurfaceHeight); 7157+ if (!checkGlError("glViewport")) break; 7158+ succeeded = true; 7159+ } while (false); 7160+ 7161+ return succeeded; 7162+} 7163+ 7164+ 7165+// Set this renderer to use the specified FBO and 7166+// set the viewport size to be the width and height of this FBO. 7167+bool Renderer::SetupGraphics(FrameBuffer* buffer) 7168+{ 7169+ bool succeeded = false; 7170+ do { 7171+ if (mGlProgram == 0) 7172+ { 7173+ if (!InitializeGLProgram()) 7174+ { 7175+ break; 7176+ } 7177+ } 7178+ glUseProgram(mGlProgram); 7179+ if (!checkGlError("glUseProgram")) break; 7180+ 7181+ glBindFramebuffer(GL_FRAMEBUFFER, buffer->GetFrameBufferName()); 7182+ 7183+ mFrameBuffer = buffer; 7184+ mSurfaceWidth = mFrameBuffer->GetWidth(); 7185+ mSurfaceHeight = mFrameBuffer->GetHeight(); 7186+ 7187+ glViewport(0, 0, mSurfaceWidth, mSurfaceHeight); 7188+ if (!checkGlError("glViewport")) break; 7189+ succeeded = true; 7190+ } while (false); 7191+ 7192+ return succeeded; 7193+} 7194+ 7195+bool Renderer::Clear(float r, float g, float b, float a) 7196+{ 7197+ bool succeeded = false; 7198+ do { 7199+ bool rt = (mFrameBuffer == NULL)? 7200+ SetupGraphics(mSurfaceWidth, mSurfaceHeight) : 7201+ SetupGraphics(mFrameBuffer); 7202+ 7203+ if(!rt) 7204+ break; 7205+ 7206+ glClearColor(r, g, b, a); 7207+ glClear(GL_COLOR_BUFFER_BIT); 7208+ 7209+ succeeded = true; 7210+ } while (false); 7211+ return succeeded; 7212+ 7213+} 7214+ 7215+void Renderer::InitializeGLContext() 7216+{ 7217+ if(mFrameBuffer != NULL) 7218+ { 7219+ delete mFrameBuffer; 7220+ mFrameBuffer = NULL; 7221+ } 7222+ 7223+ mInputTextureName = -1; 7224+ mInputTextureType = GL_TEXTURE_2D; 7225+ mGlProgram = 0; 7226+} 7227+ 7228+int Renderer::GetTextureName() 7229+{ 7230+ return mInputTextureName; 7231+} 7232+ 7233+void Renderer::SetInputTextureName(GLuint textureName) 7234+{ 7235+ mInputTextureName = textureName; 7236+} 7237+ 7238+void Renderer::SetInputTextureType(GLenum textureType) 7239+{ 7240+ mInputTextureType = textureType; 7241+} 7242+ 7243+void Renderer::SetInputTextureDimensions(int width, int height) 7244+{ 7245+ mInputTextureWidth = width; 7246+ mInputTextureHeight = height; 7247+} 7248diff --git a/benchmark/feature_mos/src/mosaic_renderer/Renderer.h b/benchmark/feature_mos/src/mosaic_renderer/Renderer.h 7249new file mode 100755 7250index 00000000..a43e8028 7251--- /dev/null 7252+++ b/benchmark/feature_mos/src/mosaic_renderer/Renderer.h 7253@@ -0,0 +1,65 @@ 7254+#pragma once 7255+ 7256+#include "FrameBuffer.h" 7257+ 7258+#include <GLES2/gl2.h> 7259+ 7260+#include <stdint.h> 7261+#include <stdio.h> 7262+#include <stdlib.h> 7263+ 7264+class Renderer { 7265+ public: 7266+ Renderer(); 7267+ virtual ~Renderer(); 7268+ 7269+ // Initialize OpenGL resources 7270+ // @return true if successful 7271+ virtual bool InitializeGLProgram() = 0; 7272+ 7273+ bool SetupGraphics(FrameBuffer* buffer); 7274+ bool SetupGraphics(int width, int height); 7275+ 7276+ bool Clear(float r, float g, float b, float a); 7277+ 7278+ int GetTextureName(); 7279+ void SetInputTextureName(GLuint textureName); 7280+ void SetInputTextureDimensions(int width, int height); 7281+ void SetInputTextureType(GLenum textureType); 7282+ 7283+ void InitializeGLContext(); 7284+ 7285+ protected: 7286+ 7287+ GLuint loadShader(GLenum shaderType, const char* pSource); 7288+ GLuint createProgram(const char*, const char* ); 7289+ 7290+ int SurfaceWidth() const { return mSurfaceWidth; } 7291+ int SurfaceHeight() const { return mSurfaceHeight; } 7292+ 7293+ // Source code for shaders. 7294+ virtual const char* VertexShaderSource() const = 0; 7295+ virtual const char* FragmentShaderSource() const = 0; 7296+ 7297+ // Redefine this to use special texture types such as 7298+ // GL_TEXTURE_EXTERNAL_OES. 7299+ GLenum InputTextureType() const { return mInputTextureType; } 7300+ 7301+ GLuint mGlProgram; 7302+ GLuint mInputTextureName; 7303+ GLenum mInputTextureType; 7304+ int mInputTextureWidth; 7305+ int mInputTextureHeight; 7306+ 7307+ // Attribute locations 7308+ GLint mScalingtransLoc; 7309+ GLint maPositionHandle; 7310+ GLint maTextureHandle; 7311+ 7312+ 7313+ int mSurfaceWidth; // Width of target surface. 7314+ int mSurfaceHeight; // Height of target surface. 7315+ 7316+ FrameBuffer *mFrameBuffer; 7317+}; 7318+ 7319diff --git a/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp b/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp 7320new file mode 100755 7321index 00000000..36f133f8 7322--- /dev/null 7323+++ b/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp 7324@@ -0,0 +1,186 @@ 7325+/* 7326+ * Copyright (C) 2011 The Android Open Source Project 7327+ * 7328+ * Licensed under the Apache License, Version 2.0 (the "License"); 7329+ * you may not use this file except in compliance with the License. 7330+ * You may obtain a copy of the License at 7331+ * 7332+ * http://www.apache.org/licenses/LICENSE-2.0 7333+ * 7334+ * Unless required by applicable law or agreed to in writing, software 7335+ * distributed under the License is distributed on an "AS IS" BASIS, 7336+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7337+ * See the License for the specific language governing permissions and 7338+ * limitations under the License. 7339+ */ 7340+ 7341+#include "SurfaceTextureRenderer.h" 7342+ 7343+#include <string.h> 7344+ 7345+#include <GLES2/gl2ext.h> 7346+const GLfloat g_vVertices[] = { 7347+ -1.f, -1.f, 0.0f, 1.0f, // Position 0 7348+ 0.0f, 0.0f, // TexCoord 0 7349+ 1.f, -1.f, 0.0f, 1.0f, // Position 1 7350+ 1.0f, 0.0f, // TexCoord 1 7351+ -1.f, 1.f, 0.0f, 1.0f, // Position 2 7352+ 0.0f, 1.0f, // TexCoord 2 7353+ 1.f, 1.f, 0.0f, 1.0f, // Position 3 7354+ 1.0f, 1.0f // TexCoord 3 7355+}; 7356+GLushort g_iIndices2[] = { 0, 1, 2, 3 }; 7357+ 7358+const int VERTEX_STRIDE = 6 * sizeof(GLfloat); 7359+ 7360+SurfaceTextureRenderer::SurfaceTextureRenderer() : Renderer() { 7361+ memset(mSTMatrix, 0.0, 16*sizeof(float)); 7362+ mSTMatrix[0] = 1.0f; 7363+ mSTMatrix[5] = 1.0f; 7364+ mSTMatrix[10] = 1.0f; 7365+ mSTMatrix[15] = 1.0f; 7366+} 7367+ 7368+SurfaceTextureRenderer::~SurfaceTextureRenderer() { 7369+} 7370+ 7371+void SurfaceTextureRenderer::SetViewportMatrix(int w, int h, int W, int H) 7372+{ 7373+ for(int i=0; i<16; i++) 7374+ { 7375+ mViewportMatrix[i] = 0.0f; 7376+ } 7377+ 7378+ mViewportMatrix[0] = float(w)/float(W); 7379+ mViewportMatrix[5] = float(h)/float(H); 7380+ mViewportMatrix[10] = 1.0f; 7381+ mViewportMatrix[12] = -1.0f + float(w)/float(W); 7382+ mViewportMatrix[13] = -1.0f + float(h)/float(H); 7383+ mViewportMatrix[15] = 1.0f; 7384+} 7385+ 7386+void SurfaceTextureRenderer::SetScalingMatrix(float xscale, float yscale) 7387+{ 7388+ for(int i=0; i<16; i++) 7389+ { 7390+ mScalingMatrix[i] = 0.0f; 7391+ } 7392+ 7393+ mScalingMatrix[0] = xscale; 7394+ mScalingMatrix[5] = yscale; 7395+ mScalingMatrix[10] = 1.0f; 7396+ mScalingMatrix[15] = 1.0f; 7397+} 7398+ 7399+void SurfaceTextureRenderer::SetSTMatrix(float *stmat) 7400+{ 7401+ memcpy(mSTMatrix, stmat, 16*sizeof(float)); 7402+} 7403+ 7404+ 7405+bool SurfaceTextureRenderer::InitializeGLProgram() 7406+{ 7407+ bool succeeded = false; 7408+ do { 7409+ GLuint glProgram; 7410+ glProgram = createProgram(VertexShaderSource(), 7411+ FragmentShaderSource()); 7412+ if (!glProgram) { 7413+ break; 7414+ } 7415+ 7416+ glUseProgram(glProgram); 7417+ if (!checkGlError("glUseProgram")) break; 7418+ 7419+ maPositionHandle = glGetAttribLocation(glProgram, "aPosition"); 7420+ checkGlError("glGetAttribLocation aPosition"); 7421+ maTextureHandle = glGetAttribLocation(glProgram, "aTextureCoord"); 7422+ checkGlError("glGetAttribLocation aTextureCoord"); 7423+ muSTMatrixHandle = glGetUniformLocation(glProgram, "uSTMatrix"); 7424+ checkGlError("glGetUniformLocation uSTMatrix"); 7425+ mScalingtransLoc = glGetUniformLocation(glProgram, "u_scalingtrans"); 7426+ 7427+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 7428+ mGlProgram = glProgram; 7429+ succeeded = true; 7430+ } while (false); 7431+ 7432+ if (!succeeded && (mGlProgram != 0)) 7433+ { 7434+ glDeleteProgram(mGlProgram); 7435+ checkGlError("glDeleteProgram"); 7436+ mGlProgram = 0; 7437+ } 7438+ return succeeded; 7439+} 7440+ 7441+bool SurfaceTextureRenderer::DrawTexture(GLfloat *affine) 7442+{ 7443+ bool succeeded = false; 7444+ do { 7445+ bool rt = (mFrameBuffer == NULL)? 7446+ SetupGraphics(mSurfaceWidth, mSurfaceHeight) : 7447+ SetupGraphics(mFrameBuffer); 7448+ 7449+ if(!rt) 7450+ break; 7451+ 7452+ glDisable(GL_BLEND); 7453+ 7454+ glActiveTexture(GL_TEXTURE0); 7455+ if (!checkGlError("glActiveTexture")) break; 7456+ 7457+ const GLenum texture_type = InputTextureType(); 7458+ glBindTexture(texture_type, mInputTextureName); 7459+ if (!checkGlError("glBindTexture")) break; 7460+ 7461+ glUniformMatrix4fv(mScalingtransLoc, 1, GL_FALSE, mScalingMatrix); 7462+ glUniformMatrix4fv(muSTMatrixHandle, 1, GL_FALSE, mSTMatrix); 7463+ 7464+ // Load the vertex position 7465+ glVertexAttribPointer(maPositionHandle, 4, GL_FLOAT, 7466+ GL_FALSE, VERTEX_STRIDE, g_vVertices); 7467+ glEnableVertexAttribArray(maPositionHandle); 7468+ // Load the texture coordinate 7469+ glVertexAttribPointer(maTextureHandle, 2, GL_FLOAT, 7470+ GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]); 7471+ glEnableVertexAttribArray(maTextureHandle); 7472+ 7473+ // And, finally, execute the GL draw command. 7474+ glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices2); 7475+ 7476+ glBindFramebuffer(GL_FRAMEBUFFER, 0); 7477+ succeeded = true; 7478+ } while (false); 7479+ return succeeded; 7480+} 7481+ 7482+const char* SurfaceTextureRenderer::VertexShaderSource() const 7483+{ 7484+ static const char gVertexShader[] = 7485+ "uniform mat4 uSTMatrix;\n" 7486+ "uniform mat4 u_scalingtrans; \n" 7487+ "attribute vec4 aPosition;\n" 7488+ "attribute vec4 aTextureCoord;\n" 7489+ "varying vec2 vTextureNormCoord;\n" 7490+ "void main() {\n" 7491+ " gl_Position = u_scalingtrans * aPosition;\n" 7492+ " vTextureNormCoord = (uSTMatrix * aTextureCoord).xy;\n" 7493+ "}\n"; 7494+ 7495+ return gVertexShader; 7496+} 7497+ 7498+const char* SurfaceTextureRenderer::FragmentShaderSource() const 7499+{ 7500+ static const char gFragmentShader[] = 7501+ "#extension GL_OES_EGL_image_external : require\n" 7502+ "precision mediump float;\n" 7503+ "varying vec2 vTextureNormCoord;\n" 7504+ "uniform samplerExternalOES sTexture;\n" 7505+ "void main() {\n" 7506+ " gl_FragColor = texture2D(sTexture, vTextureNormCoord);\n" 7507+ "}\n"; 7508+ 7509+ return gFragmentShader; 7510+} 7511diff --git a/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h b/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h 7512new file mode 100755 7513index 00000000..ea2b81ad 7514--- /dev/null 7515+++ b/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h 7516@@ -0,0 +1,44 @@ 7517+#pragma once 7518+ 7519+#include "FrameBuffer.h" 7520+#include "Renderer.h" 7521+ 7522+#include <GLES2/gl2.h> 7523+ 7524+#include <stdint.h> 7525+#include <stdio.h> 7526+#include <stdlib.h> 7527+ 7528+class SurfaceTextureRenderer: public Renderer { 7529+ public: 7530+ SurfaceTextureRenderer(); 7531+ virtual ~SurfaceTextureRenderer(); 7532+ 7533+ // Initialize OpenGL resources 7534+ // @return true if successful 7535+ bool InitializeGLProgram(); 7536+ 7537+ bool DrawTexture(GLfloat *affine); 7538+ 7539+ void SetViewportMatrix(int w, int h, int W, int H); 7540+ void SetScalingMatrix(float xscale, float yscale); 7541+ void SetSTMatrix(float *stmat); 7542+ 7543+ private: 7544+ // Source code for shaders. 7545+ const char* VertexShaderSource() const; 7546+ const char* FragmentShaderSource() const; 7547+ 7548+ // Attribute locations 7549+ GLint mScalingtransLoc; 7550+ GLint muSTMatrixHandle; 7551+ GLint maPositionHandle; 7552+ GLint maTextureHandle; 7553+ 7554+ GLfloat mViewportMatrix[16]; 7555+ GLfloat mScalingMatrix[16]; 7556+ 7557+ GLfloat mSTMatrix[16]; 7558+ 7559+}; 7560+ 7561diff --git a/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.cpp b/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.cpp 7562new file mode 100755 7563index 00000000..af6779a3 7564--- /dev/null 7565+++ b/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.cpp 7566@@ -0,0 +1,190 @@ 7567+/* 7568+ * Copyright (C) 2011 The Android Open Source Project 7569+ * 7570+ * Licensed under the Apache License, Version 2.0 (the "License"); 7571+ * you may not use this file except in compliance with the License. 7572+ * You may obtain a copy of the License at 7573+ * 7574+ * http://www.apache.org/licenses/LICENSE-2.0 7575+ * 7576+ * Unless required by applicable law or agreed to in writing, software 7577+ * distributed under the License is distributed on an "AS IS" BASIS, 7578+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7579+ * See the License for the specific language governing permissions and 7580+ * limitations under the License. 7581+ */ 7582+ 7583+#include "WarpRenderer.h" 7584+ 7585+#include <GLES2/gl2ext.h> 7586+ 7587+const GLfloat g_vVertices[] = { 7588+ -1.f, 1.f, 0.0f, 1.0f, // Position 0 7589+ 0.0f, 1.0f, // TexCoord 0 7590+ 1.f, 1.f, 0.0f, 1.0f, // Position 1 7591+ 1.0f, 1.0f, // TexCoord 1 7592+ -1.f, -1.f, 0.0f, 1.0f, // Position 2 7593+ 0.0f, 0.0f, // TexCoord 2 7594+ 1.f, -1.f, 0.0f, 1.0f, // Position 3 7595+ 1.0f, 0.0f // TexCoord 3 7596+}; 7597+ 7598+const int VERTEX_STRIDE = 6 * sizeof(GLfloat); 7599+ 7600+GLushort g_iIndices[] = { 0, 1, 2, 3 }; 7601+ 7602+WarpRenderer::WarpRenderer() : Renderer() 7603+{ 7604+} 7605+ 7606+WarpRenderer::~WarpRenderer() { 7607+} 7608+ 7609+void WarpRenderer::SetViewportMatrix(int w, int h, int W, int H) 7610+{ 7611+ for(int i=0; i<16; i++) 7612+ { 7613+ mViewportMatrix[i] = 0.0f; 7614+ } 7615+ 7616+ mViewportMatrix[0] = float(w)/float(W); 7617+ mViewportMatrix[5] = float(h)/float(H); 7618+ mViewportMatrix[10] = 1.0f; 7619+ mViewportMatrix[12] = -1.0f + float(w)/float(W); 7620+ mViewportMatrix[13] = -1.0f + float(h)/float(H); 7621+ mViewportMatrix[15] = 1.0f; 7622+} 7623+ 7624+void WarpRenderer::SetScalingMatrix(float xscale, float yscale) 7625+{ 7626+ for(int i=0; i<16; i++) 7627+ { 7628+ mScalingMatrix[i] = 0.0f; 7629+ } 7630+ 7631+ mScalingMatrix[0] = xscale; 7632+ mScalingMatrix[5] = yscale; 7633+ mScalingMatrix[10] = 1.0f; 7634+ mScalingMatrix[15] = 1.0f; 7635+} 7636+ 7637+bool WarpRenderer::InitializeGLProgram() 7638+{ 7639+ bool succeeded = false; 7640+ do { 7641+ GLuint glProgram; 7642+ glProgram = createProgram(VertexShaderSource(), 7643+ FragmentShaderSource()); 7644+ if (!glProgram) { 7645+ break; 7646+ } 7647+ 7648+ glUseProgram(glProgram); 7649+ if (!checkGlError("glUseProgram")) break; 7650+ 7651+ // Get attribute locations 7652+ mPositionLoc = glGetAttribLocation(glProgram, "a_position"); 7653+ mAffinetransLoc = glGetUniformLocation(glProgram, "u_affinetrans"); 7654+ mViewporttransLoc = glGetUniformLocation(glProgram, "u_viewporttrans"); 7655+ mScalingtransLoc = glGetUniformLocation(glProgram, "u_scalingtrans"); 7656+ mTexCoordLoc = glGetAttribLocation(glProgram, "a_texCoord"); 7657+ 7658+ // Get sampler location 7659+ mSamplerLoc = glGetUniformLocation(glProgram, "s_texture"); 7660+ 7661+ mGlProgram = glProgram; 7662+ succeeded = true; 7663+ } while (false); 7664+ 7665+ if (!succeeded && (mGlProgram != 0)) 7666+ { 7667+ glDeleteProgram(mGlProgram); 7668+ checkGlError("glDeleteProgram"); 7669+ mGlProgram = 0; 7670+ } 7671+ return succeeded; 7672+} 7673+ 7674+bool WarpRenderer::DrawTexture(GLfloat *affine) 7675+{ 7676+ bool succeeded = false; 7677+ do { 7678+ bool rt = (mFrameBuffer == NULL)? 7679+ SetupGraphics(mSurfaceWidth, mSurfaceHeight) : 7680+ SetupGraphics(mFrameBuffer); 7681+ 7682+ if(!rt) 7683+ break; 7684+ 7685+ glDisable(GL_BLEND); 7686+ 7687+ glActiveTexture(GL_TEXTURE0); 7688+ if (!checkGlError("glActiveTexture")) break; 7689+ 7690+ const GLenum texture_type = InputTextureType(); 7691+ glBindTexture(texture_type, mInputTextureName); 7692+ if (!checkGlError("glBindTexture")) break; 7693+ 7694+ // Set the sampler texture unit to 0 7695+ glUniform1i(mSamplerLoc, 0); 7696+ 7697+ // Load the vertex position 7698+ glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT, 7699+ GL_FALSE, VERTEX_STRIDE, g_vVertices); 7700+ 7701+ // Load the texture coordinate 7702+ glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, 7703+ GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]); 7704+ 7705+ glEnableVertexAttribArray(mPositionLoc); 7706+ glEnableVertexAttribArray(mTexCoordLoc); 7707+ 7708+ // pass matrix information to the vertex shader 7709+ glUniformMatrix4fv(mAffinetransLoc, 1, GL_FALSE, affine); 7710+ glUniformMatrix4fv(mViewporttransLoc, 1, GL_FALSE, mViewportMatrix); 7711+ glUniformMatrix4fv(mScalingtransLoc, 1, GL_FALSE, mScalingMatrix); 7712+ 7713+ // And, finally, execute the GL draw command. 7714+ glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices); 7715+ 7716+ checkGlError("glDrawElements"); 7717+ 7718+ glBindFramebuffer(GL_FRAMEBUFFER, 0); 7719+ succeeded = true; 7720+ } while (false); 7721+ return succeeded; 7722+} 7723+ 7724+const char* WarpRenderer::VertexShaderSource() const 7725+{ 7726+ static const char gVertexShader[] = 7727+ "uniform mat4 u_affinetrans; \n" 7728+ "uniform mat4 u_viewporttrans; \n" 7729+ "uniform mat4 u_scalingtrans; \n" 7730+ "attribute vec4 a_position; \n" 7731+ "attribute vec2 a_texCoord; \n" 7732+ "varying vec2 v_texCoord; \n" 7733+ "void main() \n" 7734+ "{ \n" 7735+ " gl_Position = u_scalingtrans * u_viewporttrans * u_affinetrans * a_position; \n" 7736+ " v_texCoord = a_texCoord; \n" 7737+ "} \n"; 7738+ 7739+ return gVertexShader; 7740+} 7741+ 7742+const char* WarpRenderer::FragmentShaderSource() const 7743+{ 7744+ static const char gFragmentShader[] = 7745+ "precision mediump float; \n" 7746+ "varying vec2 v_texCoord; \n" 7747+ "uniform sampler2D s_texture; \n" 7748+ "void main() \n" 7749+ "{ \n" 7750+ " vec4 color; \n" 7751+ " color = texture2D(s_texture, v_texCoord); \n" 7752+ " gl_FragColor = color; \n" 7753+ "} \n"; 7754+ 7755+ return gFragmentShader; 7756+} 7757diff --git a/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.h b/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.h 7758new file mode 100755 7759index 00000000..aa3f50c0 7760--- /dev/null 7761+++ b/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.h 7762@@ -0,0 +1,44 @@ 7763+#pragma once 7764+ 7765+#include "FrameBuffer.h" 7766+#include "Renderer.h" 7767+ 7768+#include <GLES2/gl2.h> 7769+ 7770+#include <stdint.h> 7771+#include <stdio.h> 7772+#include <stdlib.h> 7773+ 7774+class WarpRenderer: public Renderer { 7775+ public: 7776+ WarpRenderer(); 7777+ virtual ~WarpRenderer(); 7778+ 7779+ // Initialize OpenGL resources 7780+ // @return true if successful 7781+ bool InitializeGLProgram(); 7782+ 7783+ void SetViewportMatrix(int w, int h, int W, int H); 7784+ void SetScalingMatrix(float xscale, float yscale); 7785+ 7786+ bool DrawTexture(GLfloat *affine); 7787+ 7788+ private: 7789+ // Source code for shaders. 7790+ const char* VertexShaderSource() const; 7791+ const char* FragmentShaderSource() const; 7792+ 7793+ // Attribute locations 7794+ GLint mPositionLoc; 7795+ GLint mAffinetransLoc; 7796+ GLint mViewporttransLoc; 7797+ GLint mScalingtransLoc; 7798+ GLint mTexCoordLoc; 7799+ 7800+ GLfloat mViewportMatrix[16]; 7801+ GLfloat mScalingMatrix[16]; 7802+ 7803+ // Sampler location 7804+ GLint mSamplerLoc; 7805+}; 7806+ 7807diff --git a/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.cpp b/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.cpp 7808new file mode 100755 7809index 00000000..f7dcf6f6 7810--- /dev/null 7811+++ b/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.cpp 7812@@ -0,0 +1,160 @@ 7813+/* 7814+ * Copyright (C) 2011 The Android Open Source Project 7815+ * 7816+ * Licensed under the Apache License, Version 2.0 (the "License"); 7817+ * you may not use this file except in compliance with the License. 7818+ * You may obtain a copy of the License at 7819+ * 7820+ * http://www.apache.org/licenses/LICENSE-2.0 7821+ * 7822+ * Unless required by applicable law or agreed to in writing, software 7823+ * distributed under the License is distributed on an "AS IS" BASIS, 7824+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7825+ * See the License for the specific language governing permissions and 7826+ * limitations under the License. 7827+ */ 7828+ 7829+#include "YVURenderer.h" 7830+ 7831+#include <GLES2/gl2ext.h> 7832+ 7833+const GLfloat g_vVertices[] = { 7834+ -1.f, 1.f, 0.0f, 1.0f, // Position 0 7835+ 0.0f, 1.0f, // TexCoord 0 7836+ 1.f, 1.f, 0.0f, 1.0f, // Position 1 7837+ 1.0f, 1.0f, // TexCoord 1 7838+ -1.f, -1.f, 0.0f, 1.0f, // Position 2 7839+ 0.0f, 0.0f, // TexCoord 2 7840+ 1.f, -1.f, 0.0f, 1.0f, // Position 3 7841+ 1.0f, 0.0f // TexCoord 3 7842+}; 7843+ 7844+const int VERTEX_STRIDE = 6 * sizeof(GLfloat); 7845+ 7846+GLushort g_iIndices3[] = { 0, 1, 2, 3 }; 7847+ 7848+YVURenderer::YVURenderer() : Renderer() 7849+ { 7850+} 7851+ 7852+YVURenderer::~YVURenderer() { 7853+} 7854+ 7855+bool YVURenderer::InitializeGLProgram() 7856+{ 7857+ bool succeeded = false; 7858+ do { 7859+ GLuint glProgram; 7860+ glProgram = createProgram(VertexShaderSource(), 7861+ FragmentShaderSource()); 7862+ if (!glProgram) { 7863+ break; 7864+ } 7865+ 7866+ glUseProgram(glProgram); 7867+ if (!checkGlError("glUseProgram")) break; 7868+ 7869+ // Get attribute locations 7870+ mPositionLoc = glGetAttribLocation(glProgram, "a_Position"); 7871+ mTexCoordLoc = glGetAttribLocation(glProgram, "a_texCoord"); 7872+ 7873+ // Get sampler location 7874+ mSamplerLoc = glGetUniformLocation(glProgram, "s_texture"); 7875+ 7876+ mGlProgram = glProgram; 7877+ succeeded = true; 7878+ } while (false); 7879+ 7880+ if (!succeeded && (mGlProgram != 0)) 7881+ { 7882+ glDeleteProgram(mGlProgram); 7883+ checkGlError("glDeleteProgram"); 7884+ mGlProgram = 0; 7885+ } 7886+ return succeeded; 7887+} 7888+ 7889+bool YVURenderer::DrawTexture() 7890+{ 7891+ bool succeeded = false; 7892+ do { 7893+ bool rt = (mFrameBuffer == NULL)? 7894+ SetupGraphics(mSurfaceWidth, mSurfaceHeight) : 7895+ SetupGraphics(mFrameBuffer); 7896+ 7897+ if(!rt) 7898+ break; 7899+ 7900+ glDisable(GL_BLEND); 7901+ 7902+ glActiveTexture(GL_TEXTURE0); 7903+ if (!checkGlError("glActiveTexture")) break; 7904+ 7905+ const GLenum texture_type = InputTextureType(); 7906+ glBindTexture(texture_type, mInputTextureName); 7907+ if (!checkGlError("glBindTexture")) break; 7908+ 7909+ // Set the sampler texture unit to 0 7910+ glUniform1i(mSamplerLoc, 0); 7911+ 7912+ // Load the vertex position 7913+ glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT, 7914+ GL_FALSE, VERTEX_STRIDE, g_vVertices); 7915+ 7916+ // Load the texture coordinate 7917+ glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, 7918+ GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]); 7919+ 7920+ glEnableVertexAttribArray(mPositionLoc); 7921+ glEnableVertexAttribArray(mTexCoordLoc); 7922+ 7923+ // And, finally, execute the GL draw command. 7924+ glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices3); 7925+ 7926+ checkGlError("glDrawElements"); 7927+ 7928+ glBindFramebuffer(GL_FRAMEBUFFER, 0); 7929+ succeeded = true; 7930+ } while (false); 7931+ return succeeded; 7932+} 7933+ 7934+const char* YVURenderer::VertexShaderSource() const 7935+{ 7936+ // All this really does is copy the coordinates into 7937+ // variables for the fragment shader to pick up. 7938+ static const char gVertexShader[] = 7939+ "attribute vec4 a_Position;\n" 7940+ "attribute vec2 a_texCoord;\n" 7941+ "varying vec2 v_texCoord;\n" 7942+ "void main() {\n" 7943+ " gl_Position = a_Position;\n" 7944+ " v_texCoord = a_texCoord;\n" 7945+ "}\n"; 7946+ 7947+ return gVertexShader; 7948+} 7949+ 7950+const char* YVURenderer::FragmentShaderSource() const 7951+{ 7952+ static const char gFragmentShader[] = 7953+ "precision mediump float;\n" 7954+ "uniform sampler2D s_texture;\n" 7955+ "const vec4 coeff_y = vec4(0.257, 0.594, 0.098, 0.063);\n" 7956+ "const vec4 coeff_v = vec4(0.439, -0.368, -0.071, 0.500);\n" 7957+ "const vec4 coeff_u = vec4(-0.148, -0.291, 0.439, 0.500);\n" 7958+ "varying vec2 v_texCoord;\n" 7959+ "void main() {\n" 7960+ " vec4 p;\n" 7961+ " p = texture2D(s_texture, v_texCoord);\n" 7962+ " gl_FragColor[0] = dot(p, coeff_y);\n" 7963+ " p = texture2D(s_texture, v_texCoord);\n" 7964+ " gl_FragColor[1] = dot(p, coeff_v);\n" 7965+ " p = texture2D(s_texture, v_texCoord);\n" 7966+ " gl_FragColor[2] = dot(p, coeff_u);\n" 7967+ " p = texture2D(s_texture, v_texCoord);\n" 7968+ " gl_FragColor[3] = dot(p, coeff_y);\n" 7969+ "}\n"; 7970+ 7971+ return gFragmentShader; 7972+} 7973diff --git a/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.h b/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.h 7974new file mode 100755 7975index 00000000..d14a4b99 7976--- /dev/null 7977+++ b/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.h 7978@@ -0,0 +1,35 @@ 7979+#pragma once 7980+ 7981+#include "FrameBuffer.h" 7982+#include "Renderer.h" 7983+ 7984+#include <GLES2/gl2.h> 7985+ 7986+#include <stdint.h> 7987+#include <stdio.h> 7988+#include <stdlib.h> 7989+ 7990+class YVURenderer: public Renderer { 7991+ public: 7992+ YVURenderer(); 7993+ virtual ~YVURenderer(); 7994+ 7995+ // Initialize OpenGL resources 7996+ // @return true if successful 7997+ bool InitializeGLProgram(); 7998+ 7999+ bool DrawTexture(); 8000+ 8001+ private: 8002+ // Source code for shaders. 8003+ const char* VertexShaderSource() const; 8004+ const char* FragmentShaderSource() const; 8005+ 8006+ // Attribute locations 8007+ GLint mPositionLoc; 8008+ GLint mTexCoordLoc; 8009+ 8010+ // Sampler location 8011+ GLint mSamplerLoc; 8012+}; 8013+ 8014diff --git a/benchmark/feature_mos_jni.cpp b/benchmark/feature_mos_jni.cpp 8015new file mode 100644 8016index 00000000..e40b75a0 8017--- /dev/null 8018+++ b/benchmark/feature_mos_jni.cpp 8019@@ -0,0 +1,669 @@ 8020+/* 8021+ * Copyright (C) 2011 The Android Open Source Project 8022+ * 8023+ * Licensed under the Apache License, Version 2.0 (the "License"); 8024+ * you may not use this file except in compliance with the License. 8025+ * You may obtain a copy of the License at 8026+ * 8027+ * http://www.apache.org/licenses/LICENSE-2.0 8028+ * 8029+ * Unless required by applicable law or agreed to in writing, software 8030+ * distributed under the License is distributed on an "AS IS" BASIS, 8031+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8032+ * See the License for the specific language governing permissions and 8033+ * limitations under the License. 8034+ */ 8035+ 8036+/* 8037+* 8038+ */ 8039+#include <string.h> 8040+#include <jni.h> 8041+#include <stdio.h> 8042+#include <stdlib.h> 8043+#include <time.h> 8044+#include <db_utilities_camera.h> 8045+ 8046+#include "mosaic/AlignFeatures.h" 8047+#include "mosaic/Blend.h" 8048+#include "mosaic/Mosaic.h" 8049+#include "mosaic/Log.h" 8050+#define LOG_TAG "FEATURE_MOS_JNI" 8051+ 8052+#ifdef __cplusplus 8053+extern "C" { 8054+#endif 8055+ 8056+#include "mosaic_renderer_jni.h" 8057+ 8058+char buffer[1024]; 8059+ 8060+const int MAX_FRAMES = 100; 8061+ 8062+static double mTx; 8063+ 8064+int tWidth[NR]; 8065+int tHeight[NR]; 8066+ 8067+ImageType tImage[NR][MAX_FRAMES];// = {{ImageUtils::IMAGE_TYPE_NOIMAGE}}; // YVU24 format image 8068+Mosaic *mosaic[NR] = {NULL,NULL}; 8069+ImageType resultYVU = ImageUtils::IMAGE_TYPE_NOIMAGE; 8070+ImageType resultBGR = ImageUtils::IMAGE_TYPE_NOIMAGE; 8071+float gTRS[11]; // 9 elements of the transformation, 1 for frame-number, 1 for alignment error code. 8072+// Variables to keep track of the mosaic computation progress for both LR & HR. 8073+float gProgress[NR]; 8074+// Variables to be able to cancel the mosaic computation when the GUI says so. 8075+bool gCancelComputation[NR]; 8076+ 8077+int c; 8078+int width=0, height=0; 8079+int mosaicWidth=0, mosaicHeight=0; 8080+ 8081+//int blendingType = Blend::BLEND_TYPE_FULL; 8082+//int blendingType = Blend::BLEND_TYPE_CYLPAN; 8083+int blendingType = Blend::BLEND_TYPE_HORZ; 8084+int stripType = Blend::STRIP_TYPE_THIN; 8085+bool high_res = false; 8086+bool quarter_res[NR] = {false,false}; 8087+float thresh_still[NR] = {5.0f,0.0f}; 8088+ 8089+/* return current time in milliseconds*/ 8090+ 8091+#ifndef now_ms 8092+static double 8093+now_ms(void) 8094+{ 8095+ //struct timespec res; 8096+ struct timeval res; 8097+ //clock_gettime(CLOCK_REALTIME, &res); 8098+ gettimeofday(&res, NULL); 8099+ return 1000.0*res.tv_sec + (double)res.tv_usec/1e3; 8100+} 8101+#endif 8102+ 8103+ 8104+static int frame_number_HR = 0; 8105+static int frame_number_LR = 0; 8106+ 8107+int Init(int mID, int nmax) 8108+{ 8109+ double t0, t1, time_c; 8110+ 8111+ if(mosaic[mID]!=NULL) 8112+ { 8113+ delete mosaic[mID]; 8114+ mosaic[mID] = NULL; 8115+ } 8116+ 8117+ mosaic[mID] = new Mosaic(); 8118+ 8119+ t0 = now_ms(); 8120+ 8121+ // When processing higher than 720x480 video, process low-res at 8122+ // quarter resolution 8123+ if(tWidth[LR]>180) 8124+ quarter_res[LR] = true; 8125+ 8126+ 8127+ // Check for initialization and if not, initialize 8128+ if (!mosaic[mID]->isInitialized()) 8129+ { 8130+ mosaic[mID]->initialize(blendingType, stripType, tWidth[mID], tHeight[mID], 8131+ nmax, quarter_res[mID], thresh_still[mID]); 8132+ } 8133+ 8134+ t1 = now_ms(); 8135+ time_c = t1 - t0; 8136+ LOGV("Init[%d]: %g ms [%d frames]",mID,time_c,nmax); 8137+ return 1; 8138+} 8139+ 8140+void GenerateQuarterResImagePlanar(ImageType im, int input_w, int input_h, 8141+ ImageType &out) 8142+{ 8143+ ImageType imp; 8144+ ImageType outp; 8145+ 8146+ int count = 0; 8147+ 8148+ for (int j = 0; j < input_h; j += H2L_FACTOR) 8149+ { 8150+ imp = im + j * input_w; 8151+ outp = out + (j / H2L_FACTOR) * (input_w / H2L_FACTOR); 8152+ 8153+ for (int i = 0; i < input_w; i += H2L_FACTOR) 8154+ { 8155+ *outp++ = *(imp + i); 8156+ count++; 8157+ } 8158+ } 8159+ 8160+ for (int j = input_h; j < 2 * input_h; j += H2L_FACTOR) 8161+ { 8162+ imp = im + j * input_w; 8163+ outp = out + (j / H2L_FACTOR) * (input_w / H2L_FACTOR); 8164+ 8165+ for (int i = 0; i < input_w; i += H2L_FACTOR) 8166+ { 8167+ *outp++ = *(imp + i); 8168+ count++; 8169+ } 8170+ } 8171+ 8172+ for (int j = 2 * input_h; j < 3 * input_h; j += H2L_FACTOR) 8173+ { 8174+ imp = im + j * input_w; 8175+ outp = out + (j / H2L_FACTOR) * (input_w / H2L_FACTOR); 8176+ 8177+ for (int i = 0; i < input_w; i += H2L_FACTOR) 8178+ { 8179+ *outp++ = *(imp + i); 8180+ count++; 8181+ } 8182+ } 8183+} 8184+ 8185+int AddFrame(int mID, int k, float* trs1d) 8186+{ 8187+ double t0, t1, time_c; 8188+ double trs[3][3]; 8189+ 8190+ int ret_code = mosaic[mID]->addFrame(tImage[mID][k]); 8191+ 8192+ mosaic[mID]->getAligner()->getLastTRS(trs); 8193+ 8194+ if(trs1d!=NULL) 8195+ { 8196+ 8197+ trs1d[0] = trs[0][0]; 8198+ trs1d[1] = trs[0][1]; 8199+ trs1d[2] = trs[0][2]; 8200+ trs1d[3] = trs[1][0]; 8201+ trs1d[4] = trs[1][1]; 8202+ trs1d[5] = trs[1][2]; 8203+ trs1d[6] = trs[2][0]; 8204+ trs1d[7] = trs[2][1]; 8205+ trs1d[8] = trs[2][2]; 8206+ } 8207+ 8208+ return ret_code; 8209+} 8210+ 8211+int Finalize(int mID) 8212+{ 8213+ double t0, t1, time_c; 8214+ 8215+ t0 = now_ms(); 8216+ // Create the mosaic 8217+ int ret = mosaic[mID]->createMosaic(gProgress[mID], gCancelComputation[mID]); 8218+ t1 = now_ms(); 8219+ time_c = t1 - t0; 8220+ LOGV("CreateMosaic: %g ms",time_c); 8221+ 8222+ // Get back the result 8223+ resultYVU = mosaic[mID]->getMosaic(mosaicWidth, mosaicHeight); 8224+ 8225+ return ret; 8226+} 8227+ 8228+void YUV420toYVU24(ImageType yvu24, ImageType yuv420sp, int width, int height) 8229+{ 8230+ int frameSize = width * height; 8231+ 8232+ ImageType oyp = yvu24; 8233+ ImageType ovp = yvu24+frameSize; 8234+ ImageType oup = yvu24+frameSize+frameSize; 8235+ 8236+ for (int j = 0, yp = 0; j < height; j++) 8237+ { 8238+ unsigned char u = 0, v = 0; 8239+ int uvp = frameSize + (j >> 1) * width; 8240+ for (int i = 0; i < width; i++, yp++) 8241+ { 8242+ *oyp++ = yuv420sp[yp]; 8243+ //int y = (0xff & (int)yuv420sp[yp]) -16; 8244+ //yvu24p[yp] = (y<0)?0:y; 8245+ 8246+ if ((i & 1) == 0) 8247+ { 8248+ v = yuv420sp[uvp++]; 8249+ u = yuv420sp[uvp++]; 8250+ } 8251+ 8252+ *ovp++ = v; 8253+ *oup++ = u; 8254+ } 8255+ } 8256+} 8257+ 8258+void YUV420toYVU24_NEW(ImageType yvu24, ImageType yuv420sp, int width, 8259+ int height) 8260+{ 8261+ int frameSize = width * height; 8262+ 8263+ ImageType oyp = yvu24; 8264+ ImageType ovp = yvu24 + frameSize; 8265+ ImageType oup = yvu24 + frameSize + frameSize; 8266+ 8267+ memcpy(yvu24, yuv420sp, frameSize * sizeof(unsigned char)); 8268+ 8269+ for (int j = 0; j < height; j += 2) 8270+ { 8271+ unsigned char u = 0, v = 0; 8272+ int uvp = frameSize + (j >> 1) * width; 8273+ ovp = yvu24 + frameSize + j * width; 8274+ oup = ovp + frameSize; 8275+ 8276+ ImageType iuvp = yuv420sp + uvp; 8277+ 8278+ for (int i = 0; i < width; i += 2) 8279+ { 8280+ v = *iuvp++; 8281+ u = *iuvp++; 8282+ 8283+ *ovp++ = v; 8284+ *oup++ = u; 8285+ 8286+ *ovp++ = v; 8287+ *oup++ = u; 8288+ 8289+ } 8290+ memcpy(ovp, ovp - width, width * sizeof(unsigned char)); 8291+ memcpy(oup, oup - width, width * sizeof(unsigned char)); 8292+ } 8293+} 8294+ 8295+ 8296+JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_allocateMosaicMemory( 8297+ JNIEnv* env, jobject thiz, jint width, jint height) 8298+{ 8299+ tWidth[HR] = width; 8300+ tHeight[HR] = height; 8301+ tWidth[LR] = int(width / H2L_FACTOR); 8302+ tHeight[LR] = int(height / H2L_FACTOR); 8303+ 8304+ for(int i=0; i<MAX_FRAMES; i++) 8305+ { 8306+ tImage[LR][i] = ImageUtils::allocateImage(tWidth[LR], tHeight[LR], 8307+ ImageUtils::IMAGE_TYPE_NUM_CHANNELS); 8308+ tImage[HR][i] = ImageUtils::allocateImage(tWidth[HR], tHeight[HR], 8309+ ImageUtils::IMAGE_TYPE_NUM_CHANNELS); 8310+ } 8311+ 8312+ AllocateTextureMemory(tWidth[HR], tHeight[HR], tWidth[LR], tHeight[LR]); 8313+} 8314+ 8315+JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_freeMosaicMemory( 8316+ JNIEnv* env, jobject thiz) 8317+{ 8318+ for(int i = 0; i < MAX_FRAMES; i++) 8319+ { 8320+ ImageUtils::freeImage(tImage[LR][i]); 8321+ ImageUtils::freeImage(tImage[HR][i]); 8322+ } 8323+ 8324+ FreeTextureMemory(); 8325+} 8326+ 8327+ 8328+void decodeYUV444SP(unsigned char* rgb, unsigned char* yuv420sp, int width, 8329+ int height) 8330+{ 8331+ int frameSize = width * height; 8332+ 8333+ for (int j = 0, yp = 0; j < height; j++) 8334+ { 8335+ int vp = frameSize + j * width, u = 0, v = 0; 8336+ int up = vp + frameSize; 8337+ 8338+ for (int i = 0; i < width; i++, yp++, vp++, up++) 8339+ { 8340+ int y = (0xff & ((int) yuv420sp[yp])) - 16; 8341+ if (y < 0) y = 0; 8342+ 8343+ v = (0xff & yuv420sp[vp]) - 128; 8344+ u = (0xff & yuv420sp[up]) - 128; 8345+ 8346+ int y1192 = 1192 * y; 8347+ int r = (y1192 + 1634 * v); 8348+ int g = (y1192 - 833 * v - 400 * u); 8349+ int b = (y1192 + 2066 * u); 8350+ 8351+ if (r < 0) r = 0; else if (r > 262143) r = 262143; 8352+ if (g < 0) g = 0; else if (g > 262143) g = 262143; 8353+ if (b < 0) b = 0; else if (b > 262143) b = 262143; 8354+ 8355+ //rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); 8356+ int p = j*width*3+i*3; 8357+ rgb[p+0] = (r<<6 & 0xFF0000)>>16; 8358+ rgb[p+1] = (g>>2 & 0xFF00)>>8; 8359+ rgb[p+2] = b>>10 & 0xFF; 8360+ } 8361+ } 8362+} 8363+ 8364+static int count = 0; 8365+ 8366+void ConvertYVUAiToPlanarYVU(unsigned char *planar, unsigned char *in, int width, 8367+ int height) 8368+{ 8369+ int planeSize = width * height; 8370+ unsigned char* Yptr = planar; 8371+ unsigned char* Vptr = planar + planeSize; 8372+ unsigned char* Uptr = Vptr + planeSize; 8373+ 8374+ for (int i = 0; i < planeSize; i++) 8375+ { 8376+ *Yptr++ = *in++; 8377+ *Vptr++ = *in++; 8378+ *Uptr++ = *in++; 8379+ in++; // Alpha 8380+ } 8381+} 8382+ 8383+JNIEXPORT jfloatArray JNICALL Java_com_android_camera_panorama_Mosaic_setSourceImageFromGPU( 8384+ JNIEnv* env, jobject thiz) 8385+{ 8386+ double t0, t1, time_c; 8387+ t0 = now_ms(); 8388+ int ret_code; 8389+ 8390+ if(frame_number_HR<MAX_FRAMES && frame_number_LR<MAX_FRAMES) 8391+ { 8392+ double last_tx = mTx; 8393+ 8394+ sem_wait(&gPreviewImage_semaphore); 8395+ ConvertYVUAiToPlanarYVU(tImage[LR][frame_number_LR], gPreviewImage[LR], 8396+ tWidth[LR], tHeight[LR]); 8397+ 8398+ sem_post(&gPreviewImage_semaphore); 8399+ 8400+ ret_code = AddFrame(LR, frame_number_LR, gTRS); 8401+ 8402+ if(ret_code == Mosaic::MOSAIC_RET_OK || ret_code == Mosaic::MOSAIC_RET_FEW_INLIERS) 8403+ { 8404+ // Copy into HR buffer only if this is a valid frame 8405+ sem_wait(&gPreviewImage_semaphore); 8406+ ConvertYVUAiToPlanarYVU(tImage[HR][frame_number_HR], gPreviewImage[HR], 8407+ tWidth[HR], tHeight[HR]); 8408+ sem_post(&gPreviewImage_semaphore); 8409+ 8410+ frame_number_LR++; 8411+ frame_number_HR++; 8412+ } 8413+ } 8414+ else 8415+ { 8416+ gTRS[1] = gTRS[2] = gTRS[3] = gTRS[5] = gTRS[6] = gTRS[7] = 0.0f; 8417+ gTRS[0] = gTRS[4] = gTRS[8] = 1.0f; 8418+ } 8419+ 8420+ UpdateWarpTransformation(gTRS); 8421+ 8422+ gTRS[9] = frame_number_HR; 8423+ gTRS[10] = ret_code; 8424+ 8425+ jfloatArray bytes = env->NewFloatArray(11); 8426+ if(bytes != 0) 8427+ { 8428+ env->SetFloatArrayRegion(bytes, 0, 11, (jfloat*) gTRS); 8429+ } 8430+ return bytes; 8431+} 8432+ 8433+ 8434+ 8435+JNIEXPORT jfloatArray JNICALL Java_com_android_camera_panorama_Mosaic_setSourceImage( 8436+ JNIEnv* env, jobject thiz, jbyteArray photo_data) 8437+{ 8438+ double t0, t1, time_c; 8439+ t0 = now_ms(); 8440+ 8441+ int ret_code; 8442+ 8443+ if(frame_number_HR<MAX_FRAMES && frame_number_LR<MAX_FRAMES) 8444+ { 8445+ jbyte *pixels = env->GetByteArrayElements(photo_data, 0); 8446+ 8447+ YUV420toYVU24_NEW(tImage[HR][frame_number_HR], (ImageType)pixels, 8448+ tWidth[HR], tHeight[HR]); 8449+ 8450+ env->ReleaseByteArrayElements(photo_data, pixels, 0); 8451+ 8452+ double last_tx = mTx; 8453+ 8454+ t0 = now_ms(); 8455+ GenerateQuarterResImagePlanar(tImage[HR][frame_number_HR], tWidth[HR], 8456+ tHeight[HR], tImage[LR][frame_number_LR]); 8457+ 8458+ 8459+ sem_wait(&gPreviewImage_semaphore); 8460+ decodeYUV444SP(gPreviewImage[LR], tImage[LR][frame_number_LR], 8461+ gPreviewImageWidth[LR], gPreviewImageHeight[LR]); 8462+ sem_post(&gPreviewImage_semaphore); 8463+ 8464+ ret_code = AddFrame(LR, frame_number_LR, gTRS); 8465+ 8466+ if(ret_code == Mosaic::MOSAIC_RET_OK || ret_code == Mosaic::MOSAIC_RET_FEW_INLIERS) 8467+ { 8468+ frame_number_LR++; 8469+ frame_number_HR++; 8470+ } 8471+ 8472+ } 8473+ else 8474+ { 8475+ gTRS[1] = gTRS[2] = gTRS[3] = gTRS[5] = gTRS[6] = gTRS[7] = 0.0f; 8476+ gTRS[0] = gTRS[4] = gTRS[8] = 1.0f; 8477+ } 8478+ 8479+ UpdateWarpTransformation(gTRS); 8480+ 8481+ gTRS[9] = frame_number_HR; 8482+ gTRS[10] = ret_code; 8483+ 8484+ jfloatArray bytes = env->NewFloatArray(11); 8485+ if(bytes != 0) 8486+ { 8487+ env->SetFloatArrayRegion(bytes, 0, 11, (jfloat*) gTRS); 8488+ } 8489+ return bytes; 8490+} 8491+ 8492+JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_setBlendingType( 8493+ JNIEnv* env, jobject thiz, jint type) 8494+{ 8495+ blendingType = int(type); 8496+} 8497+ 8498+JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_setStripType( 8499+ JNIEnv* env, jobject thiz, jint type) 8500+{ 8501+ stripType = int(type); 8502+} 8503+ 8504+JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_reset( 8505+ JNIEnv* env, jobject thiz) 8506+{ 8507+ frame_number_HR = 0; 8508+ frame_number_LR = 0; 8509+ 8510+ gProgress[LR] = 0.0; 8511+ gProgress[HR] = 0.0; 8512+ 8513+ gCancelComputation[LR] = false; 8514+ gCancelComputation[HR] = false; 8515+ 8516+ Init(LR,MAX_FRAMES); 8517+} 8518+ 8519+JNIEXPORT jint JNICALL Java_com_android_camera_panorama_Mosaic_reportProgress( 8520+ JNIEnv* env, jobject thiz, jboolean hires, jboolean cancel_computation) 8521+{ 8522+ if(bool(hires)) 8523+ gCancelComputation[HR] = cancel_computation; 8524+ else 8525+ gCancelComputation[LR] = cancel_computation; 8526+ 8527+ if(bool(hires)) 8528+ return (jint) gProgress[HR]; 8529+ else 8530+ return (jint) gProgress[LR]; 8531+} 8532+ 8533+JNIEXPORT jint JNICALL Java_com_android_camera_panorama_Mosaic_createMosaic( 8534+ JNIEnv* env, jobject thiz, jboolean value) 8535+{ 8536+ high_res = bool(value); 8537+ 8538+ int ret; 8539+ 8540+ if(high_res) 8541+ { 8542+ LOGV("createMosaic() - High-Res Mode"); 8543+ double t0, t1, time_c; 8544+ 8545+ gProgress[HR] = 0.0; 8546+ t0 = now_ms(); 8547+ 8548+ Init(HR, frame_number_HR); 8549+ 8550+ for(int k = 0; k < frame_number_HR; k++) 8551+ { 8552+ if (gCancelComputation[HR]) 8553+ break; 8554+ AddFrame(HR, k, NULL); 8555+ gProgress[HR] += TIME_PERCENT_ALIGN/frame_number_HR; 8556+ } 8557+ 8558+ if (gCancelComputation[HR]) 8559+ { 8560+ ret = Mosaic::MOSAIC_RET_CANCELLED; 8561+ } 8562+ else 8563+ { 8564+ gProgress[HR] = TIME_PERCENT_ALIGN; 8565+ 8566+ t1 = now_ms(); 8567+ time_c = t1 - t0; 8568+ LOGV("AlignAll - %d frames [HR]: %g ms", frame_number_HR, time_c); 8569+ 8570+ ret = Finalize(HR); 8571+ 8572+ gProgress[HR] = 100.0; 8573+ } 8574+ 8575+ high_res = false; 8576+ } 8577+ else 8578+ { 8579+ LOGV("createMosaic() - Low-Res Mode"); 8580+ gProgress[LR] = TIME_PERCENT_ALIGN; 8581+ 8582+ ret = Finalize(LR); 8583+ 8584+ gProgress[LR] = 100.0; 8585+ } 8586+ 8587+ return (jint) ret; 8588+} 8589+ 8590+JNIEXPORT jintArray JNICALL Java_com_android_camera_panorama_Mosaic_getFinalMosaic( 8591+ JNIEnv* env, jobject thiz) 8592+{ 8593+ int y,x; 8594+ int width = mosaicWidth; 8595+ int height = mosaicHeight; 8596+ int imageSize = width * height; 8597+ 8598+ // Convert back to RGB24 8599+ resultBGR = ImageUtils::allocateImage(mosaicWidth, mosaicHeight, 8600+ ImageUtils::IMAGE_TYPE_NUM_CHANNELS); 8601+ ImageUtils::yvu2bgr(resultBGR, resultYVU, mosaicWidth, mosaicHeight); 8602+ 8603+ LOGV("MosBytes: %d, W = %d, H = %d", imageSize, width, height); 8604+ 8605+ int* image = new int[imageSize]; 8606+ int* dims = new int[2]; 8607+ 8608+ for(y=0; y<height; y++) 8609+ { 8610+ for(x=0; x<width; x++) 8611+ { 8612+ image[y*width+x] = (0xFF<<24) | (resultBGR[y*width*3+x*3+2]<<16)| 8613+ (resultBGR[y*width*3+x*3+1]<<8)| (resultBGR[y*width*3+x*3]); 8614+ } 8615+ } 8616+ 8617+ dims[0] = width; 8618+ dims[1] = height; 8619+ 8620+ ImageUtils::freeImage(resultBGR); 8621+ 8622+ jintArray bytes = env->NewIntArray(imageSize+2); 8623+ if (bytes == 0) { 8624+ LOGE("Error in creating the image."); 8625+ delete[] image; 8626+ return 0; 8627+ } 8628+ env->SetIntArrayRegion(bytes, 0, imageSize, (jint*) image); 8629+ env->SetIntArrayRegion(bytes, imageSize, 2, (jint*) dims); 8630+ delete[] image; 8631+ delete[] dims; 8632+ return bytes; 8633+} 8634+ 8635+JNIEXPORT jbyteArray JNICALL Java_com_android_camera_panorama_Mosaic_getFinalMosaicNV21( 8636+ JNIEnv* env, jobject thiz) 8637+{ 8638+ int y,x; 8639+ int width; 8640+ int height; 8641+ 8642+ width = mosaicWidth; 8643+ height = mosaicHeight; 8644+ 8645+ int imageSize = 1.5*width * height; 8646+ 8647+ // Convert YVU to NV21 format in-place 8648+ ImageType V = resultYVU+mosaicWidth*mosaicHeight; 8649+ ImageType U = V+mosaicWidth*mosaicHeight; 8650+ for(int j=0; j<mosaicHeight/2; j++) 8651+ { 8652+ for(int i=0; i<mosaicWidth; i+=2) 8653+ { 8654+ V[j*mosaicWidth+i] = V[(2*j)*mosaicWidth+i]; // V 8655+ V[j*mosaicWidth+i+1] = U[(2*j)*mosaicWidth+i]; // U 8656+ } 8657+ } 8658+ 8659+ LOGV("MosBytes: %d, W = %d, H = %d", imageSize, width, height); 8660+ 8661+ unsigned char* dims = new unsigned char[8]; 8662+ 8663+ dims[0] = (unsigned char)(width >> 24); 8664+ dims[1] = (unsigned char)(width >> 16); 8665+ dims[2] = (unsigned char)(width >> 8); 8666+ dims[3] = (unsigned char)width; 8667+ 8668+ dims[4] = (unsigned char)(height >> 24); 8669+ dims[5] = (unsigned char)(height >> 16); 8670+ dims[6] = (unsigned char)(height >> 8); 8671+ dims[7] = (unsigned char)height; 8672+ 8673+ jbyteArray bytes = env->NewByteArray(imageSize+8); 8674+ if (bytes == 0) { 8675+ LOGE("Error in creating the image."); 8676+ ImageUtils::freeImage(resultYVU); 8677+ return 0; 8678+ } 8679+ env->SetByteArrayRegion(bytes, 0, imageSize, (jbyte*) resultYVU); 8680+ env->SetByteArrayRegion(bytes, imageSize, 8, (jbyte*) dims); 8681+ delete[] dims; 8682+ ImageUtils::freeImage(resultYVU); 8683+ return bytes; 8684+} 8685+ 8686+#ifdef __cplusplus 8687+} 8688+#endif 8689diff --git a/benchmark/feature_stab/db_vlvm/db_bundle.h b/benchmark/feature_stab/db_vlvm/db_bundle.h 8690new file mode 100644 8691index 00000000..e4fb8db2 8692--- /dev/null 8693+++ b/benchmark/feature_stab/db_vlvm/db_bundle.h 8694@@ -0,0 +1,68 @@ 8695+/* 8696+ * Copyright (C) 2011 The Android Open Source Project 8697+ * 8698+ * Licensed under the Apache License, Version 2.0 (the "License"); 8699+ * you may not use this file except in compliance with the License. 8700+ * You may obtain a copy of the License at 8701+ * 8702+ * http://www.apache.org/licenses/LICENSE-2.0 8703+ * 8704+ * Unless required by applicable law or agreed to in writing, software 8705+ * distributed under the License is distributed on an "AS IS" BASIS, 8706+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8707+ * See the License for the specific language governing permissions and 8708+ * limitations under the License. 8709+ */ 8710+ 8711+/* $Id: db_bundle.h,v 1.2 2011/06/17 14:03:30 mbansal Exp $ */ 8712+ 8713+#ifndef DB_BUNDLE_H 8714+#define DB_BUNDLE_H 8715+ 8716+ 8717+/***************************************************************** 8718+* Lean and mean begins here * 8719+*****************************************************************/ 8720+/*! 8721+ * \defgroup LMBundle (LM) Bundle adjustment utilities (a.k.a. Levenberg-Marquardt algorithm) 8722+ */ 8723+/*\{*/ 8724+ 8725+#include "db_utilities.h" 8726+ 8727+/*! 8728+Solve for update dx such that diagmult(1+lambda,transpose(J)%J)%dx= -Jtf 8729+using only upper half of JtJ, destroying lower half below diagonal in the process 8730+dimension is n and d should point to n allocated doubles of scratch memory 8731+*/ 8732+inline void db_Compute_dx(double *dx,double **JtJ,double *min_Jtf,double lambda,double *d,int n) 8733+{ 8734+ int i; 8735+ double opl; 8736+ 8737+ opl=1.0+lambda; 8738+ for(i=0;i<n;i++) d[i]=JtJ[i][i]*opl; 8739+ 8740+ db_CholeskyDecompSeparateDiagonal(JtJ,d,n); 8741+ db_CholeskyBacksub(dx,JtJ,d,n,min_Jtf); 8742+} 8743+ 8744+/*! 8745+Solve for update dx such that diagmult(1+lambda,transpose(J)%J)%dx= -Jtf 8746+using only upper half of JtJ, destroying lower half below diagonal in the process 8747+*/ 8748+inline void db_Compute_dx_3x3(double dx[3],double JtJ[9],const double min_Jtf[3],double lambda) 8749+{ 8750+ double d[3],opl; 8751+ 8752+ opl=1.0+lambda; 8753+ d[0]=JtJ[0]*opl; 8754+ d[1]=JtJ[4]*opl; 8755+ d[2]=JtJ[8]*opl; 8756+ db_CholeskyDecomp3x3SeparateDiagonal(JtJ,d); 8757+ db_CholeskyBacksub3x3(dx,JtJ,d,min_Jtf); 8758+} 8759+ 8760+/*\}*/ 8761+ 8762+#endif /* DB_BUNDLE_H */ 8763diff --git a/benchmark/feature_stab/db_vlvm/db_feature_detection.cpp b/benchmark/feature_stab/db_vlvm/db_feature_detection.cpp 8764new file mode 100644 8765index 00000000..28cb4a78 8766--- /dev/null 8767+++ b/benchmark/feature_stab/db_vlvm/db_feature_detection.cpp 8768@@ -0,0 +1,1770 @@ 8769+/* 8770+ * Copyright (C) 2011 The Android Open Source Project 8771+ * 8772+ * Licensed under the Apache License, Version 2.0 (the "License"); 8773+ * you may not use this file except in compliance with the License. 8774+ * You may obtain a copy of the License at 8775+ * 8776+ * http://www.apache.org/licenses/LICENSE-2.0 8777+ * 8778+ * Unless required by applicable law or agreed to in writing, software 8779+ * distributed under the License is distributed on an "AS IS" BASIS, 8780+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8781+ * See the License for the specific language governing permissions and 8782+ * limitations under the License. 8783+ */ 8784+ 8785+/*$Id: db_feature_detection.cpp,v 1.4 2011/06/17 14:03:30 mbansal Exp $*/ 8786+ 8787+/***************************************************************** 8788+* Lean and mean begins here * 8789+*****************************************************************/ 8790+ 8791+#include "db_utilities.h" 8792+#include "db_feature_detection.h" 8793+#ifdef _VERBOSE_ 8794+#include <iostream> 8795+#endif 8796+#include <float.h> 8797+ 8798+#define DB_SUB_PIXEL 8799+ 8800+#define BORDER 10 // 5 8801+ 8802+float** db_AllocStrengthImage_f(float **im,int w,int h) 8803+{ 8804+ int i,n,aw; 8805+ long c,size; 8806+ float **img,*aim,*p; 8807+ 8808+ /*Determine number of 124 element chunks needed*/ 8809+ n=(db_maxi(1,w-6)+123)/124; 8810+ /*Determine the total allocation width aw*/ 8811+ aw=n*124+8; 8812+ /*Allocate*/ 8813+ size=aw*h+16; 8814+ *im=new float [size]; 8815+ /*Clean up*/ 8816+ p=(*im); 8817+ for(c=0;c<size;c++) p[c]=0.0; 8818+ /*Get a 16 byte aligned pointer*/ 8819+ aim=db_AlignPointer_f(*im,16); 8820+ /*Allocate pointer table*/ 8821+ img=new float* [h]; 8822+ /*Initialize the pointer table*/ 8823+ for(i=0;i<h;i++) 8824+ { 8825+ img[i]=aim+aw*i+1; 8826+ } 8827+ 8828+ return(img); 8829+} 8830+ 8831+void db_FreeStrengthImage_f(float *im,float **img,int h) 8832+{ 8833+ delete [] im; 8834+ delete [] img; 8835+} 8836+ 8837+/*Compute derivatives Ix,Iy for a subrow of img with upper left (i,j) and width chunk_width 8838+Memory references occur one pixel outside the subrow*/ 8839+inline void db_IxIyRow_f(float *Ix,float *Iy,const float * const *img,int i,int j,int chunk_width) 8840+{ 8841+ int c; 8842+ 8843+ for(c=0;c<chunk_width;c++) 8844+ { 8845+ Ix[c]=img[i][j+c-1]-img[i][j+c+1]; 8846+ Iy[c]=img[i-1][j+c]-img[i+1][j+c]; 8847+ } 8848+} 8849+ 8850+/*Compute derivatives Ix,Iy for a subrow of img with upper left (i,j) and width 128 8851+Memory references occur one pixel outside the subrow*/ 8852+inline void db_IxIyRow_u(int *dxx,const unsigned char * const *img,int i,int j,int nc) 8853+{ 8854+#ifdef DB_USE_MMX 8855+ const unsigned char *r1,*r2,*r3; 8856+ 8857+ r1=img[i-1]+j; r2=img[i]+j; r3=img[i+1]+j; 8858+ 8859+ _asm 8860+ { 8861+ mov esi,16 8862+ mov eax,r1 8863+ mov ebx,r2 8864+ mov ecx,r3 8865+ mov edx,dxx 8866+ 8867+ /*Get bitmask into mm7*/ 8868+ mov edi,7F7F7F7Fh 8869+ movd mm7,edi 8870+ punpckldq mm7,mm7 8871+ 8872+loopstart: 8873+ /***************dx part 1-12*********************************/ 8874+ movq mm0,[eax] /*1 Get upper*/ 8875+ pxor mm6,mm6 /*2 Set to zero*/ 8876+ movq mm1,[ecx] /*3 Get lower*/ 8877+ psrlq mm0,1 /*4 Shift*/ 8878+ psrlq mm1,1 /*5 Shift*/ 8879+ pand mm0,mm7 /*6 And*/ 8880+ movq mm2,[ebx-1] /*13 Get left*/ 8881+ pand mm1,mm7 /*7 And*/ 8882+ psubb mm0,mm1 /*8 Subtract*/ 8883+ pxor mm5,mm5 /*14 Set to zero*/ 8884+ movq mm1,mm0 /*9 Copy*/ 8885+ pcmpgtb mm6,mm0 /*10 Create unpack mask*/ 8886+ movq mm3,[ebx+1] /*15 Get right*/ 8887+ punpcklbw mm0,mm6 /*11 Unpack low*/ 8888+ punpckhbw mm1,mm6 /*12 Unpack high*/ 8889+ /***************dy part 13-24*********************************/ 8890+ movq mm4,mm0 /*25 Copy dx*/ 8891+ psrlq mm2,1 /*16 Shift*/ 8892+ pmullw mm0,mm0 /*26 Multiply dx*dx*/ 8893+ psrlq mm3,1 /*17 Shift*/ 8894+ pand mm2,mm7 /*18 And*/ 8895+ pand mm3,mm7 /*19 And*/ 8896+ /*Stall*/ 8897+ psubb mm2,mm3 /*20 Subtract*/ 8898+ /*Stall*/ 8899+ movq mm3,mm2 /*21 Copy*/ 8900+ pcmpgtb mm5,mm2 /*22 Create unpack mask*/ 8901+ punpcklbw mm2,mm5 /*23 Unpack low*/ 8902+ /*Stall*/ 8903+ punpckhbw mm3,mm5 /*24 Unpack high*/ 8904+ /***************dxx dxy dyy low part 25-49*********************************/ 8905+ pmullw mm4,mm2 /*27 Multiply dx*dy*/ 8906+ pmullw mm2,mm2 /*28 Multiply dy*dy*/ 8907+ pxor mm6,mm6 /*29 Set to zero*/ 8908+ movq mm5,mm0 /*30 Copy dx*dx*/ 8909+ pcmpgtw mm6,mm0 /*31 Create unpack mask for dx*dx*/ 8910+ punpcklwd mm0,mm6 /*32 Unpack dx*dx lows*/ 8911+ /*Stall*/ 8912+ punpckhwd mm5,mm6 /*33 Unpack dx*dx highs*/ 8913+ pxor mm6,mm6 /*36 Set to zero*/ 8914+ movq [edx],mm0 /*34 Store dx*dx lows*/ 8915+ movq mm0,mm4 /*37 Copy dx*dy*/ 8916+ movq [edx+8],mm5 /*35 Store dx*dx highs*/ 8917+ pcmpgtw mm6,mm4 /*38 Create unpack mask for dx*dy*/ 8918+ punpcklwd mm4,mm6 /*39 Unpack dx*dy lows*/ 8919+ /*Stall*/ 8920+ punpckhwd mm0,mm6 /*40 Unpack dx*dy highs*/ 8921+ pxor mm6,mm6 /*43 Set to zero*/ 8922+ movq [edx+512],mm4 /*41 Store dx*dy lows*/ 8923+ movq mm5,mm2 /*44 Copy dy*dy*/ 8924+ movq [edx+520],mm0 /*42 Store dx*dy highs*/ 8925+ pcmpgtw mm6,mm2 /*45 Create unpack mask for dy*dy*/ 8926+ punpcklwd mm2,mm6 /*46 Unpack dy*dy lows*/ 8927+ movq mm4,mm1 /*50 Copy dx*/ 8928+ punpckhwd mm5,mm6 /*47 Unpack dy*dy highs*/ 8929+ pmullw mm1,mm1 /*51 Multiply dx*dx*/ 8930+ movq [edx+1024],mm2 /*48 Store dy*dy lows*/ 8931+ pmullw mm4,mm3 /*52 Multiply dx*dy*/ 8932+ movq [edx+1032],mm5 /*49 Store dy*dy highs*/ 8933+ /***************dxx dxy dyy high part 50-79*********************************/ 8934+ pmullw mm3,mm3 /*53 Multiply dy*dy*/ 8935+ pxor mm6,mm6 /*54 Set to zero*/ 8936+ movq mm5,mm1 /*55 Copy dx*dx*/ 8937+ pcmpgtw mm6,mm1 /*56 Create unpack mask for dx*dx*/ 8938+ pxor mm2,mm2 /*61 Set to zero*/ 8939+ punpcklwd mm1,mm6 /*57 Unpack dx*dx lows*/ 8940+ movq mm0,mm4 /*62 Copy dx*dy*/ 8941+ punpckhwd mm5,mm6 /*58 Unpack dx*dx highs*/ 8942+ pcmpgtw mm2,mm4 /*63 Create unpack mask for dx*dy*/ 8943+ movq [edx+16],mm1 /*59 Store dx*dx lows*/ 8944+ punpcklwd mm4,mm2 /*64 Unpack dx*dy lows*/ 8945+ movq [edx+24],mm5 /*60 Store dx*dx highs*/ 8946+ punpckhwd mm0,mm2 /*65 Unpack dx*dy highs*/ 8947+ movq [edx+528],mm4 /*66 Store dx*dy lows*/ 8948+ pxor mm6,mm6 /*68 Set to zero*/ 8949+ movq [edx+536],mm0 /*67 Store dx*dy highs*/ 8950+ movq mm5,mm3 /*69 Copy dy*dy*/ 8951+ pcmpgtw mm6,mm3 /*70 Create unpack mask for dy*dy*/ 8952+ add eax,8 /*75*/ 8953+ punpcklwd mm3,mm6 /*71 Unpack dy*dy lows*/ 8954+ add ebx,8 /*76*/ 8955+ punpckhwd mm5,mm6 /*72 Unpack dy*dy highs*/ 8956+ add ecx,8 /*77*/ 8957+ movq [edx+1040],mm3 /*73 Store dy*dy lows*/ 8958+ /*Stall*/ 8959+ movq [edx+1048],mm5 /*74 Store dy*dy highs*/ 8960+ /*Stall*/ 8961+ add edx,32 /*78*/ 8962+ dec esi /*79*/ 8963+ jnz loopstart 8964+ 8965+ emms 8966+ } 8967+ 8968+#else 8969+ int c; 8970+ int Ix,Iy; 8971+ 8972+ for(c=0;c<nc;c++) 8973+ { 8974+ Ix=(img[i][j+c-1]-img[i][j+c+1])>>1; 8975+ Iy=(img[i-1][j+c]-img[i+1][j+c])>>1; 8976+ dxx[c]=Ix*Ix; 8977+ dxx[c+128]=Ix*Iy; 8978+ dxx[c+256]=Iy*Iy; 8979+ } 8980+#endif /*DB_USE_MMX*/ 8981+} 8982+ 8983+/*Filter vertically five rows of derivatives of length chunk_width into gxx,gxy,gyy*/ 8984+inline void db_gxx_gxy_gyy_row_f(float *gxx,float *gxy,float *gyy,int chunk_width, 8985+ float *Ix0,float *Ix1,float *Ix2,float *Ix3,float *Ix4, 8986+ float *Iy0,float *Iy1,float *Iy2,float *Iy3,float *Iy4) 8987+{ 8988+ int c; 8989+ float dx,dy; 8990+ float Ixx0,Ixy0,Iyy0,Ixx1,Ixy1,Iyy1,Ixx2,Ixy2,Iyy2,Ixx3,Ixy3,Iyy3,Ixx4,Ixy4,Iyy4; 8991+ 8992+ for(c=0;c<chunk_width;c++) 8993+ { 8994+ dx=Ix0[c]; 8995+ dy=Iy0[c]; 8996+ Ixx0=dx*dx; 8997+ Ixy0=dx*dy; 8998+ Iyy0=dy*dy; 8999+ 9000+ dx=Ix1[c]; 9001+ dy=Iy1[c]; 9002+ Ixx1=dx*dx; 9003+ Ixy1=dx*dy; 9004+ Iyy1=dy*dy; 9005+ 9006+ dx=Ix2[c]; 9007+ dy=Iy2[c]; 9008+ Ixx2=dx*dx; 9009+ Ixy2=dx*dy; 9010+ Iyy2=dy*dy; 9011+ 9012+ dx=Ix3[c]; 9013+ dy=Iy3[c]; 9014+ Ixx3=dx*dx; 9015+ Ixy3=dx*dy; 9016+ Iyy3=dy*dy; 9017+ 9018+ dx=Ix4[c]; 9019+ dy=Iy4[c]; 9020+ Ixx4=dx*dx; 9021+ Ixy4=dx*dy; 9022+ Iyy4=dy*dy; 9023+ 9024+ /*Filter vertically*/ 9025+ gxx[c]=Ixx0+Ixx1*4.0f+Ixx2*6.0f+Ixx3*4.0f+Ixx4; 9026+ gxy[c]=Ixy0+Ixy1*4.0f+Ixy2*6.0f+Ixy3*4.0f+Ixy4; 9027+ gyy[c]=Iyy0+Iyy1*4.0f+Iyy2*6.0f+Iyy3*4.0f+Iyy4; 9028+ } 9029+} 9030+ 9031+/*Filter vertically five rows of derivatives of length 128 into gxx,gxy,gyy*/ 9032+inline void db_gxx_gxy_gyy_row_s(int *g,int *d0,int *d1,int *d2,int *d3,int *d4,int nc) 9033+{ 9034+#ifdef DB_USE_MMX 9035+ int c; 9036+ 9037+ _asm 9038+ { 9039+ mov c,64 9040+ mov eax,d0 9041+ mov ebx,d1 9042+ mov ecx,d2 9043+ mov edx,d3 9044+ mov edi,d4 9045+ mov esi,g 9046+ 9047+loopstart: 9048+ /***************dxx part 1-14*********************************/ 9049+ movq mm0,[eax] /*1 Get dxx0*/ 9050+ /*Stall*/ 9051+ movq mm1,[ebx] /*2 Get dxx1*/ 9052+ /*Stall*/ 9053+ movq mm2,[ecx] /*5 Get dxx2*/ 9054+ pslld mm1,2 /*3 Shift dxx1*/ 9055+ movq mm3,[edx] /*10 Get dxx3*/ 9056+ paddd mm0,mm1 /*4 Accumulate dxx1*/ 9057+ movq mm4,[eax+512] /*15 Get dxy0*/ 9058+ pslld mm2,1 /*6 Shift dxx2 1*/ 9059+ paddd mm0,mm2 /*7 Accumulate dxx2 1*/ 9060+ pslld mm2,1 /*8 Shift dxx2 2*/ 9061+ movq mm5,[ebx+512] /*16 Get dxy1*/ 9062+ paddd mm0,mm2 /*9 Accumulate dxx2 2*/ 9063+ pslld mm3,2 /*11 Shift dxx3*/ 9064+ /*Stall*/ 9065+ paddd mm0,mm3 /*12 Accumulate dxx3*/ 9066+ pslld mm5,2 /*17 Shift dxy1*/ 9067+ paddd mm0,[edi] /*13 Accumulate dxx4*/ 9068+ paddd mm4,mm5 /*18 Accumulate dxy1*/ 9069+ movq mm6,[ecx+512] /*19 Get dxy2*/ 9070+ /*Stall*/ 9071+ movq [esi],mm0 /*14 Store dxx sums*/ 9072+ /***************dxy part 15-28*********************************/ 9073+ pslld mm6,1 /*20 Shift dxy2 1*/ 9074+ paddd mm4,mm6 /*21 Accumulate dxy2 1*/ 9075+ pslld mm6,1 /*22 Shift dxy2 2*/ 9076+ movq mm0,[eax+1024] /*29 Get dyy0*/ 9077+ paddd mm4,mm6 /*23 Accumulate dxy2 2*/ 9078+ movq mm7,[edx+512] /*24 Get dxy3*/ 9079+ pslld mm7,2 /*25 Shift dxy3*/ 9080+ movq mm1,[ebx+1024] /*30 Get dyy1*/ 9081+ paddd mm4,mm7 /*26 Accumulate dxy3*/ 9082+ paddd mm4,[edi+512] /*27 Accumulate dxy4*/ 9083+ pslld mm1,2 /*31 Shift dyy1*/ 9084+ movq mm2,[ecx+1024] /*33 Get dyy2*/ 9085+ paddd mm0,mm1 /*32 Accumulate dyy1*/ 9086+ movq [esi+512],mm4 /*28 Store dxy sums*/ 9087+ pslld mm2,1 /*34 Shift dyy2 1*/ 9088+ /***************dyy part 29-49*********************************/ 9089+ 9090+ 9091+ movq mm3,[edx+1024] /*38 Get dyy3*/ 9092+ paddd mm0,mm2 /*35 Accumulate dyy2 1*/ 9093+ paddd mm0,[edi+1024] /*41 Accumulate dyy4*/ 9094+ pslld mm2,1 /*36 Shift dyy2 2*/ 9095+ paddd mm0,mm2 /*37 Accumulate dyy2 2*/ 9096+ pslld mm3,2 /*39 Shift dyy3*/ 9097+ paddd mm0,mm3 /*40 Accumulate dyy3*/ 9098+ add eax,8 /*43*/ 9099+ add ebx,8 /*44*/ 9100+ add ecx,8 /*45*/ 9101+ movq [esi+1024],mm0 /*42 Store dyy sums*/ 9102+ /*Stall*/ 9103+ add edx,8 /*46*/ 9104+ add edi,8 /*47*/ 9105+ add esi,8 /*48*/ 9106+ dec c /*49*/ 9107+ jnz loopstart 9108+ 9109+ emms 9110+ } 9111+ 9112+#else 9113+ int c,dd; 9114+ 9115+ for(c=0;c<nc;c++) 9116+ { 9117+ /*Filter vertically*/ 9118+ dd=d2[c]; 9119+ g[c]=d0[c]+(d1[c]<<2)+(dd<<2)+(dd<<1)+(d3[c]<<2)+d4[c]; 9120+ 9121+ dd=d2[c+128]; 9122+ g[c+128]=d0[c+128]+(d1[c+128]<<2)+(dd<<2)+(dd<<1)+(d3[c+128]<<2)+d4[c+128]; 9123+ 9124+ dd=d2[c+256]; 9125+ g[c+256]=d0[c+256]+(d1[c+256]<<2)+(dd<<2)+(dd<<1)+(d3[c+256]<<2)+d4[c+256]; 9126+ } 9127+#endif /*DB_USE_MMX*/ 9128+} 9129+ 9130+/*Filter horizontally the three rows gxx,gxy,gyy into the strength subrow starting at i,j 9131+and with width chunk_width. gxx,gxy and gyy are assumed to be four pixels wider than chunk_width 9132+and starting at (i,j-2)*/ 9133+inline void db_HarrisStrength_row_f(float **s,float *gxx,float *gxy,float *gyy,int i,int j,int chunk_width) 9134+{ 9135+ float Gxx,Gxy,Gyy,det,trc; 9136+ int c; 9137+ 9138+ for(c=0;c<chunk_width;c++) 9139+ { 9140+ Gxx=gxx[c]+gxx[c+1]*4.0f+gxx[c+2]*6.0f+gxx[c+3]*4.0f+gxx[c+4]; 9141+ Gxy=gxy[c]+gxy[c+1]*4.0f+gxy[c+2]*6.0f+gxy[c+3]*4.0f+gxy[c+4]; 9142+ Gyy=gyy[c]+gyy[c+1]*4.0f+gyy[c+2]*6.0f+gyy[c+3]*4.0f+gyy[c+4]; 9143+ 9144+ det=Gxx*Gyy-Gxy*Gxy; 9145+ trc=Gxx+Gyy; 9146+ s[i][j+c]=det-0.06f*trc*trc; 9147+ } 9148+} 9149+ 9150+/*Filter g of length 128 in place with 14641. Output is shifted two steps 9151+and of length 124*/ 9152+inline void db_Filter14641_128_i(int *g,int nc) 9153+{ 9154+#ifdef DB_USE_MMX 9155+ int mask; 9156+ 9157+ mask=0xFFFFFFFF; 9158+ _asm 9159+ { 9160+ mov esi,31 9161+ mov eax,g 9162+ 9163+ /*Get bitmask 00000000FFFFFFFF into mm7*/ 9164+ movd mm7,mask 9165+ 9166+ /*Warming iteration one 1-16********************/ 9167+ movq mm6,[eax] /*1 Load new data*/ 9168+ paddd mm0,mm6 /*2 Add 1* behind two steps*/ 9169+ movq mm2,mm6 /*3 Start with 1* in front two steps*/ 9170+ pslld mm6,1 /*4*/ 9171+ paddd mm1,mm6 /*5 Add 2* same place*/ 9172+ pslld mm6,1 /*6*/ 9173+ paddd mm1,mm6 /*7 Add 4* same place*/ 9174+ pshufw mm6,mm6,4Eh /*8 Swap the two double-words using bitmask 01001110=4Eh*/ 9175+ paddd mm1,mm6 /*9 Add 4* swapped*/ 9176+ movq mm5,mm6 /*10 Copy*/ 9177+ pand mm6,mm7 /*11 Get low double-word only*/ 9178+ paddd mm2,mm6 /*12 Add 4* in front one step*/ 9179+ pxor mm6,mm5 /*13 Get high double-word only*/ 9180+ paddd mm0,mm6 /*14 Add 4* behind one step*/ 9181+ movq mm0,mm1 /*15 Shift along*/ 9182+ movq mm1,mm2 /*16 Shift along*/ 9183+ /*Warming iteration two 17-32********************/ 9184+ movq mm4,[eax+8] /*17 Load new data*/ 9185+ paddd mm0,mm4 /*18 Add 1* behind two steps*/ 9186+ movq mm2,mm4 /*19 Start with 1* in front two steps*/ 9187+ pslld mm4,1 /*20*/ 9188+ paddd mm1,mm4 /*21 Add 2* same place*/ 9189+ pslld mm4,1 /*22*/ 9190+ paddd mm1,mm4 /*23 Add 4* same place*/ 9191+ pshufw mm4,mm4,4Eh /*24 Swap the two double-words using bitmask 01001110=4Eh*/ 9192+ paddd mm1,mm4 /*25 Add 4* swapped*/ 9193+ movq mm3,mm4 /*26 Copy*/ 9194+ pand mm4,mm7 /*27 Get low double-word only*/ 9195+ paddd mm2,mm4 /*28 Add 4* in front one step*/ 9196+ pxor mm4,mm3 /*29 Get high double-word only*/ 9197+ paddd mm0,mm4 /*30 Add 4* behind one step*/ 9198+ movq mm0,mm1 /*31 Shift along*/ 9199+ movq mm1,mm2 /*32 Shift along*/ 9200+ 9201+ /*Loop********************/ 9202+loopstart: 9203+ /*First part of loop 33-47********/ 9204+ movq mm6,[eax+16] /*33 Load new data*/ 9205+ /*Stall*/ 9206+ paddd mm0,mm6 /*34 Add 1* behind two steps*/ 9207+ movq mm2,mm6 /*35 Start with 1* in front two steps*/ 9208+ movq mm4,[eax+24] /*48 Load new data*/ 9209+ pslld mm6,1 /*36*/ 9210+ paddd mm1,mm6 /*37 Add 2* same place*/ 9211+ pslld mm6,1 /*38*/ 9212+ paddd mm1,mm6 /*39 Add 4* same place*/ 9213+ pshufw mm6,mm6,4Eh /*40 Swap the two double-words using bitmask 01001110=4Eh*/ 9214+ paddd mm1,mm4 /*49 Add 1* behind two steps*/ 9215+ movq mm5,mm6 /*41 Copy*/ 9216+ paddd mm1,mm6 /*42 Add 4* swapped*/ 9217+ pand mm6,mm7 /*43 Get low double-word only*/ 9218+ paddd mm2,mm6 /*44 Add 4* in front one step*/ 9219+ pxor mm6,mm5 /*45 Get high double-word only*/ 9220+ paddd mm0,mm6 /*46 Add 4* behind one step*/ 9221+ movq mm6,mm4 /*50a Copy*/ 9222+ pslld mm4,1 /*51*/ 9223+ /*Stall*/ 9224+ movq [eax],mm0 /*47 Store result two steps behind*/ 9225+ /*Second part of loop 48-66********/ 9226+ movq mm0,mm6 /*50b Start with 1* in front two steps*/ 9227+ paddd mm2,mm4 /*52 Add 2* same place*/ 9228+ pslld mm4,1 /*53*/ 9229+ paddd mm2,mm4 /*54 Add 4* same place*/ 9230+ pshufw mm4,mm4,4Eh /*55 Swap the two double-words using bitmask 01001110=4Eh*/ 9231+ paddd mm2,mm4 /*56 Add 4* swapped*/ 9232+ movq mm3,mm4 /*57 Copy*/ 9233+ pand mm4,mm7 /*58 Get low double-word only*/ 9234+ /*Stall*/ 9235+ paddd mm0,mm4 /*59 Add 4* in front one step*/ 9236+ pxor mm4,mm3 /*60 Get high double-word only*/ 9237+ paddd mm1,mm4 /*61 Add 4* behind one step*/ 9238+ add eax,16 /*65*/ 9239+ dec esi /*66*/ 9240+ /*Stall*/ 9241+ movq [eax-8],mm1 /*62 Store result two steps behind*/ 9242+ movq mm1,mm0 /*63 Shift along*/ 9243+ movq mm0,mm2 /*64 Shift along*/ 9244+ jnz loopstart 9245+ 9246+ emms 9247+ } 9248+ 9249+#else 9250+ int c; 9251+ 9252+ for(c=0;c<nc-4;c++) 9253+ { 9254+ g[c]=g[c]+(g[c+1]<<2)+(g[c+2]<<2)+(g[c+2]<<1)+(g[c+3]<<2)+g[c+4]; 9255+ } 9256+#endif /*DB_USE_MMX*/ 9257+} 9258+ 9259+/*Filter horizontally the three rows gxx,gxy,gyy of length 128 into the strength subrow s 9260+of length 124. gxx,gxy and gyy are assumed to be starting at (i,j-2) if s[i][j] is sought. 9261+s should be 16 byte aligned*/ 9262+inline void db_HarrisStrength_row_s(float *s,int *gxx,int *gxy,int *gyy,int nc) 9263+{ 9264+ float k; 9265+ 9266+ k=0.06f; 9267+ 9268+ db_Filter14641_128_i(gxx,nc); 9269+ db_Filter14641_128_i(gxy,nc); 9270+ db_Filter14641_128_i(gyy,nc); 9271+ 9272+#ifdef DB_USE_SIMD 9273+ 9274+ 9275+ _asm 9276+ { 9277+ mov esi,15 9278+ mov eax,gxx 9279+ mov ebx,gxy 9280+ mov ecx,gyy 9281+ mov edx,s 9282+ 9283+ /*broadcast k to all positions of xmm7*/ 9284+ movss xmm7,k 9285+ shufps xmm7,xmm7,0 9286+ 9287+ /*****Warm up 1-10**************************************/ 9288+ cvtpi2ps xmm0,[eax+8] /*1 Convert two integers into floating point of low double-word*/ 9289+ /*Stall*/ 9290+ cvtpi2ps xmm1,[ebx+8] /*4 Convert two integers into floating point of low double-word*/ 9291+ movlhps xmm0,xmm0 /*2 Move them to the high double-word*/ 9292+ cvtpi2ps xmm2,[ecx+8] /*7 Convert two integers into floating point of low double-word*/ 9293+ movlhps xmm1,xmm1 /*5 Move them to the high double-word*/ 9294+ cvtpi2ps xmm0,[eax] /*3 Convert two integers into floating point of low double-word*/ 9295+ movlhps xmm2,xmm2 /*8 Move them to the high double-word*/ 9296+ cvtpi2ps xmm1,[ebx] /*6 Convert two integers into floating point of low double-word*/ 9297+ movaps xmm3,xmm0 /*10 Copy Cxx*/ 9298+ cvtpi2ps xmm2,[ecx] /*9 Convert two integers into floating point of low double-word*/ 9299+ /*Stall*/ 9300+loopstart: 9301+ /*****First part of loop 11-18***********************/ 9302+ mulps xmm0,xmm2 /*11 Multiply to get Gxx*Gyy*/ 9303+ addps xmm2,xmm3 /*12 Add to get Gxx+Gyy*/ 9304+ cvtpi2ps xmm4,[eax+24] /*19 Convert two integers into floating point of low double-word*/ 9305+ mulps xmm1,xmm1 /*13 Multiply to get Gxy*Gxy*/ 9306+ mulps xmm2,xmm2 /*14 Multiply to get (Gxx+Gyy)*(Gxx+Gyy)*/ 9307+ movlhps xmm4,xmm4 /*20 Move them to the high double-word*/ 9308+ cvtpi2ps xmm4,[eax+16] /*21 Convert two integers into floating point of low double-word*/ 9309+ /*Stall*/ 9310+ subps xmm0,xmm1 /*15 Subtract to get Gxx*Gyy-Gxy*Gxy*/ 9311+ mulps xmm2,xmm7 /*16 Multiply to get k*(Gxx+Gyy)*(Gxx+Gyy)*/ 9312+ cvtpi2ps xmm5,[ebx+24] /*22 Convert two integers into floating point of low double-word*/ 9313+ /*Stall*/ 9314+ movlhps xmm5,xmm5 /*23 Move them to the high double-word*/ 9315+ /*Stall*/ 9316+ cvtpi2ps xmm5,[ebx+16] /*24 Convert two integers into floating point of low double-word*/ 9317+ subps xmm0,xmm2 /*17 Subtract to get Gxx*Gyy-Gxy*Gxy-k*(Gxx+Gyy)*(Gxx+Gyy)*/ 9318+ cvtpi2ps xmm6,[ecx+24] /*25 Convert two integers into floating point of low double-word*/ 9319+ /*Stall*/ 9320+ movaps [edx],xmm0 /*18 Store*/ 9321+ /*****Second part of loop 26-40***********************/ 9322+ movlhps xmm6,xmm6 /*26 Move them to the high double-word*/ 9323+ cvtpi2ps xmm6,[ecx+16] /*27 Convert two integers into floating point of low double-word*/ 9324+ movaps xmm3,xmm4 /*28 Copy Cxx*/ 9325+ mulps xmm4,xmm6 /*29 Multiply to get Gxx*Gyy*/ 9326+ addps xmm6,xmm3 /*30 Add to get Gxx+Gyy*/ 9327+ cvtpi2ps xmm0,[eax+40] /*(1 Next) Convert two integers into floating point of low double-word*/ 9328+ mulps xmm5,xmm5 /*31 Multiply to get Gxy*Gxy*/ 9329+ cvtpi2ps xmm1,[ebx+40] /*(4 Next) Convert two integers into floating point of low double-word*/ 9330+ mulps xmm6,xmm6 /*32 Multiply to get (Gxx+Gyy)*(Gxx+Gyy)*/ 9331+ cvtpi2ps xmm2,[ecx+40] /*(7 Next) Convert two integers into floating point of low double-word*/ 9332+ movlhps xmm0,xmm0 /*(2 Next) Move them to the high double-word*/ 9333+ subps xmm4,xmm5 /*33 Subtract to get Gxx*Gyy-Gxy*Gxy*/ 9334+ movlhps xmm1,xmm1 /*(5 Next) Move them to the high double-word*/ 9335+ cvtpi2ps xmm0,[eax+32] /*(3 Next)Convert two integers into floating point of low double-word*/ 9336+ mulps xmm6,xmm7 /*34 Multiply to get k*(Gxx+Gyy)*(Gxx+Gyy)*/ 9337+ cvtpi2ps xmm1,[ebx+32] /*(6 Next) Convert two integers into floating point of low double-word*/ 9338+ movlhps xmm2,xmm2 /*(8 Next) Move them to the high double-word*/ 9339+ movaps xmm3,xmm0 /*(10 Next) Copy Cxx*/ 9340+ add eax,32 /*37*/ 9341+ subps xmm4,xmm6 /*35 Subtract to get Gxx*Gyy-Gxy*Gxy-k*(Gxx+Gyy)*(Gxx+Gyy)*/ 9342+ add ebx,32 /*38*/ 9343+ cvtpi2ps xmm2,[ecx+32] /*(9 Next) Convert two integers into floating point of low double-word*/ 9344+ /*Stall*/ 9345+ movaps [edx+16],xmm4 /*36 Store*/ 9346+ /*Stall*/ 9347+ add ecx,32 /*39*/ 9348+ add edx,32 /*40*/ 9349+ dec esi /*41*/ 9350+ jnz loopstart 9351+ 9352+ /****Cool down***************/ 9353+ mulps xmm0,xmm2 /*Multiply to get Gxx*Gyy*/ 9354+ addps xmm2,xmm3 /*Add to get Gxx+Gyy*/ 9355+ mulps xmm1,xmm1 /*Multiply to get Gxy*Gxy*/ 9356+ mulps xmm2,xmm2 /*Multiply to get (Gxx+Gyy)*(Gxx+Gyy)*/ 9357+ subps xmm0,xmm1 /*Subtract to get Gxx*Gyy-Gxy*Gxy*/ 9358+ mulps xmm2,xmm7 /*Multiply to get k*(Gxx+Gyy)*(Gxx+Gyy)*/ 9359+ subps xmm0,xmm2 /*Subtract to get Gxx*Gyy-Gxy*Gxy-k*(Gxx+Gyy)*(Gxx+Gyy)*/ 9360+ movaps [edx],xmm0 /*Store*/ 9361+ } 9362+ 9363+#else 9364+ float Gxx,Gxy,Gyy,det,trc; 9365+ int c; 9366+ 9367+ //for(c=0;c<124;c++) 9368+ for(c=0;c<nc-4;c++) 9369+ { 9370+ Gxx=(float)gxx[c]; 9371+ Gxy=(float)gxy[c]; 9372+ Gyy=(float)gyy[c]; 9373+ 9374+ det=Gxx*Gyy-Gxy*Gxy; 9375+ trc=Gxx+Gyy; 9376+ s[c]=det-k*trc*trc; 9377+ } 9378+#endif /*DB_USE_SIMD*/ 9379+} 9380+ 9381+/*Compute the Harris corner strength of the chunk [left,top,right,bottom] of img and 9382+store it into the corresponding region of s. left and top have to be at least 3 and 9383+right and bottom have to be at most width-4,height-4*/ 9384+inline void db_HarrisStrengthChunk_f(float **s,const float * const *img,int left,int top,int right,int bottom, 9385+ /*temp should point to at least 9386+ 13*(right-left+5) of allocated memory*/ 9387+ float *temp) 9388+{ 9389+ float *Ix[5],*Iy[5]; 9390+ float *gxx,*gxy,*gyy; 9391+ int i,chunk_width,chunk_width_p4; 9392+ 9393+ chunk_width=right-left+1; 9394+ chunk_width_p4=chunk_width+4; 9395+ gxx=temp; 9396+ gxy=gxx+chunk_width_p4; 9397+ gyy=gxy+chunk_width_p4; 9398+ for(i=0;i<5;i++) 9399+ { 9400+ Ix[i]=gyy+chunk_width_p4+(2*i*chunk_width_p4); 9401+ Iy[i]=Ix[i]+chunk_width_p4; 9402+ } 9403+ 9404+ /*Fill four rows of the wrap-around derivative buffers*/ 9405+ for(i=top-2;i<top+2;i++) db_IxIyRow_f(Ix[i%5],Iy[i%5],img,i,left-2,chunk_width_p4); 9406+ 9407+ /*For each output row*/ 9408+ for(i=top;i<=bottom;i++) 9409+ { 9410+ /*Step the derivative buffers*/ 9411+ db_IxIyRow_f(Ix[(i+2)%5],Iy[(i+2)%5],img,(i+2),left-2,chunk_width_p4); 9412+ 9413+ /*Filter Ix2,IxIy,Iy2 vertically into gxx,gxy,gyy*/ 9414+ db_gxx_gxy_gyy_row_f(gxx,gxy,gyy,chunk_width_p4, 9415+ Ix[(i-2)%5],Ix[(i-1)%5],Ix[i%5],Ix[(i+1)%5],Ix[(i+2)%5], 9416+ Iy[(i-2)%5],Iy[(i-1)%5],Iy[i%5],Iy[(i+1)%5],Iy[(i+2)%5]); 9417+ 9418+ /*Filter gxx,gxy,gyy horizontally and compute corner response s*/ 9419+ db_HarrisStrength_row_f(s,gxx,gxy,gyy,i,left,chunk_width); 9420+ } 9421+} 9422+ 9423+/*Compute the Harris corner strength of the chunk [left,top,left+123,bottom] of img and 9424+store it into the corresponding region of s. left and top have to be at least 3 and 9425+right and bottom have to be at most width-4,height-4. The left of the region in s should 9426+be 16 byte aligned*/ 9427+inline void db_HarrisStrengthChunk_u(float **s,const unsigned char * const *img,int left,int top,int bottom, 9428+ /*temp should point to at least 9429+ 18*128 of allocated memory*/ 9430+ int *temp, int nc) 9431+{ 9432+ int *Ixx[5],*Ixy[5],*Iyy[5]; 9433+ int *gxx,*gxy,*gyy; 9434+ int i; 9435+ 9436+ gxx=temp; 9437+ gxy=gxx+128; 9438+ gyy=gxy+128; 9439+ for(i=0;i<5;i++) 9440+ { 9441+ Ixx[i]=gyy+(3*i+1)*128; 9442+ Ixy[i]=gyy+(3*i+2)*128; 9443+ Iyy[i]=gyy+(3*i+3)*128; 9444+ } 9445+ 9446+ /*Fill four rows of the wrap-around derivative buffers*/ 9447+ for(i=top-2;i<top+2;i++) db_IxIyRow_u(Ixx[i%5],img,i,left-2,nc); 9448+ 9449+ /*For each output row*/ 9450+ for(i=top;i<=bottom;i++) 9451+ { 9452+ /*Step the derivative buffers*/ 9453+ db_IxIyRow_u(Ixx[(i+2)%5],img,(i+2),left-2,nc); 9454+ 9455+ /*Filter Ix2,IxIy,Iy2 vertically into gxx,gxy,gyy*/ 9456+ db_gxx_gxy_gyy_row_s(gxx,Ixx[(i-2)%5],Ixx[(i-1)%5],Ixx[i%5],Ixx[(i+1)%5],Ixx[(i+2)%5],nc); 9457+ 9458+ /*Filter gxx,gxy,gyy horizontally and compute corner response s*/ 9459+ db_HarrisStrength_row_s(s[i]+left,gxx,gxy,gyy,nc); 9460+ } 9461+ 9462+} 9463+ 9464+/*Compute Harris corner strength of img. Strength is returned for the region 9465+with (3,3) as upper left and (w-4,h-4) as lower right, positioned in the 9466+same place in s. In other words,image should be at least 7 pixels wide and 7 pixels high 9467+for a meaningful result*/ 9468+void db_HarrisStrength_f(float **s,const float * const *img,int w,int h, 9469+ /*temp should point to at least 9470+ 13*(chunk_width+4) of allocated memory*/ 9471+ float *temp, 9472+ int chunk_width) 9473+{ 9474+ int x,next_x,last,right; 9475+ 9476+ last=w-4; 9477+ for(x=3;x<=last;x=next_x) 9478+ { 9479+ next_x=x+chunk_width; 9480+ right=next_x-1; 9481+ if(right>last) right=last; 9482+ /*Compute the Harris strength of a chunk*/ 9483+ db_HarrisStrengthChunk_f(s,img,x,3,right,h-4,temp); 9484+ } 9485+} 9486+ 9487+/*Compute Harris corner strength of img. Strength is returned for the region 9488+with (3,3) as upper left and (w-4,h-4) as lower right, positioned in the 9489+same place in s. In other words,image should be at least 7 pixels wide and 7 pixels high 9490+for a meaningful result.Moreover, the image should be overallocated by 256 bytes. 9491+s[i][3] should by 16 byte aligned for any i*/ 9492+void db_HarrisStrength_u(float **s, const unsigned char * const *img,int w,int h, 9493+ /*temp should point to at least 9494+ 18*128 of allocated memory*/ 9495+ int *temp) 9496+{ 9497+ int x,next_x,last; 9498+ int nc; 9499+ 9500+ last=w-4; 9501+ for(x=3;x<=last;x=next_x) 9502+ { 9503+ next_x=x+124; 9504+ 9505+ // mayban: to revert to the original full chunks state, change the line below to: nc = 128; 9506+ nc = db_mini(128,last-x+1); 9507+ //nc = 128; 9508+ 9509+ /*Compute the Harris strength of a chunk*/ 9510+ db_HarrisStrengthChunk_u(s,img,x,3,h-4,temp,nc); 9511+ } 9512+} 9513+ 9514+inline float db_Max_128Aligned16_f(float *v) 9515+{ 9516+#ifdef DB_USE_SIMD 9517+ float back; 9518+ 9519+ _asm 9520+ { 9521+ mov eax,v 9522+ 9523+ /*Chunk1*/ 9524+ movaps xmm0,[eax] 9525+ movaps xmm1,[eax+16] 9526+ movaps xmm2,[eax+32] 9527+ movaps xmm3,[eax+48] 9528+ movaps xmm4,[eax+64] 9529+ movaps xmm5,[eax+80] 9530+ movaps xmm6,[eax+96] 9531+ movaps xmm7,[eax+112] 9532+ 9533+ /*Chunk2*/ 9534+ maxps xmm0,[eax+128] 9535+ maxps xmm1,[eax+144] 9536+ maxps xmm2,[eax+160] 9537+ maxps xmm3,[eax+176] 9538+ maxps xmm4,[eax+192] 9539+ maxps xmm5,[eax+208] 9540+ maxps xmm6,[eax+224] 9541+ maxps xmm7,[eax+240] 9542+ 9543+ /*Chunk3*/ 9544+ maxps xmm0,[eax+256] 9545+ maxps xmm1,[eax+272] 9546+ maxps xmm2,[eax+288] 9547+ maxps xmm3,[eax+304] 9548+ maxps xmm4,[eax+320] 9549+ maxps xmm5,[eax+336] 9550+ maxps xmm6,[eax+352] 9551+ maxps xmm7,[eax+368] 9552+ 9553+ /*Chunk4*/ 9554+ maxps xmm0,[eax+384] 9555+ maxps xmm1,[eax+400] 9556+ maxps xmm2,[eax+416] 9557+ maxps xmm3,[eax+432] 9558+ maxps xmm4,[eax+448] 9559+ maxps xmm5,[eax+464] 9560+ maxps xmm6,[eax+480] 9561+ maxps xmm7,[eax+496] 9562+ 9563+ /*Collect*/ 9564+ maxps xmm0,xmm1 9565+ maxps xmm2,xmm3 9566+ maxps xmm4,xmm5 9567+ maxps xmm6,xmm7 9568+ maxps xmm0,xmm2 9569+ maxps xmm4,xmm6 9570+ maxps xmm0,xmm4 9571+ movhlps xmm1,xmm0 9572+ maxps xmm0,xmm1 9573+ shufps xmm1,xmm0,1 9574+ maxps xmm0,xmm1 9575+ movss back,xmm0 9576+ } 9577+ 9578+ return(back); 9579+#else 9580+ float val,max_val; 9581+ float *p,*stop_p; 9582+ max_val=v[0]; 9583+ for(p=v+1,stop_p=v+128;p!=stop_p;) 9584+ { 9585+ val= *p++; 9586+ if(val>max_val) max_val=val; 9587+ } 9588+ return(max_val); 9589+#endif /*DB_USE_SIMD*/ 9590+} 9591+ 9592+inline float db_Max_64Aligned16_f(float *v) 9593+{ 9594+#ifdef DB_USE_SIMD 9595+ float back; 9596+ 9597+ _asm 9598+ { 9599+ mov eax,v 9600+ 9601+ /*Chunk1*/ 9602+ movaps xmm0,[eax] 9603+ movaps xmm1,[eax+16] 9604+ movaps xmm2,[eax+32] 9605+ movaps xmm3,[eax+48] 9606+ movaps xmm4,[eax+64] 9607+ movaps xmm5,[eax+80] 9608+ movaps xmm6,[eax+96] 9609+ movaps xmm7,[eax+112] 9610+ 9611+ /*Chunk2*/ 9612+ maxps xmm0,[eax+128] 9613+ maxps xmm1,[eax+144] 9614+ maxps xmm2,[eax+160] 9615+ maxps xmm3,[eax+176] 9616+ maxps xmm4,[eax+192] 9617+ maxps xmm5,[eax+208] 9618+ maxps xmm6,[eax+224] 9619+ maxps xmm7,[eax+240] 9620+ 9621+ /*Collect*/ 9622+ maxps xmm0,xmm1 9623+ maxps xmm2,xmm3 9624+ maxps xmm4,xmm5 9625+ maxps xmm6,xmm7 9626+ maxps xmm0,xmm2 9627+ maxps xmm4,xmm6 9628+ maxps xmm0,xmm4 9629+ movhlps xmm1,xmm0 9630+ maxps xmm0,xmm1 9631+ shufps xmm1,xmm0,1 9632+ maxps xmm0,xmm1 9633+ movss back,xmm0 9634+ } 9635+ 9636+ return(back); 9637+#else 9638+ float val,max_val; 9639+ float *p,*stop_p; 9640+ max_val=v[0]; 9641+ for(p=v+1,stop_p=v+64;p!=stop_p;) 9642+ { 9643+ val= *p++; 9644+ if(val>max_val) max_val=val; 9645+ } 9646+ return(max_val); 9647+#endif /*DB_USE_SIMD*/ 9648+} 9649+ 9650+inline float db_Max_32Aligned16_f(float *v) 9651+{ 9652+#ifdef DB_USE_SIMD 9653+ float back; 9654+ 9655+ _asm 9656+ { 9657+ mov eax,v 9658+ 9659+ /*Chunk1*/ 9660+ movaps xmm0,[eax] 9661+ movaps xmm1,[eax+16] 9662+ movaps xmm2,[eax+32] 9663+ movaps xmm3,[eax+48] 9664+ movaps xmm4,[eax+64] 9665+ movaps xmm5,[eax+80] 9666+ movaps xmm6,[eax+96] 9667+ movaps xmm7,[eax+112] 9668+ 9669+ /*Collect*/ 9670+ maxps xmm0,xmm1 9671+ maxps xmm2,xmm3 9672+ maxps xmm4,xmm5 9673+ maxps xmm6,xmm7 9674+ maxps xmm0,xmm2 9675+ maxps xmm4,xmm6 9676+ maxps xmm0,xmm4 9677+ movhlps xmm1,xmm0 9678+ maxps xmm0,xmm1 9679+ shufps xmm1,xmm0,1 9680+ maxps xmm0,xmm1 9681+ movss back,xmm0 9682+ } 9683+ 9684+ return(back); 9685+#else 9686+ float val,max_val; 9687+ float *p,*stop_p; 9688+ max_val=v[0]; 9689+ for(p=v+1,stop_p=v+32;p!=stop_p;) 9690+ { 9691+ val= *p++; 9692+ if(val>max_val) max_val=val; 9693+ } 9694+ return(max_val); 9695+#endif /*DB_USE_SIMD*/ 9696+} 9697+ 9698+inline float db_Max_16Aligned16_f(float *v) 9699+{ 9700+#ifdef DB_USE_SIMD 9701+ float back; 9702+ 9703+ _asm 9704+ { 9705+ mov eax,v 9706+ 9707+ /*Chunk1*/ 9708+ movaps xmm0,[eax] 9709+ movaps xmm1,[eax+16] 9710+ movaps xmm2,[eax+32] 9711+ movaps xmm3,[eax+48] 9712+ 9713+ /*Collect*/ 9714+ maxps xmm0,xmm1 9715+ maxps xmm2,xmm3 9716+ maxps xmm0,xmm2 9717+ movhlps xmm1,xmm0 9718+ maxps xmm0,xmm1 9719+ shufps xmm1,xmm0,1 9720+ maxps xmm0,xmm1 9721+ movss back,xmm0 9722+ } 9723+ 9724+ return(back); 9725+#else 9726+ float val,max_val; 9727+ float *p,*stop_p; 9728+ max_val=v[0]; 9729+ for(p=v+1,stop_p=v+16;p!=stop_p;) 9730+ { 9731+ val= *p++; 9732+ if(val>max_val) max_val=val; 9733+ } 9734+ return(max_val); 9735+#endif /*DB_USE_SIMD*/ 9736+} 9737+ 9738+inline float db_Max_8Aligned16_f(float *v) 9739+{ 9740+#ifdef DB_USE_SIMD 9741+ float back; 9742+ 9743+ _asm 9744+ { 9745+ mov eax,v 9746+ 9747+ /*Chunk1*/ 9748+ movaps xmm0,[eax] 9749+ movaps xmm1,[eax+16] 9750+ 9751+ /*Collect*/ 9752+ maxps xmm0,xmm1 9753+ movhlps xmm1,xmm0 9754+ maxps xmm0,xmm1 9755+ shufps xmm1,xmm0,1 9756+ maxps xmm0,xmm1 9757+ movss back,xmm0 9758+ } 9759+ 9760+ return(back); 9761+#else 9762+ float val,max_val; 9763+ float *p,*stop_p; 9764+ max_val=v[0]; 9765+ for(p=v+1,stop_p=v+8;p!=stop_p;) 9766+ { 9767+ val= *p++; 9768+ if(val>max_val) max_val=val; 9769+ } 9770+ return(max_val); 9771+#endif /*DB_USE_SIMD*/ 9772+} 9773+ 9774+inline float db_Max_Aligned16_f(float *v,int size) 9775+{ 9776+ float val,max_val; 9777+ float *stop_v; 9778+ 9779+ max_val=v[0]; 9780+ for(;size>=128;size-=128) 9781+ { 9782+ val=db_Max_128Aligned16_f(v); 9783+ v+=128; 9784+ if(val>max_val) max_val=val; 9785+ } 9786+ if(size&64) 9787+ { 9788+ val=db_Max_64Aligned16_f(v); 9789+ v+=64; 9790+ if(val>max_val) max_val=val; 9791+ } 9792+ if(size&32) 9793+ { 9794+ val=db_Max_32Aligned16_f(v); 9795+ v+=32; 9796+ if(val>max_val) max_val=val; 9797+ } 9798+ if(size&16) 9799+ { 9800+ val=db_Max_16Aligned16_f(v); 9801+ v+=16; 9802+ if(val>max_val) max_val=val; 9803+ } 9804+ if(size&8) 9805+ { 9806+ val=db_Max_8Aligned16_f(v); 9807+ v+=8; 9808+ if(val>max_val) max_val=val; 9809+ } 9810+ if(size&7) 9811+ { 9812+ for(stop_v=v+(size&7);v!=stop_v;) 9813+ { 9814+ val= *v++; 9815+ if(val>max_val) max_val=val; 9816+ } 9817+ } 9818+ 9819+ return(max_val); 9820+} 9821+ 9822+/*Find maximum value of img in the region starting at (left,top) 9823+and with width w and height h. img[left] should be 16 byte aligned*/ 9824+float db_MaxImage_Aligned16_f(float **img,int left,int top,int w,int h) 9825+{ 9826+ float val,max_val; 9827+ int i,stop_i; 9828+ 9829+ if(w && h) 9830+ { 9831+ stop_i=top+h; 9832+ max_val=img[top][left]; 9833+ 9834+ for(i=top;i<stop_i;i++) 9835+ { 9836+ val=db_Max_Aligned16_f(img[i]+left,w); 9837+ if(val>max_val) max_val=val; 9838+ } 9839+ return(max_val); 9840+ } 9841+ return(0.0); 9842+} 9843+ 9844+inline void db_MaxVector_128_Aligned16_f(float *m,float *v1,float *v2) 9845+{ 9846+#ifdef DB_USE_SIMD 9847+ _asm 9848+ { 9849+ mov eax,v1 9850+ mov ebx,v2 9851+ mov ecx,m 9852+ 9853+ /*Chunk1*/ 9854+ movaps xmm0,[eax] 9855+ movaps xmm1,[eax+16] 9856+ movaps xmm2,[eax+32] 9857+ movaps xmm3,[eax+48] 9858+ movaps xmm4,[eax+64] 9859+ movaps xmm5,[eax+80] 9860+ movaps xmm6,[eax+96] 9861+ movaps xmm7,[eax+112] 9862+ maxps xmm0,[ebx] 9863+ maxps xmm1,[ebx+16] 9864+ maxps xmm2,[ebx+32] 9865+ maxps xmm3,[ebx+48] 9866+ maxps xmm4,[ebx+64] 9867+ maxps xmm5,[ebx+80] 9868+ maxps xmm6,[ebx+96] 9869+ maxps xmm7,[ebx+112] 9870+ movaps [ecx],xmm0 9871+ movaps [ecx+16],xmm1 9872+ movaps [ecx+32],xmm2 9873+ movaps [ecx+48],xmm3 9874+ movaps [ecx+64],xmm4 9875+ movaps [ecx+80],xmm5 9876+ movaps [ecx+96],xmm6 9877+ movaps [ecx+112],xmm7 9878+ 9879+ /*Chunk2*/ 9880+ movaps xmm0,[eax+128] 9881+ movaps xmm1,[eax+144] 9882+ movaps xmm2,[eax+160] 9883+ movaps xmm3,[eax+176] 9884+ movaps xmm4,[eax+192] 9885+ movaps xmm5,[eax+208] 9886+ movaps xmm6,[eax+224] 9887+ movaps xmm7,[eax+240] 9888+ maxps xmm0,[ebx+128] 9889+ maxps xmm1,[ebx+144] 9890+ maxps xmm2,[ebx+160] 9891+ maxps xmm3,[ebx+176] 9892+ maxps xmm4,[ebx+192] 9893+ maxps xmm5,[ebx+208] 9894+ maxps xmm6,[ebx+224] 9895+ maxps xmm7,[ebx+240] 9896+ movaps [ecx+128],xmm0 9897+ movaps [ecx+144],xmm1 9898+ movaps [ecx+160],xmm2 9899+ movaps [ecx+176],xmm3 9900+ movaps [ecx+192],xmm4 9901+ movaps [ecx+208],xmm5 9902+ movaps [ecx+224],xmm6 9903+ movaps [ecx+240],xmm7 9904+ 9905+ /*Chunk3*/ 9906+ movaps xmm0,[eax+256] 9907+ movaps xmm1,[eax+272] 9908+ movaps xmm2,[eax+288] 9909+ movaps xmm3,[eax+304] 9910+ movaps xmm4,[eax+320] 9911+ movaps xmm5,[eax+336] 9912+ movaps xmm6,[eax+352] 9913+ movaps xmm7,[eax+368] 9914+ maxps xmm0,[ebx+256] 9915+ maxps xmm1,[ebx+272] 9916+ maxps xmm2,[ebx+288] 9917+ maxps xmm3,[ebx+304] 9918+ maxps xmm4,[ebx+320] 9919+ maxps xmm5,[ebx+336] 9920+ maxps xmm6,[ebx+352] 9921+ maxps xmm7,[ebx+368] 9922+ movaps [ecx+256],xmm0 9923+ movaps [ecx+272],xmm1 9924+ movaps [ecx+288],xmm2 9925+ movaps [ecx+304],xmm3 9926+ movaps [ecx+320],xmm4 9927+ movaps [ecx+336],xmm5 9928+ movaps [ecx+352],xmm6 9929+ movaps [ecx+368],xmm7 9930+ 9931+ /*Chunk4*/ 9932+ movaps xmm0,[eax+384] 9933+ movaps xmm1,[eax+400] 9934+ movaps xmm2,[eax+416] 9935+ movaps xmm3,[eax+432] 9936+ movaps xmm4,[eax+448] 9937+ movaps xmm5,[eax+464] 9938+ movaps xmm6,[eax+480] 9939+ movaps xmm7,[eax+496] 9940+ maxps xmm0,[ebx+384] 9941+ maxps xmm1,[ebx+400] 9942+ maxps xmm2,[ebx+416] 9943+ maxps xmm3,[ebx+432] 9944+ maxps xmm4,[ebx+448] 9945+ maxps xmm5,[ebx+464] 9946+ maxps xmm6,[ebx+480] 9947+ maxps xmm7,[ebx+496] 9948+ movaps [ecx+384],xmm0 9949+ movaps [ecx+400],xmm1 9950+ movaps [ecx+416],xmm2 9951+ movaps [ecx+432],xmm3 9952+ movaps [ecx+448],xmm4 9953+ movaps [ecx+464],xmm5 9954+ movaps [ecx+480],xmm6 9955+ movaps [ecx+496],xmm7 9956+ } 9957+#else 9958+ int i; 9959+ float a,b; 9960+ for(i=0;i<128;i++) 9961+ { 9962+ a=v1[i]; 9963+ b=v2[i]; 9964+ if(a>=b) m[i]=a; 9965+ else m[i]=b; 9966+ } 9967+#endif /*DB_USE_SIMD*/ 9968+} 9969+ 9970+inline void db_MaxVector_128_SecondSourceDestAligned16_f(float *m,float *v1,float *v2) 9971+{ 9972+#ifdef DB_USE_SIMD 9973+ _asm 9974+ { 9975+ mov eax,v1 9976+ mov ebx,v2 9977+ mov ecx,m 9978+ 9979+ /*Chunk1*/ 9980+ movups xmm0,[eax] 9981+ movups xmm1,[eax+16] 9982+ movups xmm2,[eax+32] 9983+ movups xmm3,[eax+48] 9984+ movups xmm4,[eax+64] 9985+ movups xmm5,[eax+80] 9986+ movups xmm6,[eax+96] 9987+ movups xmm7,[eax+112] 9988+ maxps xmm0,[ebx] 9989+ maxps xmm1,[ebx+16] 9990+ maxps xmm2,[ebx+32] 9991+ maxps xmm3,[ebx+48] 9992+ maxps xmm4,[ebx+64] 9993+ maxps xmm5,[ebx+80] 9994+ maxps xmm6,[ebx+96] 9995+ maxps xmm7,[ebx+112] 9996+ movaps [ecx],xmm0 9997+ movaps [ecx+16],xmm1 9998+ movaps [ecx+32],xmm2 9999+ movaps [ecx+48],xmm3 10000+ movaps [ecx+64],xmm4 10001+ movaps [ecx+80],xmm5 10002+ movaps [ecx+96],xmm6 10003+ movaps [ecx+112],xmm7 10004+ 10005+ /*Chunk2*/ 10006+ movups xmm0,[eax+128] 10007+ movups xmm1,[eax+144] 10008+ movups xmm2,[eax+160] 10009+ movups xmm3,[eax+176] 10010+ movups xmm4,[eax+192] 10011+ movups xmm5,[eax+208] 10012+ movups xmm6,[eax+224] 10013+ movups xmm7,[eax+240] 10014+ maxps xmm0,[ebx+128] 10015+ maxps xmm1,[ebx+144] 10016+ maxps xmm2,[ebx+160] 10017+ maxps xmm3,[ebx+176] 10018+ maxps xmm4,[ebx+192] 10019+ maxps xmm5,[ebx+208] 10020+ maxps xmm6,[ebx+224] 10021+ maxps xmm7,[ebx+240] 10022+ movaps [ecx+128],xmm0 10023+ movaps [ecx+144],xmm1 10024+ movaps [ecx+160],xmm2 10025+ movaps [ecx+176],xmm3 10026+ movaps [ecx+192],xmm4 10027+ movaps [ecx+208],xmm5 10028+ movaps [ecx+224],xmm6 10029+ movaps [ecx+240],xmm7 10030+ 10031+ /*Chunk3*/ 10032+ movups xmm0,[eax+256] 10033+ movups xmm1,[eax+272] 10034+ movups xmm2,[eax+288] 10035+ movups xmm3,[eax+304] 10036+ movups xmm4,[eax+320] 10037+ movups xmm5,[eax+336] 10038+ movups xmm6,[eax+352] 10039+ movups xmm7,[eax+368] 10040+ maxps xmm0,[ebx+256] 10041+ maxps xmm1,[ebx+272] 10042+ maxps xmm2,[ebx+288] 10043+ maxps xmm3,[ebx+304] 10044+ maxps xmm4,[ebx+320] 10045+ maxps xmm5,[ebx+336] 10046+ maxps xmm6,[ebx+352] 10047+ maxps xmm7,[ebx+368] 10048+ movaps [ecx+256],xmm0 10049+ movaps [ecx+272],xmm1 10050+ movaps [ecx+288],xmm2 10051+ movaps [ecx+304],xmm3 10052+ movaps [ecx+320],xmm4 10053+ movaps [ecx+336],xmm5 10054+ movaps [ecx+352],xmm6 10055+ movaps [ecx+368],xmm7 10056+ 10057+ /*Chunk4*/ 10058+ movups xmm0,[eax+384] 10059+ movups xmm1,[eax+400] 10060+ movups xmm2,[eax+416] 10061+ movups xmm3,[eax+432] 10062+ movups xmm4,[eax+448] 10063+ movups xmm5,[eax+464] 10064+ movups xmm6,[eax+480] 10065+ movups xmm7,[eax+496] 10066+ maxps xmm0,[ebx+384] 10067+ maxps xmm1,[ebx+400] 10068+ maxps xmm2,[ebx+416] 10069+ maxps xmm3,[ebx+432] 10070+ maxps xmm4,[ebx+448] 10071+ maxps xmm5,[ebx+464] 10072+ maxps xmm6,[ebx+480] 10073+ maxps xmm7,[ebx+496] 10074+ movaps [ecx+384],xmm0 10075+ movaps [ecx+400],xmm1 10076+ movaps [ecx+416],xmm2 10077+ movaps [ecx+432],xmm3 10078+ movaps [ecx+448],xmm4 10079+ movaps [ecx+464],xmm5 10080+ movaps [ecx+480],xmm6 10081+ movaps [ecx+496],xmm7 10082+ } 10083+#else 10084+ int i; 10085+ float a,b; 10086+ for(i=0;i<128;i++) 10087+ { 10088+ a=v1[i]; 10089+ b=v2[i]; 10090+ if(a>=b) m[i]=a; 10091+ else m[i]=b; 10092+ } 10093+#endif /*DB_USE_SIMD*/ 10094+} 10095+ 10096+/*Compute Max-suppression-filtered image for a chunk of sf starting at (left,top), of width 124 and 10097+stopping at bottom. The output is shifted two steps left and overwrites 128 elements for each row. 10098+The input s should be of width at least 128, and exist for 2 pixels outside the specified region. 10099+s[i][left-2] and sf[i][left-2] should be 16 byte aligned. Top must be at least 3*/ 10100+inline void db_MaxSuppressFilterChunk_5x5_Aligned16_f(float **sf,float **s,int left,int top,int bottom, 10101+ /*temp should point to at least 10102+ 6*132 floats of 16-byte-aligned allocated memory*/ 10103+ float *temp) 10104+{ 10105+#ifdef DB_USE_SIMD 10106+ int i,lm2; 10107+ float *two[4]; 10108+ float *four,*five; 10109+ 10110+ lm2=left-2; 10111+ 10112+ /*Set pointers to pre-allocated memory*/ 10113+ four=temp; 10114+ five=four+132; 10115+ for(i=0;i<4;i++) 10116+ { 10117+ two[i]=five+(i+1)*132; 10118+ } 10119+ 10120+ /*Set rests of four and five to zero to avoid 10121+ floating point exceptions*/ 10122+ for(i=129;i<132;i++) 10123+ { 10124+ four[i]=0.0; 10125+ five[i]=0.0; 10126+ } 10127+ 10128+ /*Fill three rows of the wrap-around max buffers*/ 10129+ for(i=top-3;i<top;i++) db_MaxVector_128_Aligned16_f(two[i&3],s[i+1]+lm2,s[i+2]+lm2); 10130+ 10131+ /*For each output row*/ 10132+ for(;i<=bottom;i++) 10133+ { 10134+ /*Compute max of the lowest pair of rows in the five row window*/ 10135+ db_MaxVector_128_Aligned16_f(two[i&3],s[i+1]+lm2,s[i+2]+lm2); 10136+ /*Compute max of the lowest and highest pair of rows in the five row window*/ 10137+ db_MaxVector_128_Aligned16_f(four,two[i&3],two[(i-3)&3]); 10138+ /*Compute max of all rows*/ 10139+ db_MaxVector_128_Aligned16_f(five,four,two[(i-1)&3]); 10140+ /*Compute max of 2x5 chunks*/ 10141+ db_MaxVector_128_SecondSourceDestAligned16_f(five,five+1,five); 10142+ /*Compute max of pairs of 2x5 chunks*/ 10143+ db_MaxVector_128_SecondSourceDestAligned16_f(five,five+3,five); 10144+ /*Compute max of pairs of 5x5 except middle*/ 10145+ db_MaxVector_128_SecondSourceDestAligned16_f(sf[i]+lm2,four+2,five); 10146+ } 10147+ 10148+#else 10149+ int i,j,right; 10150+ float sv; 10151+ 10152+ right=left+128; 10153+ for(i=top;i<=bottom;i++) for(j=left;j<right;j++) 10154+ { 10155+ sv=s[i][j]; 10156+ 10157+ if( sv>s[i-2][j-2] && sv>s[i-2][j-1] && sv>s[i-2][j] && sv>s[i-2][j+1] && sv>s[i-2][j+2] && 10158+ sv>s[i-1][j-2] && sv>s[i-1][j-1] && sv>s[i-1][j] && sv>s[i-1][j+1] && sv>s[i-1][j+2] && 10159+ sv>s[ i][j-2] && sv>s[ i][j-1] && sv>s[ i][j+1] && sv>s[ i][j+2] && 10160+ sv>s[i+1][j-2] && sv>s[i+1][j-1] && sv>s[i+1][j] && sv>s[i+1][j+1] && sv>s[i+1][j+2] && 10161+ sv>s[i+2][j-2] && sv>s[i+2][j-1] && sv>s[i+2][j] && sv>s[i+2][j+1] && sv>s[i+2][j+2]) 10162+ { 10163+ sf[i][j-2]=0.0; 10164+ } 10165+ else sf[i][j-2]=sv; 10166+ } 10167+#endif /*DB_USE_SIMD*/ 10168+} 10169+ 10170+/*Compute Max-suppression-filtered image for a chunk of sf starting at (left,top) and 10171+stopping at bottom. The output is shifted two steps left. The input s should exist for 2 pixels 10172+outside the specified region. s[i][left-2] and sf[i][left-2] should be 16 byte aligned. 10173+Top must be at least 3. Reading and writing from and to the input and output images is done 10174+as if the region had a width equal to a multiple of 124. If this is not the case, the images 10175+should be over-allocated and the input cleared for a sufficient region*/ 10176+void db_MaxSuppressFilter_5x5_Aligned16_f(float **sf,float **s,int left,int top,int right,int bottom, 10177+ /*temp should point to at least 10178+ 6*132 floats of 16-byte-aligned allocated memory*/ 10179+ float *temp) 10180+{ 10181+ int x,next_x; 10182+ 10183+ for(x=left;x<=right;x=next_x) 10184+ { 10185+ next_x=x+124; 10186+ db_MaxSuppressFilterChunk_5x5_Aligned16_f(sf,s,x,top,bottom,temp); 10187+ } 10188+} 10189+ 10190+/*Extract corners from the chunk (left,top) to (right,bottom). Store in x_temp,y_temp and s_temp 10191+which should point to space of at least as many positions as there are pixels in the chunk*/ 10192+inline int db_CornersFromChunk(float **strength,int left,int top,int right,int bottom,float threshold,double *x_temp,double *y_temp,double *s_temp) 10193+{ 10194+ int i,j,nr; 10195+ float s; 10196+ 10197+ nr=0; 10198+ for(i=top;i<=bottom;i++) for(j=left;j<=right;j++) 10199+ { 10200+ s=strength[i][j]; 10201+ 10202+ if(s>=threshold && 10203+ s>strength[i-2][j-2] && s>strength[i-2][j-1] && s>strength[i-2][j] && s>strength[i-2][j+1] && s>strength[i-2][j+2] && 10204+ s>strength[i-1][j-2] && s>strength[i-1][j-1] && s>strength[i-1][j] && s>strength[i-1][j+1] && s>strength[i-1][j+2] && 10205+ s>strength[ i][j-2] && s>strength[ i][j-1] && s>strength[ i][j+1] && s>strength[ i][j+2] && 10206+ s>strength[i+1][j-2] && s>strength[i+1][j-1] && s>strength[i+1][j] && s>strength[i+1][j+1] && s>strength[i+1][j+2] && 10207+ s>strength[i+2][j-2] && s>strength[i+2][j-1] && s>strength[i+2][j] && s>strength[i+2][j+1] && s>strength[i+2][j+2]) 10208+ { 10209+ x_temp[nr]=(double) j; 10210+ y_temp[nr]=(double) i; 10211+ s_temp[nr]=(double) s; 10212+ nr++; 10213+ } 10214+ } 10215+ return(nr); 10216+} 10217+ 10218+ 10219+//Sub-pixel accuracy using 2D quadratic interpolation.(YCJ) 10220+inline void db_SubPixel(float **strength, const double xd, const double yd, double &xs, double &ys) 10221+{ 10222+ int x = (int) xd; 10223+ int y = (int) yd; 10224+ 10225+ float fxx = strength[y][x-1] - strength[y][x] - strength[y][x] + strength[y][x+1]; 10226+ float fyy = strength[y-1][x] - strength[y][x] - strength[y][x] + strength[y+1][x]; 10227+ float fxy = (strength[y-1][x-1] - strength[y-1][x+1] - strength[y+1][x-1] + strength[y+1][x+1])/(float)4.0; 10228+ 10229+ float denom = (fxx * fyy - fxy * fxy) * (float) 2.0; 10230+ 10231+ xs = xd; 10232+ ys = yd; 10233+ 10234+ if ( db_absf(denom) <= FLT_EPSILON ) 10235+ { 10236+ return; 10237+ } 10238+ else 10239+ { 10240+ float fx = strength[y][x+1] - strength[y][x-1]; 10241+ float fy = strength[y+1][x] - strength[y-1][x]; 10242+ 10243+ float dx = (fyy * fx - fxy * fy) / denom; 10244+ float dy = (fxx * fy - fxy * fx) / denom; 10245+ 10246+ if ( db_absf(dx) > 1.0 || db_absf(dy) > 1.0 ) 10247+ { 10248+ return; 10249+ } 10250+ else 10251+ { 10252+ xs -= dx; 10253+ ys -= dy; 10254+ } 10255+ } 10256+ 10257+ return; 10258+} 10259+ 10260+/*Extract corners from the image part from (left,top) to (right,bottom). 10261+Store in x and y, extracting at most satnr corners in each block of size (bw,bh). 10262+The pointer temp_d should point to at least 5*bw*bh positions. 10263+area_factor holds how many corners max to extract per 10000 pixels*/ 10264+void db_ExtractCornersSaturated(float **strength,int left,int top,int right,int bottom, 10265+ int bw,int bh,unsigned long area_factor, 10266+ float threshold,double *temp_d, 10267+ double *x_coord,double *y_coord,int *nr_corners) 10268+{ 10269+ double *x_temp,*y_temp,*s_temp,*select_temp; 10270+ double loc_thresh; 10271+ unsigned long bwbh,area,saturation; 10272+ int x,next_x,last_x; 10273+ int y,next_y,last_y; 10274+ int nr,nr_points,i,stop; 10275+ 10276+ bwbh=bw*bh; 10277+ x_temp=temp_d; 10278+ y_temp=x_temp+bwbh; 10279+ s_temp=y_temp+bwbh; 10280+ select_temp=s_temp+bwbh; 10281+ 10282+#ifdef DB_SUB_PIXEL 10283+ // subpixel processing may sometimes push the corner ourside the real border 10284+ // increasing border size: 10285+ left++; 10286+ top++; 10287+ bottom--; 10288+ right--; 10289+#endif /*DB_SUB_PIXEL*/ 10290+ 10291+ nr_points=0; 10292+ for(y=top;y<=bottom;y=next_y) 10293+ { 10294+ next_y=y+bh; 10295+ last_y=next_y-1; 10296+ if(last_y>bottom) last_y=bottom; 10297+ for(x=left;x<=right;x=next_x) 10298+ { 10299+ next_x=x+bw; 10300+ last_x=next_x-1; 10301+ if(last_x>right) last_x=right; 10302+ 10303+ area=(last_x-x+1)*(last_y-y+1); 10304+ saturation=(area*area_factor)/10000; 10305+ nr=db_CornersFromChunk(strength,x,y,last_x,last_y,threshold,x_temp,y_temp,s_temp); 10306+ if(nr) 10307+ { 10308+ if(((unsigned long)nr)>saturation) loc_thresh=db_LeanQuickSelect(s_temp,nr,nr-saturation,select_temp); 10309+ else loc_thresh=threshold; 10310+ 10311+ stop=nr_points+saturation; 10312+ for(i=0;(i<nr)&&(nr_points<stop);i++) 10313+ { 10314+ if(s_temp[i]>=loc_thresh) 10315+ { 10316+ #ifdef DB_SUB_PIXEL 10317+ db_SubPixel(strength, x_temp[i], y_temp[i], x_coord[nr_points], y_coord[nr_points]); 10318+ #else 10319+ x_coord[nr_points]=x_temp[i]; 10320+ y_coord[nr_points]=y_temp[i]; 10321+ #endif 10322+ 10323+ nr_points++; 10324+ } 10325+ } 10326+ } 10327+ } 10328+ } 10329+ *nr_corners=nr_points; 10330+} 10331+ 10332+db_CornerDetector_f::db_CornerDetector_f() 10333+{ 10334+ m_w=0; m_h=0; 10335+} 10336+ 10337+db_CornerDetector_f::~db_CornerDetector_f() 10338+{ 10339+ Clean(); 10340+} 10341+ 10342+void db_CornerDetector_f::Clean() 10343+{ 10344+ if(m_w!=0) 10345+ { 10346+ delete [] m_temp_f; 10347+ delete [] m_temp_d; 10348+ db_FreeStrengthImage_f(m_strength_mem,m_strength,m_h); 10349+ } 10350+ m_w=0; m_h=0; 10351+} 10352+ 10353+unsigned long db_CornerDetector_f::Init(int im_width,int im_height,int target_nr_corners, 10354+ int nr_horizontal_blocks,int nr_vertical_blocks, 10355+ double absolute_threshold,double relative_threshold) 10356+{ 10357+ int chunkwidth=208; 10358+ int block_width,block_height; 10359+ unsigned long area_factor; 10360+ int active_width,active_height; 10361+ 10362+ active_width=db_maxi(1,im_width-10); 10363+ active_height=db_maxi(1,im_height-10); 10364+ block_width=db_maxi(1,active_width/nr_horizontal_blocks); 10365+ block_height=db_maxi(1,active_height/nr_vertical_blocks); 10366+ 10367+ area_factor=db_minl(1000,db_maxl(1,(long)(10000.0*((double)target_nr_corners)/ 10368+ (((double)active_width)*((double)active_height))))); 10369+ 10370+ return(Start(im_width,im_height,block_width,block_height,area_factor, 10371+ absolute_threshold,relative_threshold,chunkwidth)); 10372+} 10373+ 10374+unsigned long db_CornerDetector_f::Start(int im_width,int im_height, 10375+ int block_width,int block_height,unsigned long area_factor, 10376+ double absolute_threshold,double relative_threshold,int chunkwidth) 10377+{ 10378+ Clean(); 10379+ 10380+ m_w=im_width; 10381+ m_h=im_height; 10382+ m_cw=chunkwidth; 10383+ m_bw=block_width; 10384+ m_bh=block_height; 10385+ m_area_factor=area_factor; 10386+ m_r_thresh=relative_threshold; 10387+ m_a_thresh=absolute_threshold; 10388+ m_max_nr=db_maxl(1,1+(m_w*m_h*m_area_factor)/10000); 10389+ 10390+ m_temp_f=new float[13*(m_cw+4)]; 10391+ m_temp_d=new double[5*m_bw*m_bh]; 10392+ m_strength=db_AllocStrengthImage_f(&m_strength_mem,m_w,m_h); 10393+ 10394+ return(m_max_nr); 10395+} 10396+ 10397+void db_CornerDetector_f::DetectCorners(const float * const *img,double *x_coord,double *y_coord,int *nr_corners) const 10398+{ 10399+ float max_val,threshold; 10400+ 10401+ db_HarrisStrength_f(m_strength,img,m_w,m_h,m_temp_f,m_cw); 10402+ 10403+ if(m_r_thresh) 10404+ { 10405+ max_val=db_MaxImage_Aligned16_f(m_strength,3,3,m_w-6,m_h-6); 10406+ threshold= (float) db_maxd(m_a_thresh,max_val*m_r_thresh); 10407+ } 10408+ else threshold= (float) m_a_thresh; 10409+ 10410+ db_ExtractCornersSaturated(m_strength,BORDER,BORDER,m_w-BORDER-1,m_h-BORDER-1,m_bw,m_bh,m_area_factor,threshold, 10411+ m_temp_d,x_coord,y_coord,nr_corners); 10412+} 10413+ 10414+db_CornerDetector_u::db_CornerDetector_u() 10415+{ 10416+ m_w=0; m_h=0; 10417+} 10418+ 10419+db_CornerDetector_u::~db_CornerDetector_u() 10420+{ 10421+ Clean(); 10422+} 10423+ 10424+db_CornerDetector_u::db_CornerDetector_u(const db_CornerDetector_u& cd) 10425+{ 10426+ Start(cd.m_w, cd.m_h, cd.m_bw, cd.m_bh, cd.m_area_factor, 10427+ cd.m_a_thresh, cd.m_r_thresh); 10428+} 10429+ 10430+db_CornerDetector_u& db_CornerDetector_u::operator=(const db_CornerDetector_u& cd) 10431+{ 10432+ if ( this == &cd ) return *this; 10433+ 10434+ Clean(); 10435+ 10436+ Start(cd.m_w, cd.m_h, cd.m_bw, cd.m_bh, cd.m_area_factor, 10437+ cd.m_a_thresh, cd.m_r_thresh); 10438+ 10439+ return *this; 10440+} 10441+ 10442+void db_CornerDetector_u::Clean() 10443+{ 10444+ if(m_w!=0) 10445+ { 10446+ delete [] m_temp_i; 10447+ delete [] m_temp_d; 10448+ db_FreeStrengthImage_f(m_strength_mem,m_strength,m_h); 10449+ } 10450+ m_w=0; m_h=0; 10451+} 10452+ 10453+unsigned long db_CornerDetector_u::Init(int im_width,int im_height,int target_nr_corners, 10454+ int nr_horizontal_blocks,int nr_vertical_blocks, 10455+ double absolute_threshold,double relative_threshold) 10456+{ 10457+ int block_width,block_height; 10458+ unsigned long area_factor; 10459+ int active_width,active_height; 10460+ 10461+ active_width=db_maxi(1,im_width-10); 10462+ active_height=db_maxi(1,im_height-10); 10463+ block_width=db_maxi(1,active_width/nr_horizontal_blocks); 10464+ block_height=db_maxi(1,active_height/nr_vertical_blocks); 10465+ 10466+ area_factor=db_minl(1000,db_maxl(1,(long)(10000.0*((double)target_nr_corners)/ 10467+ (((double)active_width)*((double)active_height))))); 10468+ 10469+ return(Start(im_width,im_height,block_width,block_height,area_factor, 10470+ 16.0*absolute_threshold,relative_threshold)); 10471+} 10472+ 10473+unsigned long db_CornerDetector_u::Start(int im_width,int im_height, 10474+ int block_width,int block_height,unsigned long area_factor, 10475+ double absolute_threshold,double relative_threshold) 10476+{ 10477+ Clean(); 10478+ 10479+ m_w=im_width; 10480+ m_h=im_height; 10481+ m_bw=block_width; 10482+ m_bh=block_height; 10483+ m_area_factor=area_factor; 10484+ m_r_thresh=relative_threshold; 10485+ m_a_thresh=absolute_threshold; 10486+ m_max_nr=db_maxl(1,1+(m_w*m_h*m_area_factor)/10000); 10487+ 10488+ m_temp_i=new int[18*128]; 10489+ m_temp_d=new double[5*m_bw*m_bh]; 10490+ m_strength=db_AllocStrengthImage_f(&m_strength_mem,m_w,m_h); 10491+ 10492+ return(m_max_nr); 10493+} 10494+ 10495+void db_CornerDetector_u::DetectCorners(const unsigned char * const *img,double *x_coord,double *y_coord,int *nr_corners, 10496+ const unsigned char * const *msk, unsigned char fgnd) const 10497+{ 10498+ float max_val,threshold; 10499+ 10500+ db_HarrisStrength_u(m_strength,img,m_w,m_h,m_temp_i); 10501+ 10502+ 10503+ if(m_r_thresh) 10504+ { 10505+ max_val=db_MaxImage_Aligned16_f(m_strength,3,3,m_w-6,m_h-6); 10506+ threshold= (float) db_maxd(m_a_thresh,max_val*m_r_thresh); 10507+ } 10508+ else threshold= (float) m_a_thresh; 10509+ 10510+ db_ExtractCornersSaturated(m_strength,BORDER,BORDER,m_w-BORDER-1,m_h-BORDER-1,m_bw,m_bh,m_area_factor,threshold, 10511+ m_temp_d,x_coord,y_coord,nr_corners); 10512+ 10513+ 10514+ if ( msk ) 10515+ { 10516+ int nr_corners_mask=0; 10517+ 10518+ for ( int i = 0; i < *nr_corners; ++i) 10519+ { 10520+ int cor_x = db_roundi(*(x_coord+i)); 10521+ int cor_y = db_roundi(*(y_coord+i)); 10522+ if ( msk[cor_y][cor_x] == fgnd ) 10523+ { 10524+ x_coord[nr_corners_mask] = x_coord[i]; 10525+ y_coord[nr_corners_mask] = y_coord[i]; 10526+ nr_corners_mask++; 10527+ } 10528+ } 10529+ *nr_corners = nr_corners_mask; 10530+ } 10531+} 10532+ 10533+void db_CornerDetector_u::ExtractCorners(float ** strength, double *x_coord, double *y_coord, int *nr_corners) { 10534+ if ( m_w!=0 ) 10535+ db_ExtractCornersSaturated(strength,BORDER,BORDER,m_w-BORDER-1,m_h-BORDER-1,m_bw,m_bh,m_area_factor,float(m_a_thresh), 10536+ m_temp_d,x_coord,y_coord,nr_corners); 10537+} 10538+ 10539diff --git a/benchmark/feature_stab/db_vlvm/db_feature_detection.h b/benchmark/feature_stab/db_vlvm/db_feature_detection.h 10540new file mode 100644 10541index 00000000..68ffcc9a 10542--- /dev/null 10543+++ b/benchmark/feature_stab/db_vlvm/db_feature_detection.h 10544@@ -0,0 +1,179 @@ 10545+/* 10546+ * Copyright (C) 2011 The Android Open Source Project 10547+ * 10548+ * Licensed under the Apache License, Version 2.0 (the "License"); 10549+ * you may not use this file except in compliance with the License. 10550+ * You may obtain a copy of the License at 10551+ * 10552+ * http://www.apache.org/licenses/LICENSE-2.0 10553+ * 10554+ * Unless required by applicable law or agreed to in writing, software 10555+ * distributed under the License is distributed on an "AS IS" BASIS, 10556+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10557+ * See the License for the specific language governing permissions and 10558+ * limitations under the License. 10559+ */ 10560+ 10561+/*$Id: db_feature_detection.h,v 1.3 2011/06/17 14:03:30 mbansal Exp $*/ 10562+ 10563+#ifndef DB_FEATURE_DETECTION_H 10564+#define DB_FEATURE_DETECTION_H 10565+ 10566+/***************************************************************** 10567+* Lean and mean begins here * 10568+*****************************************************************/ 10569+/*! 10570+ * \defgroup FeatureDetection Feature Detection 10571+ */ 10572+#include "db_utilities.h" 10573+#include "db_utilities_constants.h" 10574+#include <stdlib.h> //for NULL 10575+ 10576+/*! 10577+ * \class db_CornerDetector_f 10578+ * \ingroup FeatureDetection 10579+ * \brief Harris corner detector for float images. 10580+ * 10581+ * This class performs Harris corner extraction on *float* images managed 10582+ * with functions in \ref LMImageBasicUtilities. 10583+ */ 10584+class DB_API db_CornerDetector_f 10585+{ 10586+public: 10587+ db_CornerDetector_f(); 10588+ ~db_CornerDetector_f(); 10589+ 10590+ /*! 10591+ * Set parameters and pre-allocate memory. Return an upper bound 10592+ * on the number of corners detected in one frame. 10593+ * \param im_width width 10594+ * \param im_height height 10595+ * \param target_nr_corners 10596+ * \param nr_horizontal_blocks 10597+ * \param nr_vertical_blocks 10598+ * \param absolute_threshold 10599+ * \param relative_threshold 10600+ */ 10601+ unsigned long Init(int im_width,int im_height, 10602+ int target_nr_corners=DB_DEFAULT_TARGET_NR_CORNERS, 10603+ int nr_horizontal_blocks=DB_DEFAULT_NR_FEATURE_BLOCKS, 10604+ int nr_vertical_blocks=DB_DEFAULT_NR_FEATURE_BLOCKS, 10605+ double absolute_threshold=DB_DEFAULT_ABS_CORNER_THRESHOLD, 10606+ double relative_threshold=DB_DEFAULT_REL_CORNER_THRESHOLD); 10607+ 10608+ /*! 10609+ * Detect the corners. 10610+ * x_coord and y_coord should be pre-allocated arrays of length returned by Init(). 10611+ * \param img row array pointer 10612+ * \param x_coord corner locations 10613+ * \param y_coord corner locations 10614+ * \param nr_corners actual number of corners computed 10615+ */ 10616+ void DetectCorners(const float * const *img,double *x_coord,double *y_coord,int *nr_corners) const; 10617+ void SetAbsoluteThreshold(double a_thresh) { m_a_thresh = a_thresh; }; 10618+ void SetRelativeThreshold(double r_thresh) { m_r_thresh = r_thresh; }; 10619+protected: 10620+ void Clean(); 10621+ unsigned long Start(int im_width,int im_height, 10622+ int block_width,int block_height,unsigned long area_factor, 10623+ double absolute_threshold,double relative_threshold,int chunkwidth); 10624+ 10625+ int m_w,m_h,m_cw,m_bw,m_bh; 10626+ /*Area factor holds the maximum number of corners to detect 10627+ per 10000 pixels*/ 10628+ unsigned long m_area_factor,m_max_nr; 10629+ double m_a_thresh,m_r_thresh; 10630+ float *m_temp_f; 10631+ double *m_temp_d; 10632+ float **m_strength,*m_strength_mem; 10633+}; 10634+/*! 10635+ * \class db_CornerDetector_u 10636+ * \ingroup FeatureDetection 10637+ * \brief Harris corner detector for byte images. 10638+ * 10639+ * This class performs Harris corner extraction on *byte* images managed 10640+ * with functions in \ref LMImageBasicUtilities. 10641+ */ 10642+class DB_API db_CornerDetector_u 10643+{ 10644+public: 10645+ db_CornerDetector_u(); 10646+ virtual ~db_CornerDetector_u(); 10647+ 10648+ /*! 10649+ Copy ctor duplicates settings. 10650+ Memory is not copied. 10651+ */ 10652+ db_CornerDetector_u(const db_CornerDetector_u& cd); 10653+ /*! 10654+ Assignment optor duplicates settings. 10655+ Memory not copied. 10656+ */ 10657+ db_CornerDetector_u& operator=(const db_CornerDetector_u& cd); 10658+ 10659+ /*! 10660+ * Set parameters and pre-allocate memory. Return an upper bound 10661+ * on the number of corners detected in one frame 10662+ */ 10663+ virtual unsigned long Init(int im_width,int im_height, 10664+ int target_nr_corners=DB_DEFAULT_TARGET_NR_CORNERS, 10665+ int nr_horizontal_blocks=DB_DEFAULT_NR_FEATURE_BLOCKS, 10666+ int nr_vertical_blocks=DB_DEFAULT_NR_FEATURE_BLOCKS, 10667+ double absolute_threshold=DB_DEFAULT_ABS_CORNER_THRESHOLD, 10668+ double relative_threshold=DB_DEFAULT_REL_CORNER_THRESHOLD); 10669+ 10670+ /*! 10671+ * Detect the corners. 10672+ * Observe that the image should be overallocated by at least 256 bytes 10673+ * at the end. 10674+ * x_coord and y_coord should be pre-allocated arrays of length returned by Init(). 10675+ * Specifying image mask will restrict corner output to foreground regions. 10676+ * Foreground value can be specified using fgnd. By default any >0 mask value 10677+ * is considered to be foreground 10678+ * \param img row array pointer 10679+ * \param x_coord corner locations 10680+ * \param y_coord corner locations 10681+ * \param nr_corners actual number of corners computed 10682+ * \param msk row array pointer to mask image 10683+ * \param fgnd foreground value in the mask 10684+ */ 10685+ virtual void DetectCorners(const unsigned char * const *img,double *x_coord,double *y_coord,int *nr_corners, 10686+ const unsigned char * const * msk=NULL, unsigned char fgnd=255) const; 10687+ 10688+ /*! 10689+ Set absolute feature threshold 10690+ */ 10691+ virtual void SetAbsoluteThreshold(double a_thresh) { m_a_thresh = a_thresh; }; 10692+ /*! 10693+ Set relative feature threshold 10694+ */ 10695+ virtual void SetRelativeThreshold(double r_thresh) { m_r_thresh = r_thresh; }; 10696+ 10697+ /*! 10698+ Extract corners from a pre-computed strength image. 10699+ \param strength Harris strength image 10700+ \param x_coord corner locations 10701+ \param y_coord corner locations 10702+ \param nr_corners actual number of corners computed 10703+ */ 10704+ virtual void ExtractCorners(float ** strength, double *x_coord, double *y_coord, int *nr_corners); 10705+protected: 10706+ virtual void Clean(); 10707+ /*The absolute threshold to this function should be 16.0 times 10708+ normal*/ 10709+ unsigned long Start(int im_width,int im_height, 10710+ int block_width,int block_height,unsigned long area_factor, 10711+ double absolute_threshold,double relative_threshold); 10712+ 10713+ int m_w,m_h,m_bw,m_bh; 10714+ /*Area factor holds the maximum number of corners to detect 10715+ per 10000 pixels*/ 10716+ unsigned long m_area_factor,m_max_nr; 10717+ double m_a_thresh,m_r_thresh; 10718+ int *m_temp_i; 10719+ double *m_temp_d; 10720+ float **m_strength,*m_strength_mem; 10721+}; 10722+ 10723+#endif /*DB_FEATURE_DETECTION_H*/ 10724diff --git a/benchmark/feature_stab/db_vlvm/db_feature_matching.cpp b/benchmark/feature_stab/db_vlvm/db_feature_matching.cpp 10725new file mode 100644 10726index 00000000..891cac33 10727--- /dev/null 10728+++ b/benchmark/feature_stab/db_vlvm/db_feature_matching.cpp 10729@@ -0,0 +1,3409 @@ 10730+/* 10731+ * Copyright (C) 2011 The Android Open Source Project 10732+ * 10733+ * Licensed under the Apache License, Version 2.0 (the "License"); 10734+ * you may not use this file except in compliance with the License. 10735+ * You may obtain a copy of the License at 10736+ * 10737+ * http://www.apache.org/licenses/LICENSE-2.0 10738+ * 10739+ * Unless required by applicable law or agreed to in writing, software 10740+ * distributed under the License is distributed on an "AS IS" BASIS, 10741+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10742+ * See the License for the specific language governing permissions and 10743+ * limitations under the License. 10744+ */ 10745+ 10746+/*$Id: db_feature_matching.cpp,v 1.4 2011/06/17 14:03:30 mbansal Exp $*/ 10747+ 10748+/***************************************************************** 10749+* Lean and mean begins here * 10750+*****************************************************************/ 10751+ 10752+#include "db_utilities.h" 10753+#include "db_feature_matching.h" 10754+#ifdef _VERBOSE_ 10755+#include <iostream> 10756+#endif 10757+ 10758+ 10759+int AffineWarpPoint_NN_LUT_x[11][11]; 10760+int AffineWarpPoint_NN_LUT_y[11][11]; 10761+ 10762+float AffineWarpPoint_BL_LUT_x[11][11]; 10763+float AffineWarpPoint_BL_LUT_y[11][11]; 10764+ 10765+ 10766+inline float db_SignedSquareNormCorr7x7_u(unsigned char **f_img,unsigned char **g_img,int x_f,int y_f,int x_g,int y_g) 10767+{ 10768+ unsigned char *pf,*pg; 10769+ float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den; 10770+ int xm_f,xm_g; 10771+ 10772+ xm_f=x_f-3; 10773+ xm_g=x_g-3; 10774+ fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0; 10775+ 10776+ pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g; 10777+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10778+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10779+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10780+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10781+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10782+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10783+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10784+ 10785+ pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g; 10786+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10787+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10788+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10789+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10790+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10791+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10792+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10793+ 10794+ pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g; 10795+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10796+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10797+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10798+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10799+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10800+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10801+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10802+ 10803+ pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g; 10804+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10805+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10806+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10807+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10808+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10809+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10810+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10811+ 10812+ pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g; 10813+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10814+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10815+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10816+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10817+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10818+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10819+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10820+ 10821+ pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g; 10822+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10823+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10824+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10825+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10826+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10827+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10828+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10829+ 10830+ pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g; 10831+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10832+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10833+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10834+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10835+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10836+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10837+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10838+ 10839+ fg_corr=49.0f*fgsum-fsum*gsum; 10840+ den=(49.0f*f2sum-fsum*fsum)*(49.0f*g2sum-gsum*gsum); 10841+ if(den!=0.0) 10842+ { 10843+ if(fg_corr>=0.0) return(fg_corr*fg_corr/den); 10844+ return(-fg_corr*fg_corr/den); 10845+ } 10846+ return(0.0); 10847+} 10848+ 10849+inline float db_SignedSquareNormCorr9x9_u(unsigned char **f_img,unsigned char **g_img,int x_f,int y_f,int x_g,int y_g) 10850+{ 10851+ unsigned char *pf,*pg; 10852+ float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den; 10853+ int xm_f,xm_g; 10854+ 10855+ xm_f=x_f-4; 10856+ xm_g=x_g-4; 10857+ fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0; 10858+ 10859+ pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g; 10860+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10861+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10862+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10863+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10864+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10865+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10866+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10867+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10868+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10869+ 10870+ pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g; 10871+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10872+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10873+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10874+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10875+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10876+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10877+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10878+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10879+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10880+ 10881+ pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g; 10882+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10883+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10884+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10885+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10886+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10887+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10888+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10889+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10890+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10891+ 10892+ pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g; 10893+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10894+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10895+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10896+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10897+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10898+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10899+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10900+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10901+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10902+ 10903+ pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g; 10904+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10905+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10906+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10907+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10908+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10909+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10910+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10911+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10912+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10913+ 10914+ pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g; 10915+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10916+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10917+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10918+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10919+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10920+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10921+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10922+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10923+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10924+ 10925+ pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g; 10926+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10927+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10928+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10929+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10930+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10931+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10932+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10933+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10934+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10935+ 10936+ pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g; 10937+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10938+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10939+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10940+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10941+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10942+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10943+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10944+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10945+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10946+ 10947+ pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g; 10948+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10949+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10950+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10951+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10952+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10953+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10954+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10955+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10956+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10957+ 10958+ fg_corr=81.0f*fgsum-fsum*gsum; 10959+ den=(81.0f*f2sum-fsum*fsum)*(81.0f*g2sum-gsum*gsum); 10960+ if(den!=0.0) 10961+ { 10962+ if(fg_corr>=0.0) return(fg_corr*fg_corr/den); 10963+ return(-fg_corr*fg_corr/den); 10964+ } 10965+ return(0.0); 10966+} 10967+ 10968+inline float db_SignedSquareNormCorr11x11_u(unsigned char **f_img,unsigned char **g_img,int x_f,int y_f,int x_g,int y_g) 10969+{ 10970+ unsigned char *pf,*pg; 10971+ float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den; 10972+ int xm_f,xm_g; 10973+ 10974+ xm_f=x_f-5; 10975+ xm_g=x_g-5; 10976+ fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0; 10977+ 10978+ pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g; 10979+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10980+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10981+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10982+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10983+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10984+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10985+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10986+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10987+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10988+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10989+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10990+ 10991+ pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g; 10992+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10993+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10994+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10995+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10996+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10997+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10998+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 10999+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11000+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11001+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11002+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11003+ 11004+ pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g; 11005+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11006+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11007+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11008+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11009+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11010+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11011+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11012+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11013+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11014+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11015+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11016+ 11017+ pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g; 11018+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11019+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11020+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11021+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11022+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11023+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11024+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11025+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11026+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11027+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11028+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11029+ 11030+ pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g; 11031+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11032+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11033+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11034+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11035+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11036+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11037+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11038+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11039+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11040+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11041+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11042+ 11043+ pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g; 11044+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11045+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11046+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11047+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11048+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11049+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11050+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11051+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11052+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11053+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11054+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11055+ 11056+ pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g; 11057+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11058+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11059+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11060+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11061+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11062+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11063+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11064+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11065+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11066+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11067+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11068+ 11069+ pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g; 11070+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11071+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11072+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11073+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11074+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11075+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11076+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11077+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11078+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11079+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11080+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11081+ 11082+ pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g; 11083+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11084+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11085+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11086+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11087+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11088+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11089+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11090+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11091+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11092+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11093+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11094+ 11095+ pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g; 11096+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11097+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11098+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11099+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11100+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11101+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11102+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11103+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11104+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11105+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11106+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11107+ 11108+ pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g; 11109+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11110+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11111+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11112+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11113+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11114+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11115+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11116+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11117+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11118+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11119+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 11120+ 11121+ fg_corr=121.0f*fgsum-fsum*gsum; 11122+ den=(121.0f*f2sum-fsum*fsum)*(121.0f*g2sum-gsum*gsum); 11123+ if(den!=0.0) 11124+ { 11125+ if(fg_corr>=0.0) return(fg_corr*fg_corr/den); 11126+ return(-fg_corr*fg_corr/den); 11127+ } 11128+ return(0.0); 11129+} 11130+ 11131+inline void db_SignedSquareNormCorr11x11_Pre_u(unsigned char **f_img,int x_f,int y_f,float *sum,float *recip) 11132+{ 11133+ unsigned char *pf; 11134+ float den; 11135+ int f,f2sum,fsum; 11136+ int xm_f; 11137+ 11138+ xm_f=x_f-5; 11139+ 11140+ pf=f_img[y_f-5]+xm_f; 11141+ f= *pf++; f2sum=f*f; fsum=f; 11142+ f= *pf++; f2sum+=f*f; fsum+=f; 11143+ f= *pf++; f2sum+=f*f; fsum+=f; 11144+ f= *pf++; f2sum+=f*f; fsum+=f; 11145+ f= *pf++; f2sum+=f*f; fsum+=f; 11146+ f= *pf++; f2sum+=f*f; fsum+=f; 11147+ f= *pf++; f2sum+=f*f; fsum+=f; 11148+ f= *pf++; f2sum+=f*f; fsum+=f; 11149+ f= *pf++; f2sum+=f*f; fsum+=f; 11150+ f= *pf++; f2sum+=f*f; fsum+=f; 11151+ f= *pf; f2sum+=f*f; fsum+=f; 11152+ 11153+ pf=f_img[y_f-4]+xm_f; 11154+ f= *pf++; f2sum+=f*f; fsum+=f; 11155+ f= *pf++; f2sum+=f*f; fsum+=f; 11156+ f= *pf++; f2sum+=f*f; fsum+=f; 11157+ f= *pf++; f2sum+=f*f; fsum+=f; 11158+ f= *pf++; f2sum+=f*f; fsum+=f; 11159+ f= *pf++; f2sum+=f*f; fsum+=f; 11160+ f= *pf++; f2sum+=f*f; fsum+=f; 11161+ f= *pf++; f2sum+=f*f; fsum+=f; 11162+ f= *pf++; f2sum+=f*f; fsum+=f; 11163+ f= *pf++; f2sum+=f*f; fsum+=f; 11164+ f= *pf; f2sum+=f*f; fsum+=f; 11165+ 11166+ pf=f_img[y_f-3]+xm_f; 11167+ f= *pf++; f2sum+=f*f; fsum+=f; 11168+ f= *pf++; f2sum+=f*f; fsum+=f; 11169+ f= *pf++; f2sum+=f*f; fsum+=f; 11170+ f= *pf++; f2sum+=f*f; fsum+=f; 11171+ f= *pf++; f2sum+=f*f; fsum+=f; 11172+ f= *pf++; f2sum+=f*f; fsum+=f; 11173+ f= *pf++; f2sum+=f*f; fsum+=f; 11174+ f= *pf++; f2sum+=f*f; fsum+=f; 11175+ f= *pf++; f2sum+=f*f; fsum+=f; 11176+ f= *pf++; f2sum+=f*f; fsum+=f; 11177+ f= *pf; f2sum+=f*f; fsum+=f; 11178+ 11179+ pf=f_img[y_f-2]+xm_f; 11180+ f= *pf++; f2sum+=f*f; fsum+=f; 11181+ f= *pf++; f2sum+=f*f; fsum+=f; 11182+ f= *pf++; f2sum+=f*f; fsum+=f; 11183+ f= *pf++; f2sum+=f*f; fsum+=f; 11184+ f= *pf++; f2sum+=f*f; fsum+=f; 11185+ f= *pf++; f2sum+=f*f; fsum+=f; 11186+ f= *pf++; f2sum+=f*f; fsum+=f; 11187+ f= *pf++; f2sum+=f*f; fsum+=f; 11188+ f= *pf++; f2sum+=f*f; fsum+=f; 11189+ f= *pf++; f2sum+=f*f; fsum+=f; 11190+ f= *pf; f2sum+=f*f; fsum+=f; 11191+ 11192+ pf=f_img[y_f-1]+xm_f; 11193+ f= *pf++; f2sum+=f*f; fsum+=f; 11194+ f= *pf++; f2sum+=f*f; fsum+=f; 11195+ f= *pf++; f2sum+=f*f; fsum+=f; 11196+ f= *pf++; f2sum+=f*f; fsum+=f; 11197+ f= *pf++; f2sum+=f*f; fsum+=f; 11198+ f= *pf++; f2sum+=f*f; fsum+=f; 11199+ f= *pf++; f2sum+=f*f; fsum+=f; 11200+ f= *pf++; f2sum+=f*f; fsum+=f; 11201+ f= *pf++; f2sum+=f*f; fsum+=f; 11202+ f= *pf++; f2sum+=f*f; fsum+=f; 11203+ f= *pf; f2sum+=f*f; fsum+=f; 11204+ 11205+ pf=f_img[y_f]+xm_f; 11206+ f= *pf++; f2sum+=f*f; fsum+=f; 11207+ f= *pf++; f2sum+=f*f; fsum+=f; 11208+ f= *pf++; f2sum+=f*f; fsum+=f; 11209+ f= *pf++; f2sum+=f*f; fsum+=f; 11210+ f= *pf++; f2sum+=f*f; fsum+=f; 11211+ f= *pf++; f2sum+=f*f; fsum+=f; 11212+ f= *pf++; f2sum+=f*f; fsum+=f; 11213+ f= *pf++; f2sum+=f*f; fsum+=f; 11214+ f= *pf++; f2sum+=f*f; fsum+=f; 11215+ f= *pf++; f2sum+=f*f; fsum+=f; 11216+ f= *pf; f2sum+=f*f; fsum+=f; 11217+ 11218+ pf=f_img[y_f+1]+xm_f; 11219+ f= *pf++; f2sum+=f*f; fsum+=f; 11220+ f= *pf++; f2sum+=f*f; fsum+=f; 11221+ f= *pf++; f2sum+=f*f; fsum+=f; 11222+ f= *pf++; f2sum+=f*f; fsum+=f; 11223+ f= *pf++; f2sum+=f*f; fsum+=f; 11224+ f= *pf++; f2sum+=f*f; fsum+=f; 11225+ f= *pf++; f2sum+=f*f; fsum+=f; 11226+ f= *pf++; f2sum+=f*f; fsum+=f; 11227+ f= *pf++; f2sum+=f*f; fsum+=f; 11228+ f= *pf++; f2sum+=f*f; fsum+=f; 11229+ f= *pf; f2sum+=f*f; fsum+=f; 11230+ 11231+ pf=f_img[y_f+2]+xm_f; 11232+ f= *pf++; f2sum+=f*f; fsum+=f; 11233+ f= *pf++; f2sum+=f*f; fsum+=f; 11234+ f= *pf++; f2sum+=f*f; fsum+=f; 11235+ f= *pf++; f2sum+=f*f; fsum+=f; 11236+ f= *pf++; f2sum+=f*f; fsum+=f; 11237+ f= *pf++; f2sum+=f*f; fsum+=f; 11238+ f= *pf++; f2sum+=f*f; fsum+=f; 11239+ f= *pf++; f2sum+=f*f; fsum+=f; 11240+ f= *pf++; f2sum+=f*f; fsum+=f; 11241+ f= *pf++; f2sum+=f*f; fsum+=f; 11242+ f= *pf; f2sum+=f*f; fsum+=f; 11243+ 11244+ pf=f_img[y_f+3]+xm_f; 11245+ f= *pf++; f2sum+=f*f; fsum+=f; 11246+ f= *pf++; f2sum+=f*f; fsum+=f; 11247+ f= *pf++; f2sum+=f*f; fsum+=f; 11248+ f= *pf++; f2sum+=f*f; fsum+=f; 11249+ f= *pf++; f2sum+=f*f; fsum+=f; 11250+ f= *pf++; f2sum+=f*f; fsum+=f; 11251+ f= *pf++; f2sum+=f*f; fsum+=f; 11252+ f= *pf++; f2sum+=f*f; fsum+=f; 11253+ f= *pf++; f2sum+=f*f; fsum+=f; 11254+ f= *pf++; f2sum+=f*f; fsum+=f; 11255+ f= *pf; f2sum+=f*f; fsum+=f; 11256+ 11257+ pf=f_img[y_f+4]+xm_f; 11258+ f= *pf++; f2sum+=f*f; fsum+=f; 11259+ f= *pf++; f2sum+=f*f; fsum+=f; 11260+ f= *pf++; f2sum+=f*f; fsum+=f; 11261+ f= *pf++; f2sum+=f*f; fsum+=f; 11262+ f= *pf++; f2sum+=f*f; fsum+=f; 11263+ f= *pf++; f2sum+=f*f; fsum+=f; 11264+ f= *pf++; f2sum+=f*f; fsum+=f; 11265+ f= *pf++; f2sum+=f*f; fsum+=f; 11266+ f= *pf++; f2sum+=f*f; fsum+=f; 11267+ f= *pf++; f2sum+=f*f; fsum+=f; 11268+ f= *pf; f2sum+=f*f; fsum+=f; 11269+ 11270+ pf=f_img[y_f+5]+xm_f; 11271+ f= *pf++; f2sum+=f*f; fsum+=f; 11272+ f= *pf++; f2sum+=f*f; fsum+=f; 11273+ f= *pf++; f2sum+=f*f; fsum+=f; 11274+ f= *pf++; f2sum+=f*f; fsum+=f; 11275+ f= *pf++; f2sum+=f*f; fsum+=f; 11276+ f= *pf++; f2sum+=f*f; fsum+=f; 11277+ f= *pf++; f2sum+=f*f; fsum+=f; 11278+ f= *pf++; f2sum+=f*f; fsum+=f; 11279+ f= *pf++; f2sum+=f*f; fsum+=f; 11280+ f= *pf++; f2sum+=f*f; fsum+=f; 11281+ f= *pf; f2sum+=f*f; fsum+=f; 11282+ 11283+ *sum= (float) fsum; 11284+ den=(121.0f*f2sum-fsum*fsum); 11285+ *recip=(float)(((den!=0.0)?1.0/den:0.0)); 11286+} 11287+ 11288+inline void db_SignedSquareNormCorr5x5_PreAlign_u(short *patch,const unsigned char * const *f_img,int x_f,int y_f,float *sum,float *recip) 11289+{ 11290+ float den; 11291+ int f2sum,fsum; 11292+ int xm_f=x_f-2; 11293+ 11294+#ifndef DB_USE_SSE2 11295+ const unsigned char *pf; 11296+ short f; 11297+ 11298+ pf=f_img[y_f-2]+xm_f; 11299+ f= *pf++; f2sum=f*f; fsum=f; (*patch++)=f; 11300+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11301+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11302+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11303+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11304+ 11305+ pf=f_img[y_f-1]+xm_f; 11306+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11307+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11308+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11309+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11310+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11311+ 11312+ pf=f_img[y_f]+xm_f; 11313+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11314+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11315+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11316+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11317+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11318+ 11319+ pf=f_img[y_f+1]+xm_f; 11320+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11321+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11322+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11323+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11324+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11325+ 11326+ pf=f_img[y_f+2]+xm_f; 11327+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11328+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11329+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11330+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11331+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11332+ //int xwi; 11333+ //int ywi; 11334+ //f2sum=0; 11335+ //fsum=0; 11336+ //for (int r=-5;r<=5;r++){ 11337+ // ywi=y_f+r; 11338+ // for (int c=-5;c<=5;c++){ 11339+ // xwi=x_f+c; 11340+ // f=f_img[ywi][xwi]; 11341+ // f2sum+=f*f; 11342+ // fsum+=f; 11343+ // (*patch++)=f; 11344+ // } 11345+ //} 11346+ (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0; 11347+ (*patch++)=0; (*patch++)=0; 11348+#endif /* DB_USE_SSE2 */ 11349+ 11350+ *sum= (float) fsum; 11351+ den=(25.0f*f2sum-fsum*fsum); 11352+ *recip= (float)((den!=0.0)?1.0/den:0.0); 11353+} 11354+ 11355+inline void db_SignedSquareNormCorr21x21_PreAlign_u(short *patch,const unsigned char * const *f_img,int x_f,int y_f,float *sum,float *recip) 11356+{ 11357+ float den; 11358+ int f2sum,fsum; 11359+ short f; 11360+ 11361+ int xwi; 11362+ int ywi; 11363+ f2sum=0; 11364+ fsum=0; 11365+ for (int r=-10;r<=10;r++){ 11366+ ywi=y_f+r; 11367+ for (int c=-10;c<=10;c++){ 11368+ xwi=x_f+c; 11369+ f=f_img[ywi][xwi]; 11370+ f2sum+=f*f; 11371+ fsum+=f; 11372+ (*patch++)=f; 11373+ } 11374+ } 11375+ 11376+ for(int i=442; i<512; i++) 11377+ (*patch++)=0; 11378+ 11379+ *sum= (float) fsum; 11380+ den=(441.0f*f2sum-fsum*fsum); 11381+ *recip= (float)((den!=0.0)?1.0/den:0.0); 11382+ 11383+ 11384+} 11385+ 11386+/* Lay out the image in the patch, computing norm and 11387+*/ 11388+inline void db_SignedSquareNormCorr11x11_PreAlign_u(short *patch,const unsigned char * const *f_img,int x_f,int y_f,float *sum,float *recip) 11389+{ 11390+ float den; 11391+ int f2sum,fsum; 11392+ int xm_f=x_f-5; 11393+ 11394+#ifndef DB_USE_SSE2 11395+ const unsigned char *pf; 11396+ short f; 11397+ 11398+ pf=f_img[y_f-5]+xm_f; 11399+ f= *pf++; f2sum=f*f; fsum=f; (*patch++)=f; 11400+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11401+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11402+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11403+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11404+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11405+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11406+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11407+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11408+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11409+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11410+ 11411+ pf=f_img[y_f-4]+xm_f; 11412+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11413+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11414+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11415+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11416+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11417+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11418+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11419+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11420+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11421+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11422+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11423+ 11424+ pf=f_img[y_f-3]+xm_f; 11425+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11426+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11427+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11428+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11429+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11430+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11431+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11432+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11433+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11434+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11435+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11436+ 11437+ pf=f_img[y_f-2]+xm_f; 11438+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11439+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11440+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11441+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11442+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11443+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11444+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11445+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11446+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11447+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11448+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11449+ 11450+ pf=f_img[y_f-1]+xm_f; 11451+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11452+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11453+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11454+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11455+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11456+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11457+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11458+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11459+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11460+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11461+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11462+ 11463+ pf=f_img[y_f]+xm_f; 11464+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11465+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11466+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11467+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11468+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11469+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11470+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11471+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11472+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11473+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11474+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11475+ 11476+ pf=f_img[y_f+1]+xm_f; 11477+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11478+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11479+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11480+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11481+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11482+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11483+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11484+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11485+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11486+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11487+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11488+ 11489+ pf=f_img[y_f+2]+xm_f; 11490+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11491+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11492+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11493+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11494+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11495+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11496+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11497+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11498+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11499+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11500+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11501+ 11502+ pf=f_img[y_f+3]+xm_f; 11503+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11504+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11505+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11506+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11507+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11508+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11509+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11510+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11511+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11512+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11513+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11514+ 11515+ pf=f_img[y_f+4]+xm_f; 11516+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11517+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11518+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11519+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11520+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11521+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11522+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11523+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11524+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11525+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11526+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11527+ 11528+ pf=f_img[y_f+5]+xm_f; 11529+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11530+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11531+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11532+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11533+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11534+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11535+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11536+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11537+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11538+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 11539+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 11540+ 11541+ //int xwi; 11542+ //int ywi; 11543+ //f2sum=0; 11544+ //fsum=0; 11545+ //for (int r=-5;r<=5;r++){ 11546+ // ywi=y_f+r; 11547+ // for (int c=-5;c<=5;c++){ 11548+ // xwi=x_f+c; 11549+ // f=f_img[ywi][xwi]; 11550+ // f2sum+=f*f; 11551+ // fsum+=f; 11552+ // (*patch++)=f; 11553+ // } 11554+ //} 11555+ 11556+ (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0; 11557+ (*patch++)=0; (*patch++)=0; 11558+#else 11559+ const unsigned char *pf0 =f_img[y_f-5]+xm_f; 11560+ const unsigned char *pf1 =f_img[y_f-4]+xm_f; 11561+ const unsigned char *pf2 =f_img[y_f-3]+xm_f; 11562+ const unsigned char *pf3 =f_img[y_f-2]+xm_f; 11563+ const unsigned char *pf4 =f_img[y_f-1]+xm_f; 11564+ const unsigned char *pf5 =f_img[y_f ]+xm_f; 11565+ const unsigned char *pf6 =f_img[y_f+1]+xm_f; 11566+ const unsigned char *pf7 =f_img[y_f+2]+xm_f; 11567+ const unsigned char *pf8 =f_img[y_f+3]+xm_f; 11568+ const unsigned char *pf9 =f_img[y_f+4]+xm_f; 11569+ const unsigned char *pf10=f_img[y_f+5]+xm_f; 11570+ 11571+ /* pixel mask */ 11572+ const unsigned char pm[16] = { 11573+ 0xFF,0xFF, 11574+ 0xFF,0xFF, 11575+ 0xFF,0xFF, 11576+ 0,0,0,0,0, 11577+ 0,0,0,0,0}; 11578+ const unsigned char * pm_p = pm; 11579+ 11580+ _asm 11581+ { 11582+ mov ecx,patch /* load patch pointer */ 11583+ mov ebx, pm_p /* load pixel mask pointer */ 11584+ movdqu xmm1,[ebx] /* load pixel mask */ 11585+ 11586+ pxor xmm5,xmm5 /* set xmm5 to 0 accumulator for sum squares */ 11587+ pxor xmm4,xmm4 /* set xmm4 to 0 accumulator for sum */ 11588+ pxor xmm0,xmm0 /* set xmm0 to 0 */ 11589+ 11590+ /* row 0 */ 11591+ mov eax,pf0 /* load image pointer */ 11592+ movdqu xmm7,[eax] /* load 16 pixels */ 11593+ movdqa xmm6,xmm7 11594+ 11595+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11596+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11597+ 11598+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11599+ 11600+ movdqa [ecx+0*22],xmm7 /* move short values to patch */ 11601+ movdqa [ecx+0*22+16],xmm6 /* move short values to patch */ 11602+ 11603+ paddusw xmm4,xmm7 /* accumulate sums */ 11604+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11605+ paddd xmm5,xmm7 /* accumulate sum squares */ 11606+ 11607+ paddw xmm4,xmm6 /* accumulate sums */ 11608+ pmaddwd xmm6,xmm6 /* multiply 16 bit uints into 16 bit uints */ 11609+ paddd xmm5,xmm6 /* accumulate sum squares */ 11610+ 11611+ /* row 1 */ 11612+ mov eax,pf1 /* load image pointer */ 11613+ movdqu xmm7,[eax] /* load 16 pixels */ 11614+ movdqa xmm6,xmm7 11615+ 11616+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11617+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11618+ 11619+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11620+ 11621+ movdqu [ecx+1*22],xmm7 /* move short values to patch */ 11622+ movdqu [ecx+1*22+16],xmm6 /* move short values to patch */ 11623+ 11624+ paddusw xmm4,xmm7 /* accumulate sums */ 11625+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11626+ paddd xmm5,xmm7 /* accumulate sum squares */ 11627+ 11628+ paddw xmm4,xmm6 /* accumulate sums */ 11629+ pmaddwd xmm6,xmm6 /* multiply 16 bit uints into 16 bit uints */ 11630+ paddd xmm5,xmm6 /* accumulate sum squares */ 11631+ 11632+ /* row 2 */ 11633+ mov eax,pf2 /* load image pointer */ 11634+ movdqu xmm7,[eax] /* load 16 pixels */ 11635+ movdqa xmm6,xmm7 11636+ 11637+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11638+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11639+ 11640+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11641+ 11642+ movdqu [ecx+2*22],xmm7 /* move short values to patch */ 11643+ movdqu [ecx+2*22+16],xmm6 /* move short values to patch */ 11644+ 11645+ paddusw xmm4,xmm7 /* accumulate sums */ 11646+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11647+ paddd xmm5,xmm7 /* accumulate sum squares */ 11648+ 11649+ paddw xmm4,xmm6 /* accumulate sums */ 11650+ pmaddwd xmm6,xmm6 /* multiply 16 bit uints into 16 bit uints */ 11651+ paddd xmm5,xmm6 /* accumulate sum squares */ 11652+ 11653+ /* row 3 */ 11654+ mov eax,pf3 /* load image pointer */ 11655+ movdqu xmm7,[eax] /* load 16 pixels */ 11656+ movdqa xmm6,xmm7 11657+ 11658+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11659+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11660+ 11661+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11662+ 11663+ movdqu [ecx+3*22],xmm7 /* move short values to patch */ 11664+ movdqu [ecx+3*22+16],xmm6 /* move short values to patch */ 11665+ 11666+ paddusw xmm4,xmm7 /* accumulate sums */ 11667+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11668+ paddd xmm5,xmm7 /* accumulate sum squares */ 11669+ 11670+ paddw xmm4,xmm6 /* accumulate sums */ 11671+ pmaddwd xmm6,xmm6 /* multiply 16 bit uints into 16 bit uints */ 11672+ paddd xmm5,xmm6 /* accumulate sum squares */ 11673+ 11674+ /* row 4 */ 11675+ mov eax,pf4 /* load image pointer */ 11676+ movdqu xmm7,[eax] /* load 16 pixels */ 11677+ movdqa xmm6,xmm7 11678+ 11679+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11680+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11681+ 11682+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11683+ 11684+ movdqu [ecx+4*22],xmm7 /* move short values to patch */ 11685+ movdqu [ecx+4*22+16],xmm6 /* move short values to patch */ 11686+ 11687+ paddusw xmm4,xmm7 /* accumulate sums */ 11688+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11689+ paddd xmm5,xmm7 /* accumulate sum squares */ 11690+ 11691+ paddw xmm4,xmm6 /* accumulate sums */ 11692+ pmaddwd xmm6,xmm6 /* multiply 16 bit uints into 16 bit uints */ 11693+ paddd xmm5,xmm6 /* accumulate sum squares */ 11694+ 11695+ /* row 5 */ 11696+ mov eax,pf5 /* load image pointer */ 11697+ movdqu xmm7,[eax] /* load 16 pixels */ 11698+ movdqa xmm6,xmm7 11699+ 11700+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11701+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11702+ 11703+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11704+ 11705+ movdqu [ecx+5*22],xmm7 /* move short values to patch */ 11706+ movdqu [ecx+5*22+16],xmm6 /* move short values to patch */ 11707+ 11708+ paddusw xmm4,xmm7 /* accumulate sums */ 11709+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11710+ paddd xmm5,xmm7 /* accumulate sum squares */ 11711+ 11712+ paddw xmm4,xmm6 /* accumulate sums */ 11713+ pmaddwd xmm6,xmm6 /* multiply 16 bit uints into 16 bit uints */ 11714+ paddd xmm5,xmm6 /* accumulate sum squares */ 11715+ 11716+ /* row 6 */ 11717+ mov eax,pf6 /* load image pointer */ 11718+ movdqu xmm7,[eax] /* load 16 pixels */ 11719+ movdqa xmm6,xmm7 11720+ 11721+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11722+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11723+ 11724+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11725+ 11726+ movdqu [ecx+6*22],xmm7 /* move short values to patch */ 11727+ movdqu [ecx+6*22+16],xmm6 /* move short values to patch */ 11728+ 11729+ paddusw xmm4,xmm7 /* accumulate sums */ 11730+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11731+ paddd xmm5,xmm7 /* accumulate sum squares */ 11732+ 11733+ paddw xmm4,xmm6 /* accumulate sums */ 11734+ pmaddwd xmm6,xmm6 /* multiply 16 bit uints into 16 bit uints */ 11735+ paddd xmm5,xmm6 /* accumulate sum squares */ 11736+ 11737+ /* row 7 */ 11738+ mov eax,pf7 /* load image pointer */ 11739+ movdqu xmm7,[eax] /* load 16 pixels */ 11740+ movdqa xmm6,xmm7 11741+ 11742+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11743+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11744+ 11745+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11746+ 11747+ movdqu [ecx+7*22],xmm7 /* move short values to patch */ 11748+ movdqu [ecx+7*22+16],xmm6 /* move short values to patch */ 11749+ 11750+ paddusw xmm4,xmm7 /* accumulate sums */ 11751+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11752+ paddd xmm5,xmm7 /* accumulate sum squares */ 11753+ 11754+ paddw xmm4,xmm6 /* accumulate sums */ 11755+ pmaddwd xmm6,xmm6 /* multiply 16 bit uints into 16 bit uints */ 11756+ paddd xmm5,xmm6 /* accumulate sum squares */ 11757+ 11758+ /* row 8 */ 11759+ mov eax,pf8 /* load image pointer */ 11760+ movdqu xmm7,[eax] /* load 16 pixels */ 11761+ movdqa xmm6,xmm7 11762+ 11763+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11764+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11765+ 11766+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11767+ 11768+ movdqa [ecx+8*22],xmm7 /* move short values to patch */ 11769+ movdqa [ecx+8*22+16],xmm6 /* move short values to patch */ 11770+ 11771+ paddusw xmm4,xmm7 /* accumulate sums */ 11772+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11773+ paddd xmm5,xmm7 /* accumulate sum squares */ 11774+ 11775+ paddw xmm4,xmm6 /* accumulate sums */ 11776+ pmaddwd xmm6,xmm6 /* multiply 16 bit uints into 16 bit uints */ 11777+ paddd xmm5,xmm6 /* accumulate sum squares */ 11778+ 11779+ /* row 9 */ 11780+ mov eax,pf9 /* load image pointer */ 11781+ movdqu xmm7,[eax] /* load 16 pixels */ 11782+ movdqa xmm6,xmm7 11783+ 11784+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11785+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11786+ 11787+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11788+ 11789+ movdqu [ecx+9*22],xmm7 /* move short values to patch */ 11790+ movdqu [ecx+9*22+16],xmm6 /* move short values to patch */ 11791+ 11792+ paddusw xmm4,xmm7 /* accumulate sums */ 11793+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11794+ paddd xmm5,xmm7 /* accumulate sum squares */ 11795+ 11796+ paddw xmm4,xmm6 /* accumulate sums */ 11797+ pmaddwd xmm6,xmm6 /* multiply 16 bit uints into 16 bit uints */ 11798+ paddd xmm5,xmm6 /* accumulate sum squares */ 11799+ 11800+ /* row 10 */ 11801+ mov eax,pf10 /* load image pointer */ 11802+ movdqu xmm7,[eax] /* load 16 pixels */ 11803+ movdqa xmm6,xmm7 11804+ 11805+ punpcklbw xmm7,xmm0 /* unpack low pixels (first 8)*/ 11806+ punpckhbw xmm6,xmm0 /* unpack high pixels (last 8)*/ 11807+ 11808+ pand xmm6,xmm1 /* mask out pixels 12-16 */ 11809+ 11810+ movdqu [ecx+10*22],xmm7 /* move short values to patch */ 11811+ movdqu [ecx+10*22+16],xmm6 /* move short values to patch */ 11812+ 11813+ paddusw xmm4,xmm7 /* accumulate sums */ 11814+ pmaddwd xmm7,xmm7 /* multiply 16 bit ints and add into 32 bit ints */ 11815+ paddd xmm5,xmm7 /* accumulate sum squares */ 11816+ 11817+ paddw xmm4,xmm6 /* accumulate sums */ 11818+ pmaddwd xmm6,xmm6 /* multiply 16 bit ints and add into 32 bit ints */ 11819+ paddd xmm5,xmm6 /* accumulate sum squares */ 11820+ 11821+ /* add up the sum squares */ 11822+ movhlps xmm0,xmm5 /* high half to low half */ 11823+ paddd xmm5,xmm0 /* add high to low */ 11824+ pshuflw xmm0,xmm5, 0xE /* reshuffle */ 11825+ paddd xmm5,xmm0 /* add remaining */ 11826+ movd f2sum,xmm5 11827+ 11828+ /* add up the sum */ 11829+ movhlps xmm0,xmm4 11830+ paddw xmm4,xmm0 /* halves added */ 11831+ pshuflw xmm0,xmm4,0xE 11832+ paddw xmm4,xmm0 /* quarters added */ 11833+ pshuflw xmm0,xmm4,0x1 11834+ paddw xmm4,xmm0 /* eighth added */ 11835+ movd fsum, xmm4 11836+ 11837+ emms 11838+ } 11839+ 11840+ fsum = fsum & 0xFFFF; 11841+ 11842+ patch[126] = 0; 11843+ patch[127] = 0; 11844+#endif /* DB_USE_SSE2 */ 11845+ 11846+ *sum= (float) fsum; 11847+ den=(121.0f*f2sum-fsum*fsum); 11848+ *recip= (float)((den!=0.0)?1.0/den:0.0); 11849+} 11850+ 11851+void AffineWarpPointOffset(float &r_w,float &c_w,double Hinv[9],int r,int c) 11852+{ 11853+ r_w=(float)(Hinv[3]*c+Hinv[4]*r); 11854+ c_w=(float)(Hinv[0]*c+Hinv[1]*r); 11855+} 11856+ 11857+ 11858+ 11859+/*! 11860+Prewarp the patches with given affine transform. For a given homogeneous point "x", "H*x" is 11861+the warped point and for any displacement "d" in the warped image resulting in point "y", the 11862+corresponding point in the original image is given by "Hinv*y", which can be simplified for affine H. 11863+If "affine" is 1, then nearest neighbor method is used, else if it is 2, then 11864+bilinear method is used. 11865+ */ 11866+inline void db_SignedSquareNormCorr11x11_PreAlign_AffinePatchWarp_u(short *patch,const unsigned char * const *f_img, 11867+ int xi,int yi,float *sum,float *recip, 11868+ const double Hinv[9],int affine) 11869+{ 11870+ float den; 11871+ short f; 11872+ int f2sum,fsum; 11873+ 11874+ f2sum=0; 11875+ fsum=0; 11876+ 11877+ if (affine==1) 11878+ { 11879+ for (int r=0;r<11;r++){ 11880+ for (int c=0;c<11;c++){ 11881+ f=f_img[yi+AffineWarpPoint_NN_LUT_y[r][c]][xi+AffineWarpPoint_NN_LUT_x[r][c]]; 11882+ f2sum+=f*f; 11883+ fsum+=f; 11884+ (*patch++)=f; 11885+ } 11886+ } 11887+ } 11888+ else if (affine==2) 11889+ { 11890+ for (int r=0;r<11;r++){ 11891+ for (int c=0;c<11;c++){ 11892+ f=db_BilinearInterpolation(yi+AffineWarpPoint_BL_LUT_y[r][c] 11893+ ,xi+AffineWarpPoint_BL_LUT_x[r][c],f_img); 11894+ f2sum+=f*f; 11895+ fsum+=f; 11896+ (*patch++)=f; 11897+ } 11898+ } 11899+ } 11900+ 11901+ 11902+ 11903+ (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0; 11904+ (*patch++)=0; (*patch++)=0; 11905+ 11906+ *sum= (float) fsum; 11907+ den=(121.0f*f2sum-fsum*fsum); 11908+ *recip= (float)((den!=0.0)?1.0/den:0.0); 11909+} 11910+ 11911+ 11912+inline float db_SignedSquareNormCorr11x11_Post_u(unsigned char **f_img,unsigned char **g_img,int x_f,int y_f,int x_g,int y_g, 11913+ float fsum_gsum,float f_recip_g_recip) 11914+{ 11915+ unsigned char *pf,*pg; 11916+ int fgsum; 11917+ float fg_corr; 11918+ int xm_f,xm_g; 11919+ 11920+ xm_f=x_f-5; 11921+ xm_g=x_g-5; 11922+ 11923+ pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g; 11924+ fgsum=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11925+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11926+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11927+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11928+ 11929+ pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g; 11930+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11931+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11932+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11933+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11934+ 11935+ pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g; 11936+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11937+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11938+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11939+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11940+ 11941+ pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g; 11942+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11943+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11944+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11945+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11946+ 11947+ pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g; 11948+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11949+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11950+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11951+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11952+ 11953+ pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g; 11954+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11955+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11956+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11957+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11958+ 11959+ pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g; 11960+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11961+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11962+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11963+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11964+ 11965+ pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g; 11966+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11967+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11968+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11969+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11970+ 11971+ pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g; 11972+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11973+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11974+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11975+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11976+ 11977+ pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g; 11978+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11979+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11980+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11981+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11982+ 11983+ pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g; 11984+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11985+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11986+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 11987+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 11988+ 11989+ fg_corr=121.0f*fgsum-fsum_gsum; 11990+ if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip); 11991+ return(-fg_corr*fg_corr*f_recip_g_recip); 11992+} 11993+ 11994+float db_SignedSquareNormCorr21x21Aligned_Post_s(const short *f_patch,const short *g_patch,float fsum_gsum,float f_recip_g_recip) 11995+{ 11996+ float fgsum,fg_corr; 11997+ 11998+ fgsum= (float) db_ScalarProduct512_s(f_patch,g_patch); 11999+ 12000+ fg_corr=441.0f*fgsum-fsum_gsum; 12001+ if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip); 12002+ return(-fg_corr*fg_corr*f_recip_g_recip); 12003+} 12004+ 12005+ 12006+float db_SignedSquareNormCorr11x11Aligned_Post_s(const short *f_patch,const short *g_patch,float fsum_gsum,float f_recip_g_recip) 12007+{ 12008+ float fgsum,fg_corr; 12009+ 12010+ fgsum= (float) db_ScalarProduct128_s(f_patch,g_patch); 12011+ 12012+ fg_corr=121.0f*fgsum-fsum_gsum; 12013+ if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip); 12014+ return(-fg_corr*fg_corr*f_recip_g_recip); 12015+} 12016+ 12017+float db_SignedSquareNormCorr5x5Aligned_Post_s(const short *f_patch,const short *g_patch,float fsum_gsum,float f_recip_g_recip) 12018+{ 12019+ float fgsum,fg_corr; 12020+ 12021+ fgsum= (float) db_ScalarProduct32_s(f_patch,g_patch); 12022+ 12023+ fg_corr=25.0f*fgsum-fsum_gsum; 12024+ if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip); 12025+ return(-fg_corr*fg_corr*f_recip_g_recip); 12026+} 12027+ 12028+ 12029+inline float db_SignedSquareNormCorr15x15_u(unsigned char **f_img,unsigned char **g_img,int x_f,int y_f,int x_g,int y_g) 12030+{ 12031+ unsigned char *pf,*pg; 12032+ float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den; 12033+ int xm_f,xm_g; 12034+ 12035+ xm_f=x_f-7; 12036+ xm_g=x_g-7; 12037+ fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0; 12038+ 12039+ pf=f_img[y_f-7]+xm_f; pg=g_img[y_g-7]+xm_g; 12040+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12041+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12042+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12043+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12044+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12045+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12046+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12047+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12048+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12049+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12050+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12051+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12052+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12053+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12054+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12055+ 12056+ pf=f_img[y_f-6]+xm_f; pg=g_img[y_g-6]+xm_g; 12057+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12058+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12059+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12060+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12061+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12062+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12063+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12064+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12065+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12066+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12067+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12068+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12069+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12070+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12071+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12072+ 12073+ pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g; 12074+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12075+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12076+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12077+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12078+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12079+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12080+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12081+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12082+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12083+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12084+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12085+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12086+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12087+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12088+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12089+ 12090+ pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g; 12091+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12092+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12093+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12094+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12095+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12096+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12097+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12098+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12099+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12100+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12101+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12102+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12103+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12104+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12105+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12106+ 12107+ pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g; 12108+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12109+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12110+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12111+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12112+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12113+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12114+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12115+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12116+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12117+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12118+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12119+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12120+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12121+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12122+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12123+ 12124+ pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g; 12125+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12126+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12127+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12128+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12129+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12130+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12131+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12132+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12133+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12134+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12135+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12136+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12137+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12138+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12139+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12140+ 12141+ pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g; 12142+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12143+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12144+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12145+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12146+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12147+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12148+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12149+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12150+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12151+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12152+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12153+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12154+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12155+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12156+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12157+ 12158+ pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g; 12159+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12160+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12161+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12162+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12163+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12164+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12165+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12166+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12167+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12168+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12169+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12170+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12171+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12172+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12173+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12174+ 12175+ pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g; 12176+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12177+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12178+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12179+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12180+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12181+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12182+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12183+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12184+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12185+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12186+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12187+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12188+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12189+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12190+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12191+ 12192+ pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g; 12193+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12194+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12195+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12196+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12197+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12198+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12199+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12200+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12201+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12202+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12203+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12204+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12205+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12206+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12207+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12208+ 12209+ pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g; 12210+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12211+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12212+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12213+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12214+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12215+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12216+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12217+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12218+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12219+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12220+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12221+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12222+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12223+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12224+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12225+ 12226+ pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g; 12227+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12228+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12229+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12230+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12231+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12232+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12233+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12234+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12235+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12236+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12237+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12238+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12239+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12240+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12241+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12242+ 12243+ pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g; 12244+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12245+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12246+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12247+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12248+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12249+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12250+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12251+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12252+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12253+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12254+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12255+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12256+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12257+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12258+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12259+ 12260+ pf=f_img[y_f+6]+xm_f; pg=g_img[y_g+6]+xm_g; 12261+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12262+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12263+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12264+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12265+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12266+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12267+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12268+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12269+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12270+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12271+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12272+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12273+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12274+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12275+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12276+ 12277+ pf=f_img[y_f+7]+xm_f; pg=g_img[y_g+7]+xm_g; 12278+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12279+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12280+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12281+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12282+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12283+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12284+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12285+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12286+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12287+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12288+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12289+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12290+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12291+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12292+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12293+ 12294+ fg_corr=225.0f*fgsum-fsum*gsum; 12295+ den=(225.0f*f2sum-fsum*fsum)*(225.0f*g2sum-gsum*gsum); 12296+ if(den!=0.0) 12297+ { 12298+ if(fg_corr>=0.0) return(fg_corr*fg_corr/den); 12299+ return(-fg_corr*fg_corr/den); 12300+ } 12301+ return(0.0); 12302+} 12303+ 12304+inline float db_SignedSquareNormCorr7x7_f(float **f_img,float **g_img,int x_f,int y_f,int x_g,int y_g) 12305+{ 12306+ float f,g,*pf,*pg,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den; 12307+ int xm_f,xm_g; 12308+ 12309+ xm_f=x_f-3; 12310+ xm_g=x_g-3; 12311+ fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0; 12312+ 12313+ pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g; 12314+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12315+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12316+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12317+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12318+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12319+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12320+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12321+ 12322+ pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g; 12323+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12324+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12325+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12326+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12327+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12328+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12329+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12330+ 12331+ pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g; 12332+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12333+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12334+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12335+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12336+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12337+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12338+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12339+ 12340+ pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g; 12341+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12342+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12343+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12344+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12345+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12346+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12347+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12348+ 12349+ pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g; 12350+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12351+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12352+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12353+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12354+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12355+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12356+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12357+ 12358+ pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g; 12359+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12360+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12361+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12362+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12363+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12364+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12365+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12366+ 12367+ pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g; 12368+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12369+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12370+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12371+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12372+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12373+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12374+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12375+ 12376+ fg_corr=49.0f*fgsum-fsum*gsum; 12377+ den=(49.0f*f2sum-fsum*fsum)*(49.0f*g2sum-gsum*gsum); 12378+ if(den!=0.0) 12379+ { 12380+ if(fg_corr>=0.0) return(fg_corr*fg_corr/den); 12381+ return(-fg_corr*fg_corr/den); 12382+ } 12383+ return(0.0); 12384+} 12385+ 12386+inline float db_SignedSquareNormCorr9x9_f(float **f_img,float **g_img,int x_f,int y_f,int x_g,int y_g) 12387+{ 12388+ float f,g,*pf,*pg,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den; 12389+ int xm_f,xm_g; 12390+ 12391+ xm_f=x_f-4; 12392+ xm_g=x_g-4; 12393+ fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0; 12394+ 12395+ pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g; 12396+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12397+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12398+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12399+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12400+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12401+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12402+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12403+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12404+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12405+ 12406+ pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g; 12407+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12408+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12409+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12410+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12411+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12412+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12413+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12414+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12415+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12416+ 12417+ pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g; 12418+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12419+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12420+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12421+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12422+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12423+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12424+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12425+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12426+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12427+ 12428+ pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g; 12429+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12430+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12431+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12432+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12433+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12434+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12435+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12436+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12437+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12438+ 12439+ pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g; 12440+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12441+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12442+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12443+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12444+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12445+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12446+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12447+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12448+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12449+ 12450+ pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g; 12451+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12452+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12453+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12454+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12455+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12456+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12457+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12458+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12459+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12460+ 12461+ pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g; 12462+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12463+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12464+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12465+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12466+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12467+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12468+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12469+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12470+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12471+ 12472+ pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g; 12473+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12474+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12475+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12476+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12477+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12478+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12479+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12480+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12481+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12482+ 12483+ pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g; 12484+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12485+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12486+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12487+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12488+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12489+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12490+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12491+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12492+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12493+ 12494+ fg_corr=81.0f*fgsum-fsum*gsum; 12495+ den=(81.0f*f2sum-fsum*fsum)*(81.0f*g2sum-gsum*gsum); 12496+ if(den!=0.0) 12497+ { 12498+ if(fg_corr>=0.0) return(fg_corr*fg_corr/den); 12499+ return(-fg_corr*fg_corr/den); 12500+ } 12501+ return(0.0); 12502+} 12503+ 12504+inline float db_SignedSquareNormCorr11x11_f(float **f_img,float **g_img,int x_f,int y_f,int x_g,int y_g) 12505+{ 12506+ float *pf,*pg; 12507+ float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den; 12508+ int xm_f,xm_g; 12509+ 12510+ xm_f=x_f-5; 12511+ xm_g=x_g-5; 12512+ fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0; 12513+ 12514+ pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g; 12515+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12516+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12517+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12518+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12519+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12520+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12521+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12522+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12523+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12524+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12525+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12526+ 12527+ pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g; 12528+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12529+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12530+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12531+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12532+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12533+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12534+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12535+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12536+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12537+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12538+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12539+ 12540+ pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g; 12541+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12542+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12543+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12544+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12545+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12546+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12547+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12548+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12549+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12550+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12551+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12552+ 12553+ pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g; 12554+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12555+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12556+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12557+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12558+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12559+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12560+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12561+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12562+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12563+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12564+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12565+ 12566+ pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g; 12567+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12568+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12569+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12570+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12571+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12572+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12573+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12574+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12575+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12576+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12577+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12578+ 12579+ pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g; 12580+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12581+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12582+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12583+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12584+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12585+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12586+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12587+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12588+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12589+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12590+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12591+ 12592+ pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g; 12593+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12594+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12595+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12596+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12597+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12598+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12599+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12600+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12601+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12602+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12603+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12604+ 12605+ pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g; 12606+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12607+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12608+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12609+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12610+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12611+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12612+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12613+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12614+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12615+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12616+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12617+ 12618+ pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g; 12619+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12620+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12621+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12622+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12623+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12624+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12625+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12626+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12627+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12628+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12629+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12630+ 12631+ pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g; 12632+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12633+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12634+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12635+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12636+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12637+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12638+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12639+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12640+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12641+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12642+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12643+ 12644+ pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g; 12645+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12646+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12647+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12648+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12649+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12650+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12651+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12652+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12653+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12654+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12655+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 12656+ 12657+ fg_corr=121.0f*fgsum-fsum*gsum; 12658+ den=(121.0f*f2sum-fsum*fsum)*(121.0f*g2sum-gsum*gsum); 12659+ if(den!=0.0) 12660+ { 12661+ if(fg_corr>=0.0) return(fg_corr*fg_corr/den); 12662+ return(-fg_corr*fg_corr/den); 12663+ } 12664+ return(0.0); 12665+} 12666+ 12667+inline void db_SignedSquareNormCorr11x11_Pre_f(float **f_img,int x_f,int y_f,float *sum,float *recip) 12668+{ 12669+ float *pf,den; 12670+ float f,f2sum,fsum; 12671+ int xm_f; 12672+ 12673+ xm_f=x_f-5; 12674+ 12675+ pf=f_img[y_f-5]+xm_f; 12676+ f= *pf++; f2sum=f*f; fsum=f; 12677+ f= *pf++; f2sum+=f*f; fsum+=f; 12678+ f= *pf++; f2sum+=f*f; fsum+=f; 12679+ f= *pf++; f2sum+=f*f; fsum+=f; 12680+ f= *pf++; f2sum+=f*f; fsum+=f; 12681+ f= *pf++; f2sum+=f*f; fsum+=f; 12682+ f= *pf++; f2sum+=f*f; fsum+=f; 12683+ f= *pf++; f2sum+=f*f; fsum+=f; 12684+ f= *pf++; f2sum+=f*f; fsum+=f; 12685+ f= *pf++; f2sum+=f*f; fsum+=f; 12686+ f= *pf; f2sum+=f*f; fsum+=f; 12687+ 12688+ pf=f_img[y_f-4]+xm_f; 12689+ f= *pf++; f2sum+=f*f; fsum+=f; 12690+ f= *pf++; f2sum+=f*f; fsum+=f; 12691+ f= *pf++; f2sum+=f*f; fsum+=f; 12692+ f= *pf++; f2sum+=f*f; fsum+=f; 12693+ f= *pf++; f2sum+=f*f; fsum+=f; 12694+ f= *pf++; f2sum+=f*f; fsum+=f; 12695+ f= *pf++; f2sum+=f*f; fsum+=f; 12696+ f= *pf++; f2sum+=f*f; fsum+=f; 12697+ f= *pf++; f2sum+=f*f; fsum+=f; 12698+ f= *pf++; f2sum+=f*f; fsum+=f; 12699+ f= *pf; f2sum+=f*f; fsum+=f; 12700+ 12701+ pf=f_img[y_f-3]+xm_f; 12702+ f= *pf++; f2sum+=f*f; fsum+=f; 12703+ f= *pf++; f2sum+=f*f; fsum+=f; 12704+ f= *pf++; f2sum+=f*f; fsum+=f; 12705+ f= *pf++; f2sum+=f*f; fsum+=f; 12706+ f= *pf++; f2sum+=f*f; fsum+=f; 12707+ f= *pf++; f2sum+=f*f; fsum+=f; 12708+ f= *pf++; f2sum+=f*f; fsum+=f; 12709+ f= *pf++; f2sum+=f*f; fsum+=f; 12710+ f= *pf++; f2sum+=f*f; fsum+=f; 12711+ f= *pf++; f2sum+=f*f; fsum+=f; 12712+ f= *pf; f2sum+=f*f; fsum+=f; 12713+ 12714+ pf=f_img[y_f-2]+xm_f; 12715+ f= *pf++; f2sum+=f*f; fsum+=f; 12716+ f= *pf++; f2sum+=f*f; fsum+=f; 12717+ f= *pf++; f2sum+=f*f; fsum+=f; 12718+ f= *pf++; f2sum+=f*f; fsum+=f; 12719+ f= *pf++; f2sum+=f*f; fsum+=f; 12720+ f= *pf++; f2sum+=f*f; fsum+=f; 12721+ f= *pf++; f2sum+=f*f; fsum+=f; 12722+ f= *pf++; f2sum+=f*f; fsum+=f; 12723+ f= *pf++; f2sum+=f*f; fsum+=f; 12724+ f= *pf++; f2sum+=f*f; fsum+=f; 12725+ f= *pf; f2sum+=f*f; fsum+=f; 12726+ 12727+ pf=f_img[y_f-1]+xm_f; 12728+ f= *pf++; f2sum+=f*f; fsum+=f; 12729+ f= *pf++; f2sum+=f*f; fsum+=f; 12730+ f= *pf++; f2sum+=f*f; fsum+=f; 12731+ f= *pf++; f2sum+=f*f; fsum+=f; 12732+ f= *pf++; f2sum+=f*f; fsum+=f; 12733+ f= *pf++; f2sum+=f*f; fsum+=f; 12734+ f= *pf++; f2sum+=f*f; fsum+=f; 12735+ f= *pf++; f2sum+=f*f; fsum+=f; 12736+ f= *pf++; f2sum+=f*f; fsum+=f; 12737+ f= *pf++; f2sum+=f*f; fsum+=f; 12738+ f= *pf; f2sum+=f*f; fsum+=f; 12739+ 12740+ pf=f_img[y_f]+xm_f; 12741+ f= *pf++; f2sum+=f*f; fsum+=f; 12742+ f= *pf++; f2sum+=f*f; fsum+=f; 12743+ f= *pf++; f2sum+=f*f; fsum+=f; 12744+ f= *pf++; f2sum+=f*f; fsum+=f; 12745+ f= *pf++; f2sum+=f*f; fsum+=f; 12746+ f= *pf++; f2sum+=f*f; fsum+=f; 12747+ f= *pf++; f2sum+=f*f; fsum+=f; 12748+ f= *pf++; f2sum+=f*f; fsum+=f; 12749+ f= *pf++; f2sum+=f*f; fsum+=f; 12750+ f= *pf++; f2sum+=f*f; fsum+=f; 12751+ f= *pf; f2sum+=f*f; fsum+=f; 12752+ 12753+ pf=f_img[y_f+1]+xm_f; 12754+ f= *pf++; f2sum+=f*f; fsum+=f; 12755+ f= *pf++; f2sum+=f*f; fsum+=f; 12756+ f= *pf++; f2sum+=f*f; fsum+=f; 12757+ f= *pf++; f2sum+=f*f; fsum+=f; 12758+ f= *pf++; f2sum+=f*f; fsum+=f; 12759+ f= *pf++; f2sum+=f*f; fsum+=f; 12760+ f= *pf++; f2sum+=f*f; fsum+=f; 12761+ f= *pf++; f2sum+=f*f; fsum+=f; 12762+ f= *pf++; f2sum+=f*f; fsum+=f; 12763+ f= *pf++; f2sum+=f*f; fsum+=f; 12764+ f= *pf; f2sum+=f*f; fsum+=f; 12765+ 12766+ pf=f_img[y_f+2]+xm_f; 12767+ f= *pf++; f2sum+=f*f; fsum+=f; 12768+ f= *pf++; f2sum+=f*f; fsum+=f; 12769+ f= *pf++; f2sum+=f*f; fsum+=f; 12770+ f= *pf++; f2sum+=f*f; fsum+=f; 12771+ f= *pf++; f2sum+=f*f; fsum+=f; 12772+ f= *pf++; f2sum+=f*f; fsum+=f; 12773+ f= *pf++; f2sum+=f*f; fsum+=f; 12774+ f= *pf++; f2sum+=f*f; fsum+=f; 12775+ f= *pf++; f2sum+=f*f; fsum+=f; 12776+ f= *pf++; f2sum+=f*f; fsum+=f; 12777+ f= *pf; f2sum+=f*f; fsum+=f; 12778+ 12779+ pf=f_img[y_f+3]+xm_f; 12780+ f= *pf++; f2sum+=f*f; fsum+=f; 12781+ f= *pf++; f2sum+=f*f; fsum+=f; 12782+ f= *pf++; f2sum+=f*f; fsum+=f; 12783+ f= *pf++; f2sum+=f*f; fsum+=f; 12784+ f= *pf++; f2sum+=f*f; fsum+=f; 12785+ f= *pf++; f2sum+=f*f; fsum+=f; 12786+ f= *pf++; f2sum+=f*f; fsum+=f; 12787+ f= *pf++; f2sum+=f*f; fsum+=f; 12788+ f= *pf++; f2sum+=f*f; fsum+=f; 12789+ f= *pf++; f2sum+=f*f; fsum+=f; 12790+ f= *pf; f2sum+=f*f; fsum+=f; 12791+ 12792+ pf=f_img[y_f+4]+xm_f; 12793+ f= *pf++; f2sum+=f*f; fsum+=f; 12794+ f= *pf++; f2sum+=f*f; fsum+=f; 12795+ f= *pf++; f2sum+=f*f; fsum+=f; 12796+ f= *pf++; f2sum+=f*f; fsum+=f; 12797+ f= *pf++; f2sum+=f*f; fsum+=f; 12798+ f= *pf++; f2sum+=f*f; fsum+=f; 12799+ f= *pf++; f2sum+=f*f; fsum+=f; 12800+ f= *pf++; f2sum+=f*f; fsum+=f; 12801+ f= *pf++; f2sum+=f*f; fsum+=f; 12802+ f= *pf++; f2sum+=f*f; fsum+=f; 12803+ f= *pf; f2sum+=f*f; fsum+=f; 12804+ 12805+ pf=f_img[y_f+5]+xm_f; 12806+ f= *pf++; f2sum+=f*f; fsum+=f; 12807+ f= *pf++; f2sum+=f*f; fsum+=f; 12808+ f= *pf++; f2sum+=f*f; fsum+=f; 12809+ f= *pf++; f2sum+=f*f; fsum+=f; 12810+ f= *pf++; f2sum+=f*f; fsum+=f; 12811+ f= *pf++; f2sum+=f*f; fsum+=f; 12812+ f= *pf++; f2sum+=f*f; fsum+=f; 12813+ f= *pf++; f2sum+=f*f; fsum+=f; 12814+ f= *pf++; f2sum+=f*f; fsum+=f; 12815+ f= *pf++; f2sum+=f*f; fsum+=f; 12816+ f= *pf; f2sum+=f*f; fsum+=f; 12817+ 12818+ *sum=fsum; 12819+ den=(121.0f*f2sum-fsum*fsum); 12820+ *recip= (float) ((den!=0.0)?1.0/den:0.0); 12821+} 12822+ 12823+inline void db_SignedSquareNormCorr11x11_PreAlign_f(float *patch,const float * const *f_img,int x_f,int y_f,float *sum,float *recip) 12824+{ 12825+ const float *pf; 12826+ float den,f,f2sum,fsum; 12827+ int xm_f; 12828+ 12829+ xm_f=x_f-5; 12830+ 12831+ pf=f_img[y_f-5]+xm_f; 12832+ f= *pf++; f2sum=f*f; fsum=f; (*patch++)=f; 12833+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12834+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12835+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12836+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12837+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12838+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12839+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12840+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12841+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12842+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12843+ 12844+ pf=f_img[y_f-4]+xm_f; 12845+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12846+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12847+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12848+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12849+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12850+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12851+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12852+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12853+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12854+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12855+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12856+ 12857+ pf=f_img[y_f-3]+xm_f; 12858+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12859+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12860+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12861+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12862+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12863+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12864+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12865+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12866+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12867+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12868+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12869+ 12870+ pf=f_img[y_f-2]+xm_f; 12871+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12872+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12873+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12874+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12875+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12876+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12877+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12878+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12879+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12880+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12881+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12882+ 12883+ pf=f_img[y_f-1]+xm_f; 12884+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12885+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12886+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12887+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12888+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12889+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12890+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12891+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12892+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12893+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12894+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12895+ 12896+ pf=f_img[y_f]+xm_f; 12897+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12898+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12899+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12900+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12901+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12902+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12903+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12904+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12905+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12906+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12907+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12908+ 12909+ pf=f_img[y_f+1]+xm_f; 12910+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12911+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12912+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12913+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12914+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12915+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12916+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12917+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12918+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12919+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12920+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12921+ 12922+ pf=f_img[y_f+2]+xm_f; 12923+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12924+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12925+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12926+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12927+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12928+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12929+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12930+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12931+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12932+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12933+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12934+ 12935+ pf=f_img[y_f+3]+xm_f; 12936+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12937+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12938+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12939+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12940+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12941+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12942+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12943+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12944+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12945+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12946+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12947+ 12948+ pf=f_img[y_f+4]+xm_f; 12949+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12950+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12951+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12952+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12953+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12954+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12955+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12956+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12957+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12958+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12959+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12960+ 12961+ pf=f_img[y_f+5]+xm_f; 12962+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12963+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12964+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12965+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12966+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12967+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12968+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12969+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12970+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12971+ f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f; 12972+ f= *pf; f2sum+=f*f; fsum+=f; (*patch++)=f; 12973+ 12974+ (*patch++)=0.0; (*patch++)=0.0; (*patch++)=0.0; (*patch++)=0.0; (*patch++)=0.0; 12975+ (*patch++)=0.0; (*patch++)=0.0; 12976+ 12977+ *sum=fsum; 12978+ den=(121.0f*f2sum-fsum*fsum); 12979+ *recip= (float) ((den!=0.0)?1.0/den:0.0); 12980+} 12981+ 12982+inline float db_SignedSquareNormCorr11x11_Post_f(float **f_img,float **g_img,int x_f,int y_f,int x_g,int y_g, 12983+ float fsum_gsum,float f_recip_g_recip) 12984+{ 12985+ float *pf,*pg; 12986+ float fgsum,fg_corr; 12987+ int xm_f,xm_g; 12988+ 12989+ xm_f=x_f-5; 12990+ xm_g=x_g-5; 12991+ 12992+ pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g; 12993+ fgsum=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 12994+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 12995+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 12996+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 12997+ 12998+ pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g; 12999+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13000+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13001+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13002+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 13003+ 13004+ pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g; 13005+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13006+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13007+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13008+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 13009+ 13010+ pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g; 13011+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13012+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13013+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13014+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 13015+ 13016+ pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g; 13017+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13018+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13019+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13020+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 13021+ 13022+ pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g; 13023+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13024+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13025+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13026+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 13027+ 13028+ pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g; 13029+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13030+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13031+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13032+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 13033+ 13034+ pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g; 13035+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13036+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13037+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13038+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 13039+ 13040+ pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g; 13041+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13042+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13043+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13044+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 13045+ 13046+ pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g; 13047+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13048+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13049+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13050+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 13051+ 13052+ pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g; 13053+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13054+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13055+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); 13056+ fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg); 13057+ 13058+ fg_corr=121.0f*fgsum-fsum_gsum; 13059+ if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip); 13060+ return(-fg_corr*fg_corr*f_recip_g_recip); 13061+} 13062+ 13063+inline float db_SignedSquareNormCorr11x11Aligned_Post_f(const float *f_patch,const float *g_patch,float fsum_gsum,float f_recip_g_recip) 13064+{ 13065+ float fgsum,fg_corr; 13066+ 13067+ fgsum=db_ScalarProduct128Aligned16_f(f_patch,g_patch); 13068+ 13069+ fg_corr=121.0f*fgsum-fsum_gsum; 13070+ if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip); 13071+ return(-fg_corr*fg_corr*f_recip_g_recip); 13072+} 13073+ 13074+inline float db_SignedSquareNormCorr15x15_f(float **f_img,float **g_img,int x_f,int y_f,int x_g,int y_g) 13075+{ 13076+ float *pf,*pg; 13077+ float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den; 13078+ int xm_f,xm_g; 13079+ 13080+ xm_f=x_f-7; 13081+ xm_g=x_g-7; 13082+ fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0; 13083+ 13084+ pf=f_img[y_f-7]+xm_f; pg=g_img[y_g-7]+xm_g; 13085+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13086+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13087+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13088+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13089+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13090+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13091+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13092+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13093+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13094+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13095+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13096+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13097+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13098+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13099+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13100+ 13101+ pf=f_img[y_f-6]+xm_f; pg=g_img[y_g-6]+xm_g; 13102+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13103+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13104+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13105+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13106+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13107+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13108+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13109+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13110+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13111+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13112+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13113+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13114+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13115+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13116+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13117+ 13118+ pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g; 13119+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13120+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13121+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13122+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13123+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13124+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13125+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13126+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13127+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13128+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13129+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13130+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13131+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13132+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13133+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13134+ 13135+ pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g; 13136+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13137+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13138+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13139+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13140+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13141+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13142+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13143+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13144+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13145+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13146+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13147+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13148+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13149+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13150+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13151+ 13152+ pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g; 13153+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13154+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13155+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13156+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13157+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13158+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13159+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13160+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13161+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13162+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13163+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13164+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13165+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13166+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13167+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13168+ 13169+ pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g; 13170+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13171+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13172+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13173+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13174+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13175+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13176+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13177+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13178+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13179+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13180+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13181+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13182+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13183+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13184+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13185+ 13186+ pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g; 13187+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13188+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13189+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13190+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13191+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13192+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13193+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13194+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13195+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13196+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13197+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13198+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13199+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13200+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13201+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13202+ 13203+ pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g; 13204+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13205+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13206+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13207+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13208+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13209+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13210+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13211+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13212+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13213+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13214+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13215+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13216+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13217+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13218+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13219+ 13220+ pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g; 13221+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13222+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13223+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13224+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13225+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13226+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13227+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13228+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13229+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13230+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13231+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13232+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13233+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13234+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13235+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13236+ 13237+ pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g; 13238+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13239+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13240+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13241+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13242+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13243+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13244+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13245+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13246+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13247+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13248+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13249+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13250+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13251+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13252+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13253+ 13254+ pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g; 13255+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13256+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13257+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13258+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13259+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13260+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13261+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13262+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13263+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13264+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13265+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13266+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13267+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13268+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13269+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13270+ 13271+ pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g; 13272+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13273+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13274+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13275+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13276+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13277+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13278+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13279+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13280+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13281+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13282+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13283+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13284+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13285+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13286+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13287+ 13288+ pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g; 13289+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13290+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13291+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13292+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13293+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13294+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13295+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13296+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13297+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13298+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13299+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13300+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13301+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13302+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13303+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13304+ 13305+ pf=f_img[y_f+6]+xm_f; pg=g_img[y_g+6]+xm_g; 13306+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13307+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13308+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13309+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13310+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13311+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13312+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13313+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13314+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13315+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13316+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13317+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13318+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13319+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13320+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13321+ 13322+ pf=f_img[y_f+7]+xm_f; pg=g_img[y_g+7]+xm_g; 13323+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13324+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13325+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13326+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13327+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13328+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13329+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13330+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13331+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13332+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13333+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13334+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13335+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13336+ f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13337+ f= *pf; g= *pg; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g; 13338+ 13339+ fg_corr=225.0f*fgsum-fsum*gsum; 13340+ den=(225.0f*f2sum-fsum*fsum)*(225.0f*g2sum-gsum*gsum); 13341+ if(den!=0.0) 13342+ { 13343+ if(fg_corr>=0.0) return(fg_corr*fg_corr/den); 13344+ return(-fg_corr*fg_corr/den); 13345+ } 13346+ return(0.0); 13347+} 13348+ 13349+db_Bucket_f** db_AllocBuckets_f(int nr_h,int nr_v,int bd) 13350+{ 13351+ int i,j; 13352+ db_Bucket_f **bp,*b; 13353+ 13354+ b=new db_Bucket_f [(nr_h+2)*(nr_v+2)]; 13355+ bp=new db_Bucket_f* [(nr_v+2)]; 13356+ bp=bp+1; 13357+ for(i= -1;i<=nr_v;i++) 13358+ { 13359+ bp[i]=b+1+(nr_h+2)*(i+1); 13360+ for(j= -1;j<=nr_h;j++) 13361+ { 13362+ bp[i][j].ptr=new db_PointInfo_f [bd]; 13363+ } 13364+ } 13365+ 13366+ return(bp); 13367+} 13368+ 13369+db_Bucket_u** db_AllocBuckets_u(int nr_h,int nr_v,int bd) 13370+{ 13371+ int i,j; 13372+ db_Bucket_u **bp,*b; 13373+ 13374+ b=new db_Bucket_u [(nr_h+2)*(nr_v+2)]; 13375+ bp=new db_Bucket_u* [(nr_v+2)]; 13376+ bp=bp+1; 13377+ for(i= -1;i<=nr_v;i++) 13378+ { 13379+ bp[i]=b+1+(nr_h+2)*(i+1); 13380+ for(j= -1;j<=nr_h;j++) 13381+ { 13382+ bp[i][j].ptr=new db_PointInfo_u [bd]; 13383+ } 13384+ } 13385+ 13386+ return(bp); 13387+} 13388+ 13389+void db_FreeBuckets_f(db_Bucket_f **bp,int nr_h,int nr_v) 13390+{ 13391+ int i,j; 13392+ 13393+ for(i= -1;i<=nr_v;i++) for(j= -1;j<=nr_h;j++) 13394+ { 13395+ delete [] bp[i][j].ptr; 13396+ } 13397+ delete [] (bp[-1]-1); 13398+ delete [] (bp-1); 13399+} 13400+ 13401+void db_FreeBuckets_u(db_Bucket_u **bp,int nr_h,int nr_v) 13402+{ 13403+ int i,j; 13404+ 13405+ for(i= -1;i<=nr_v;i++) for(j= -1;j<=nr_h;j++) 13406+ { 13407+ delete [] bp[i][j].ptr; 13408+ } 13409+ delete [] (bp[-1]-1); 13410+ delete [] (bp-1); 13411+} 13412+ 13413+void db_EmptyBuckets_f(db_Bucket_f **bp,int nr_h,int nr_v) 13414+{ 13415+ int i,j; 13416+ for(i= -1;i<=nr_v;i++) for(j= -1;j<=nr_h;j++) bp[i][j].nr=0; 13417+} 13418+ 13419+void db_EmptyBuckets_u(db_Bucket_u **bp,int nr_h,int nr_v) 13420+{ 13421+ int i,j; 13422+ for(i= -1;i<=nr_v;i++) for(j= -1;j<=nr_h;j++) bp[i][j].nr=0; 13423+} 13424+ 13425+float* db_FillBuckets_f(float *patch_space,const float * const *f_img,db_Bucket_f **bp,int bw,int bh,int nr_h,int nr_v,int bd,const double *x,const double *y,int nr_corners) 13426+{ 13427+ int i,xi,yi,xpos,ypos,nr; 13428+ db_Bucket_f *br; 13429+ db_PointInfo_f *pir; 13430+ 13431+ db_EmptyBuckets_f(bp,nr_h,nr_v); 13432+ for(i=0;i<nr_corners;i++) 13433+ { 13434+ xi=(int) x[i]; 13435+ yi=(int) y[i]; 13436+ xpos=xi/bw; 13437+ ypos=yi/bh; 13438+ if(xpos>=0 && xpos<nr_h && ypos>=0 && ypos<nr_v) 13439+ { 13440+ br=&bp[ypos][xpos]; 13441+ nr=br->nr; 13442+ if(nr<bd) 13443+ { 13444+ pir=&(br->ptr[nr]); 13445+ pir->x=xi; 13446+ pir->y=yi; 13447+ pir->id=i; 13448+ pir->pir=0; 13449+ pir->patch=patch_space; 13450+ br->nr=nr+1; 13451+ 13452+ db_SignedSquareNormCorr11x11_PreAlign_f(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip)); 13453+ patch_space+=128; 13454+ } 13455+ } 13456+ } 13457+ return(patch_space); 13458+} 13459+ 13460+short* db_FillBuckets_u(short *patch_space,const unsigned char * const *f_img,db_Bucket_u **bp,int bw,int bh,int nr_h,int nr_v,int bd,const double *x,const double *y,int nr_corners,int use_smaller_matching_window, int use_21) 13461+{ 13462+ int i,xi,yi,xpos,ypos,nr; 13463+ db_Bucket_u *br; 13464+ db_PointInfo_u *pir; 13465+ 13466+ db_EmptyBuckets_u(bp,nr_h,nr_v); 13467+ for(i=0;i<nr_corners;i++) 13468+ { 13469+ xi=(int)db_roundi(x[i]); 13470+ yi=(int)db_roundi(y[i]); 13471+ xpos=xi/bw; 13472+ ypos=yi/bh; 13473+ if(xpos>=0 && xpos<nr_h && ypos>=0 && ypos<nr_v) 13474+ { 13475+ br=&bp[ypos][xpos]; 13476+ nr=br->nr; 13477+ if(nr<bd) 13478+ { 13479+ pir=&(br->ptr[nr]); 13480+ pir->x=xi; 13481+ pir->y=yi; 13482+ pir->id=i; 13483+ pir->pir=0; 13484+ pir->patch=patch_space; 13485+ br->nr=nr+1; 13486+ 13487+ if(use_21) 13488+ { 13489+ db_SignedSquareNormCorr21x21_PreAlign_u(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip)); 13490+ patch_space+=512; 13491+ } 13492+ else 13493+ { 13494+ if(!use_smaller_matching_window) 13495+ { 13496+ db_SignedSquareNormCorr11x11_PreAlign_u(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip)); 13497+ patch_space+=128; 13498+ } 13499+ else 13500+ { 13501+ db_SignedSquareNormCorr5x5_PreAlign_u(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip)); 13502+ patch_space+=32; 13503+ } 13504+ } 13505+ } 13506+ } 13507+ } 13508+ return(patch_space); 13509+} 13510+ 13511+ 13512+ 13513+float* db_FillBucketsPrewarped_f(float *patch_space,const float *const *f_img,db_Bucket_f **bp,int bw,int bh,int nr_h,int nr_v,int bd,const double *x,const double *y,int nr_corners,const double H[9]) 13514+{ 13515+ int i,xi,yi,xpos,ypos,nr,wxi,wyi; 13516+ db_Bucket_f *br; 13517+ db_PointInfo_f *pir; 13518+ double xd[2],wx[2]; 13519+ 13520+ db_EmptyBuckets_f(bp,nr_h,nr_v); 13521+ for(i=0;i<nr_corners;i++) 13522+ { 13523+ xd[0]=x[i]; 13524+ xd[1]=y[i]; 13525+ xi=(int) xd[0]; 13526+ yi=(int) xd[1]; 13527+ db_ImageHomographyInhomogenous(wx,H,xd); 13528+ wxi=(int) wx[0]; 13529+ wyi=(int) wx[1]; 13530+ 13531+ xpos=((wxi+bw)/bw)-1; 13532+ ypos=((wyi+bh)/bh)-1; 13533+ if(xpos>= -1 && xpos<=nr_h && ypos>= -1 && ypos<=nr_v) 13534+ { 13535+ br=&bp[ypos][xpos]; 13536+ nr=br->nr; 13537+ if(nr<bd) 13538+ { 13539+ pir=&(br->ptr[nr]); 13540+ pir->x=wxi; 13541+ pir->y=wyi; 13542+ pir->id=i; 13543+ pir->pir=0; 13544+ pir->patch=patch_space; 13545+ br->nr=nr+1; 13546+ 13547+ db_SignedSquareNormCorr11x11_PreAlign_f(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip)); 13548+ patch_space+=128; 13549+ } 13550+ } 13551+ } 13552+ return(patch_space); 13553+} 13554+ 13555+short* db_FillBucketsPrewarped_u(short *patch_space,const unsigned char * const *f_img,db_Bucket_u **bp, 13556+ int bw,int bh,int nr_h,int nr_v,int bd,const double *x,const double *y, 13557+ int nr_corners,const double H[9]) 13558+{ 13559+ int i,xi,yi,xpos,ypos,nr,wxi,wyi; 13560+ db_Bucket_u *br; 13561+ db_PointInfo_u *pir; 13562+ double xd[2],wx[2]; 13563+ 13564+ db_EmptyBuckets_u(bp,nr_h,nr_v); 13565+ for(i=0;i<nr_corners;i++) 13566+ { 13567+ xd[0]=x[i]; 13568+ xd[1]=y[i]; 13569+ xi=(int) db_roundi(xd[0]); 13570+ yi=(int) db_roundi(xd[1]); 13571+ db_ImageHomographyInhomogenous(wx,H,xd); 13572+ wxi=(int) wx[0]; 13573+ wyi=(int) wx[1]; 13574+ 13575+ xpos=((wxi+bw)/bw)-1; 13576+ ypos=((wyi+bh)/bh)-1; 13577+ if(xpos>= -1 && xpos<=nr_h && ypos>= -1 && ypos<=nr_v) 13578+ { 13579+ br=&bp[ypos][xpos]; 13580+ nr=br->nr; 13581+ if(nr<bd) 13582+ { 13583+ pir=&(br->ptr[nr]); 13584+ pir->x=wxi; 13585+ pir->y=wyi; 13586+ pir->id=i; 13587+ pir->pir=0; 13588+ pir->patch=patch_space; 13589+ br->nr=nr+1; 13590+ 13591+ db_SignedSquareNormCorr11x11_PreAlign_u(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip)); 13592+ patch_space+=128; 13593+ } 13594+ } 13595+ } 13596+ return(patch_space); 13597+} 13598+ 13599+ 13600+ 13601+short* db_FillBucketsPrewarpedAffine_u(short *patch_space,const unsigned char * const *f_img,db_Bucket_u **bp, 13602+ int bw,int bh,int nr_h,int nr_v,int bd,const double *x,const double *y, 13603+ int nr_corners,const double H[9],const double Hinv[9],const int warpboundsp[4], 13604+ int affine) 13605+{ 13606+ int i,xi,yi,xpos,ypos,nr,wxi,wyi; 13607+ db_Bucket_u *br; 13608+ db_PointInfo_u *pir; 13609+ double xd[2],wx[2]; 13610+ 13611+ db_EmptyBuckets_u(bp,nr_h,nr_v); 13612+ for(i=0;i<nr_corners;i++) 13613+ { 13614+ xd[0]=x[i]; 13615+ xd[1]=y[i]; 13616+ xi=(int) db_roundi(xd[0]); 13617+ yi=(int) db_roundi(xd[1]); 13618+ db_ImageHomographyInhomogenous(wx,H,xd); 13619+ wxi=(int) wx[0]; 13620+ wyi=(int) wx[1]; 13621+ 13622+ xpos=((wxi+bw)/bw)-1; 13623+ ypos=((wyi+bh)/bh)-1; 13624+ 13625+ 13626+ if (xpos>= -1 && xpos<=nr_h && ypos>= -1 && ypos<=nr_v) 13627+ { 13628+ if( xi>warpboundsp[0] && xi<warpboundsp[1] && yi>warpboundsp[2] && yi<warpboundsp[3]) 13629+ { 13630+ 13631+ br=&bp[ypos][xpos]; 13632+ nr=br->nr; 13633+ if(nr<bd) 13634+ { 13635+ pir=&(br->ptr[nr]); 13636+ pir->x=wxi; 13637+ pir->y=wyi; 13638+ pir->id=i; 13639+ pir->pir=0; 13640+ pir->patch=patch_space; 13641+ br->nr=nr+1; 13642+ 13643+ db_SignedSquareNormCorr11x11_PreAlign_AffinePatchWarp_u(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip),Hinv,affine); 13644+ patch_space+=128; 13645+ } 13646+ } 13647+ } 13648+ } 13649+ return(patch_space); 13650+} 13651+ 13652+ 13653+ 13654+inline void db_MatchPointPair_f(db_PointInfo_f *pir_l,db_PointInfo_f *pir_r, 13655+ unsigned long kA,unsigned long kB) 13656+{ 13657+ int x_l,y_l,x_r,y_r,xm,ym; 13658+ double score; 13659+ 13660+ x_l=pir_l->x; 13661+ y_l=pir_l->y; 13662+ x_r=pir_r->x; 13663+ y_r=pir_r->y; 13664+ xm=x_l-x_r; 13665+ ym=y_l-y_r; 13666+ /*Check if disparity is within the maximum disparity 13667+ with the formula xm^2*256+ym^2*kA<kB 13668+ where kA=256*w^2/h^2 13669+ and kB=256*max_disp^2*w^2*/ 13670+ if(((xm*xm)<<8)+ym*ym*kA<kB) 13671+ { 13672+ /*Correlate*/ 13673+ score=db_SignedSquareNormCorr11x11Aligned_Post_f(pir_l->patch,pir_r->patch, 13674+ (pir_l->sum)*(pir_r->sum), 13675+ (pir_l->recip)*(pir_r->recip)); 13676+ 13677+ if((!(pir_l->pir)) || (score>pir_l->s)) 13678+ { 13679+ /*Update left corner*/ 13680+ pir_l->s=score; 13681+ pir_l->pir=pir_r; 13682+ } 13683+ if((!(pir_r->pir)) || (score>pir_r->s)) 13684+ { 13685+ /*Update right corner*/ 13686+ pir_r->s=score; 13687+ pir_r->pir=pir_l; 13688+ } 13689+ } 13690+} 13691+ 13692+inline void db_MatchPointPair_u(db_PointInfo_u *pir_l,db_PointInfo_u *pir_r, 13693+ unsigned long kA,unsigned long kB, unsigned int rect_window,bool use_smaller_matching_window, int use_21) 13694+{ 13695+ int xm,ym; 13696+ double score; 13697+ bool compute_score; 13698+ 13699+ 13700+ if( rect_window ) 13701+ compute_score = ((unsigned)db_absi(pir_l->x - pir_r->x)<kA && (unsigned)db_absi(pir_l->y - pir_r->y)<kB); 13702+ else 13703+ { /*Check if disparity is within the maximum disparity 13704+ with the formula xm^2*256+ym^2*kA<kB 13705+ where kA=256*w^2/h^2 13706+ and kB=256*max_disp^2*w^2*/ 13707+ xm= pir_l->x - pir_r->x; 13708+ ym= pir_l->y - pir_r->y; 13709+ compute_score = ((xm*xm)<<8)+ym*ym*kA < kB; 13710+ } 13711+ 13712+ if ( compute_score ) 13713+ { 13714+ if(use_21) 13715+ { 13716+ score=db_SignedSquareNormCorr21x21Aligned_Post_s(pir_l->patch,pir_r->patch, 13717+ (pir_l->sum)*(pir_r->sum), 13718+ (pir_l->recip)*(pir_r->recip)); 13719+ } 13720+ else 13721+ { 13722+ /*Correlate*/ 13723+ if(!use_smaller_matching_window) 13724+ { 13725+ score=db_SignedSquareNormCorr11x11Aligned_Post_s(pir_l->patch,pir_r->patch, 13726+ (pir_l->sum)*(pir_r->sum), 13727+ (pir_l->recip)*(pir_r->recip)); 13728+ } 13729+ else 13730+ { 13731+ score=db_SignedSquareNormCorr5x5Aligned_Post_s(pir_l->patch,pir_r->patch, 13732+ (pir_l->sum)*(pir_r->sum), 13733+ (pir_l->recip)*(pir_r->recip)); 13734+ } 13735+ } 13736+ 13737+ if((!(pir_l->pir)) || (score>pir_l->s)) 13738+ { 13739+ /*Update left corner*/ 13740+ pir_l->s=score; 13741+ pir_l->pir=pir_r; 13742+ } 13743+ if((!(pir_r->pir)) || (score>pir_r->s)) 13744+ { 13745+ /*Update right corner*/ 13746+ pir_r->s=score; 13747+ pir_r->pir=pir_l; 13748+ } 13749+ } 13750+} 13751+ 13752+inline void db_MatchPointAgainstBucket_f(db_PointInfo_f *pir_l,db_Bucket_f *b_r, 13753+ unsigned long kA,unsigned long kB) 13754+{ 13755+ int p_r,nr; 13756+ db_PointInfo_f *pir_r; 13757+ 13758+ nr=b_r->nr; 13759+ pir_r=b_r->ptr; 13760+ for(p_r=0;p_r<nr;p_r++) db_MatchPointPair_f(pir_l,pir_r+p_r,kA,kB); 13761+} 13762+ 13763+inline void db_MatchPointAgainstBucket_u(db_PointInfo_u *pir_l,db_Bucket_u *b_r, 13764+ unsigned long kA,unsigned long kB,int rect_window, bool use_smaller_matching_window, int use_21) 13765+{ 13766+ int p_r,nr; 13767+ db_PointInfo_u *pir_r; 13768+ 13769+ nr=b_r->nr; 13770+ pir_r=b_r->ptr; 13771+ 13772+ for(p_r=0;p_r<nr;p_r++) db_MatchPointPair_u(pir_l,pir_r+p_r,kA,kB, rect_window, use_smaller_matching_window, use_21); 13773+ 13774+} 13775+ 13776+void db_MatchBuckets_f(db_Bucket_f **bp_l,db_Bucket_f **bp_r,int nr_h,int nr_v, 13777+ unsigned long kA,unsigned long kB) 13778+{ 13779+ int i,j,k,a,b,br_nr; 13780+ db_Bucket_f *br; 13781+ db_PointInfo_f *pir_l; 13782+ 13783+ /*For all buckets*/ 13784+ for(i=0;i<nr_v;i++) for(j=0;j<nr_h;j++) 13785+ { 13786+ br=&bp_l[i][j]; 13787+ br_nr=br->nr; 13788+ /*For all points in bucket*/ 13789+ for(k=0;k<br_nr;k++) 13790+ { 13791+ pir_l=br->ptr+k; 13792+ for(a=i-1;a<=i+1;a++) 13793+ { 13794+ for(b=j-1;b<=j+1;b++) 13795+ { 13796+ db_MatchPointAgainstBucket_f(pir_l,&bp_r[a][b],kA,kB); 13797+ } 13798+ } 13799+ } 13800+ } 13801+} 13802+ 13803+void db_MatchBuckets_u(db_Bucket_u **bp_l,db_Bucket_u **bp_r,int nr_h,int nr_v, 13804+ unsigned long kA,unsigned long kB,int rect_window,bool use_smaller_matching_window, int use_21) 13805+{ 13806+ int i,j,k,a,b,br_nr; 13807+ db_Bucket_u *br; 13808+ db_PointInfo_u *pir_l; 13809+ 13810+ /*For all buckets*/ 13811+ for(i=0;i<nr_v;i++) for(j=0;j<nr_h;j++) 13812+ { 13813+ br=&bp_l[i][j]; 13814+ br_nr=br->nr; 13815+ /*For all points in bucket*/ 13816+ for(k=0;k<br_nr;k++) 13817+ { 13818+ pir_l=br->ptr+k; 13819+ for(a=i-1;a<=i+1;a++) 13820+ { 13821+ for(b=j-1;b<=j+1;b++) 13822+ { 13823+ db_MatchPointAgainstBucket_u(pir_l,&bp_r[a][b],kA,kB,rect_window,use_smaller_matching_window, use_21); 13824+ } 13825+ } 13826+ } 13827+ } 13828+} 13829+ 13830+void db_CollectMatches_f(db_Bucket_f **bp_l,int nr_h,int nr_v,unsigned long target,int *id_l,int *id_r,int *nr_matches) 13831+{ 13832+ int i,j,k,br_nr; 13833+ unsigned long count; 13834+ db_Bucket_f *br; 13835+ db_PointInfo_f *pir,*pir2; 13836+ 13837+ count=0; 13838+ /*For all buckets*/ 13839+ for(i=0;i<nr_v;i++) for(j=0;j<nr_h;j++) 13840+ { 13841+ br=&bp_l[i][j]; 13842+ br_nr=br->nr; 13843+ /*For all points in bucket*/ 13844+ for(k=0;k<br_nr;k++) 13845+ { 13846+ pir=br->ptr+k; 13847+ pir2=pir->pir; 13848+ if(pir2) 13849+ { 13850+ /*This point has a best match*/ 13851+ if((pir2->pir)==pir) 13852+ { 13853+ /*We have a mutually consistent match*/ 13854+ if(count<target) 13855+ { 13856+ id_l[count]=pir->id; 13857+ id_r[count]=pir2->id; 13858+ count++; 13859+ } 13860+ } 13861+ } 13862+ } 13863+ } 13864+ *nr_matches=count; 13865+} 13866+ 13867+void db_CollectMatches_u(db_Bucket_u **bp_l,int nr_h,int nr_v,unsigned long target,int *id_l,int *id_r,int *nr_matches) 13868+{ 13869+ int i,j,k,br_nr; 13870+ unsigned long count; 13871+ db_Bucket_u *br; 13872+ db_PointInfo_u *pir,*pir2; 13873+ 13874+ count=0; 13875+ /*For all buckets*/ 13876+ for(i=0;i<nr_v;i++) for(j=0;j<nr_h;j++) 13877+ { 13878+ br=&bp_l[i][j]; 13879+ br_nr=br->nr; 13880+ /*For all points in bucket*/ 13881+ for(k=0;k<br_nr;k++) 13882+ { 13883+ pir=br->ptr+k; 13884+ pir2=pir->pir; 13885+ if(pir2) 13886+ { 13887+ /*This point has a best match*/ 13888+ if((pir2->pir)==pir) 13889+ { 13890+ /*We have a mutually consistent match*/ 13891+ if(count<target) 13892+ { 13893+ id_l[count]=pir->id; 13894+ id_r[count]=pir2->id; 13895+ count++; 13896+ } 13897+ } 13898+ } 13899+ } 13900+ } 13901+ *nr_matches=count; 13902+} 13903+ 13904+db_Matcher_f::db_Matcher_f() 13905+{ 13906+ m_w=0; m_h=0; 13907+} 13908+ 13909+db_Matcher_f::~db_Matcher_f() 13910+{ 13911+ Clean(); 13912+} 13913+ 13914+void db_Matcher_f::Clean() 13915+{ 13916+ if(m_w) 13917+ { 13918+ /*Free buckets*/ 13919+ db_FreeBuckets_f(m_bp_l,m_nr_h,m_nr_v); 13920+ db_FreeBuckets_f(m_bp_r,m_nr_h,m_nr_v); 13921+ /*Free space for patch layouts*/ 13922+ delete [] m_patch_space; 13923+ } 13924+ m_w=0; m_h=0; 13925+} 13926+ 13927+unsigned long db_Matcher_f::Init(int im_width,int im_height,double max_disparity,int target_nr_corners) 13928+{ 13929+ Clean(); 13930+ m_w=im_width; 13931+ m_h=im_height; 13932+ m_bw=db_maxi(1,(int) (max_disparity*((double)im_width))); 13933+ m_bh=db_maxi(1,(int) (max_disparity*((double)im_height))); 13934+ m_nr_h=1+(im_width-1)/m_bw; 13935+ m_nr_v=1+(im_height-1)/m_bh; 13936+ m_bd=db_maxi(1,(int)(((double)target_nr_corners)* 13937+ max_disparity*max_disparity)); 13938+ m_target=target_nr_corners; 13939+ m_kA=(long)(256.0*((double)(m_w*m_w))/((double)(m_h*m_h))); 13940+ m_kB=(long)(256.0*max_disparity*max_disparity*((double)(m_w*m_w))); 13941+ 13942+ /*Alloc bucket structure*/ 13943+ m_bp_l=db_AllocBuckets_f(m_nr_h,m_nr_v,m_bd); 13944+ m_bp_r=db_AllocBuckets_f(m_nr_h,m_nr_v,m_bd); 13945+ 13946+ /*Alloc 16byte-aligned space for patch layouts*/ 13947+ m_patch_space=new float [2*(m_nr_h+2)*(m_nr_v+2)*m_bd*128+16]; 13948+ m_aligned_patch_space=db_AlignPointer_f(m_patch_space,16); 13949+ 13950+ return(m_target); 13951+} 13952+ 13953+void db_Matcher_f::Match(const float * const *l_img,const float * const *r_img, 13954+ const double *x_l,const double *y_l,int nr_l,const double *x_r,const double *y_r,int nr_r, 13955+ int *id_l,int *id_r,int *nr_matches,const double H[9]) 13956+{ 13957+ float *ps; 13958+ 13959+ /*Insert the corners into bucket structure*/ 13960+ ps=db_FillBuckets_f(m_aligned_patch_space,l_img,m_bp_l,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_l,y_l,nr_l); 13961+ if(H==0) db_FillBuckets_f(ps,r_img,m_bp_r,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_r,y_r,nr_r); 13962+ else db_FillBucketsPrewarped_f(ps,r_img,m_bp_r,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_r,y_r,nr_r,H); 13963+ 13964+ /*Compute all the necessary match scores*/ 13965+ db_MatchBuckets_f(m_bp_l,m_bp_r,m_nr_h,m_nr_v,m_kA,m_kB); 13966+ 13967+ /*Collect the correspondences*/ 13968+ db_CollectMatches_f(m_bp_l,m_nr_h,m_nr_v,m_target,id_l,id_r,nr_matches); 13969+} 13970+ 13971+db_Matcher_u::db_Matcher_u() 13972+{ 13973+ m_w=0; m_h=0; 13974+ m_rect_window = 0; 13975+ m_bw=m_bh=m_nr_h=m_nr_v=m_bd=m_target=0; 13976+ m_bp_l=m_bp_r=0; 13977+ m_patch_space=m_aligned_patch_space=0; 13978+} 13979+ 13980+db_Matcher_u::db_Matcher_u(const db_Matcher_u& cm) 13981+{ 13982+ Init(cm.m_w, cm.m_h, cm.m_max_disparity, cm.m_target, cm.m_max_disparity_v); 13983+} 13984+ 13985+db_Matcher_u& db_Matcher_u::operator= (const db_Matcher_u& cm) 13986+{ 13987+ if ( this == &cm ) return *this; 13988+ Init(cm.m_w, cm.m_h, cm.m_max_disparity, cm.m_target, cm.m_max_disparity_v); 13989+ return *this; 13990+} 13991+ 13992+ 13993+db_Matcher_u::~db_Matcher_u() 13994+{ 13995+ Clean(); 13996+} 13997+ 13998+void db_Matcher_u::Clean() 13999+{ 14000+ if(m_w) 14001+ { 14002+ /*Free buckets*/ 14003+ db_FreeBuckets_u(m_bp_l,m_nr_h,m_nr_v); 14004+ db_FreeBuckets_u(m_bp_r,m_nr_h,m_nr_v); 14005+ /*Free space for patch layouts*/ 14006+ delete [] m_patch_space; 14007+ } 14008+ m_w=0; m_h=0; 14009+} 14010+ 14011+ 14012+unsigned long db_Matcher_u::Init(int im_width,int im_height,double max_disparity,int target_nr_corners, 14013+ double max_disparity_v, bool use_smaller_matching_window, int use_21) 14014+{ 14015+ Clean(); 14016+ m_w=im_width; 14017+ m_h=im_height; 14018+ m_max_disparity=max_disparity; 14019+ m_max_disparity_v=max_disparity_v; 14020+ 14021+ if ( max_disparity_v != DB_DEFAULT_NO_DISPARITY ) 14022+ { 14023+ m_rect_window = 1; 14024+ 14025+ m_bw=db_maxi(1,(int)(max_disparity*((double)im_width))); 14026+ m_bh=db_maxi(1,(int)(max_disparity_v*((double)im_height))); 14027+ 14028+ m_bd=db_maxi(1,(int)(((double)target_nr_corners)*max_disparity*max_disparity_v)); 14029+ 14030+ m_kA=(int)(max_disparity*m_w); 14031+ m_kB=(int)(max_disparity_v*m_h); 14032+ 14033+ } else 14034+ { 14035+ m_bw=(int)db_maxi(1,(int)(max_disparity*((double)im_width))); 14036+ m_bh=(int)db_maxi(1,(int)(max_disparity*((double)im_height))); 14037+ 14038+ m_bd=db_maxi(1,(int)(((double)target_nr_corners)*max_disparity*max_disparity)); 14039+ 14040+ m_kA=(long)(256.0*((double)(m_w*m_w))/((double)(m_h*m_h))); 14041+ m_kB=(long)(256.0*max_disparity*max_disparity*((double)(m_w*m_w))); 14042+ } 14043+ 14044+ m_nr_h=1+(im_width-1)/m_bw; 14045+ m_nr_v=1+(im_height-1)/m_bh; 14046+ 14047+ m_target=target_nr_corners; 14048+ 14049+ /*Alloc bucket structure*/ 14050+ m_bp_l=db_AllocBuckets_u(m_nr_h,m_nr_v,m_bd); 14051+ m_bp_r=db_AllocBuckets_u(m_nr_h,m_nr_v,m_bd); 14052+ 14053+ m_use_smaller_matching_window = use_smaller_matching_window; 14054+ m_use_21 = use_21; 14055+ 14056+ if(m_use_21) 14057+ { 14058+ /*Alloc 64byte-aligned space for patch layouts*/ 14059+ m_patch_space=new short [2*(m_nr_h+2)*(m_nr_v+2)*m_bd*512+64]; 14060+ m_aligned_patch_space=db_AlignPointer_s(m_patch_space,64); 14061+ } 14062+ else 14063+ { 14064+ if(!m_use_smaller_matching_window) 14065+ { 14066+ /*Alloc 16byte-aligned space for patch layouts*/ 14067+ m_patch_space=new short [2*(m_nr_h+2)*(m_nr_v+2)*m_bd*128+16]; 14068+ m_aligned_patch_space=db_AlignPointer_s(m_patch_space,16); 14069+ } 14070+ else 14071+ { 14072+ /*Alloc 4byte-aligned space for patch layouts*/ 14073+ m_patch_space=new short [2*(m_nr_h+2)*(m_nr_v+2)*m_bd*32+4]; 14074+ m_aligned_patch_space=db_AlignPointer_s(m_patch_space,4); 14075+ } 14076+ } 14077+ 14078+ return(m_target); 14079+} 14080+ 14081+void db_Matcher_u::Match(const unsigned char * const *l_img,const unsigned char * const *r_img, 14082+ const double *x_l,const double *y_l,int nr_l,const double *x_r,const double *y_r,int nr_r, 14083+ int *id_l,int *id_r,int *nr_matches,const double H[9],int affine) 14084+{ 14085+ short *ps; 14086+ 14087+ /*Insert the corners into bucket structure*/ 14088+ ps=db_FillBuckets_u(m_aligned_patch_space,l_img,m_bp_l,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_l,y_l,nr_l,m_use_smaller_matching_window,m_use_21); 14089+ if(H==0) 14090+ db_FillBuckets_u(ps,r_img,m_bp_r,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_r,y_r,nr_r,m_use_smaller_matching_window,m_use_21); 14091+ else 14092+ { 14093+ if (affine) 14094+ { 14095+ double Hinv[9]; 14096+ db_InvertAffineTransform(Hinv,H); 14097+ float r_w, c_w; 14098+ float stretch_x[2]; 14099+ float stretch_y[2]; 14100+ AffineWarpPointOffset(r_w,c_w,Hinv, 5,5); 14101+ stretch_x[0]=db_absf(c_w);stretch_y[0]=db_absf(r_w); 14102+ AffineWarpPointOffset(r_w,c_w,Hinv, 5,-5); 14103+ stretch_x[1]=db_absf(c_w);stretch_y[1]=db_absf(r_w); 14104+ int max_stretxh_x=(int) (db_maxd(stretch_x[0],stretch_x[1])); 14105+ int max_stretxh_y=(int) (db_maxd(stretch_y[0],stretch_y[1])); 14106+ int warpbounds[4]={max_stretxh_x,m_w-1-max_stretxh_x,max_stretxh_y,m_h-1-max_stretxh_y}; 14107+ 14108+ for (int r=-5;r<=5;r++){ 14109+ for (int c=-5;c<=5;c++){ 14110+ AffineWarpPointOffset(r_w,c_w,Hinv,r,c); 14111+ AffineWarpPoint_BL_LUT_y[r+5][c+5]=r_w; 14112+ AffineWarpPoint_BL_LUT_x[r+5][c+5]=c_w; 14113+ 14114+ AffineWarpPoint_NN_LUT_y[r+5][c+5]=db_roundi(r_w); 14115+ AffineWarpPoint_NN_LUT_x[r+5][c+5]=db_roundi(c_w); 14116+ 14117+ } 14118+ } 14119+ 14120+ db_FillBucketsPrewarpedAffine_u(ps,r_img,m_bp_r,m_bw,m_bh,m_nr_h,m_nr_v,m_bd, 14121+ x_r,y_r,nr_r,H,Hinv,warpbounds,affine); 14122+ } 14123+ else 14124+ db_FillBucketsPrewarped_u(ps,r_img,m_bp_r,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_r,y_r,nr_r,H); 14125+ } 14126+ 14127+ 14128+ /*Compute all the necessary match scores*/ 14129+ db_MatchBuckets_u(m_bp_l,m_bp_r,m_nr_h,m_nr_v,m_kA,m_kB, m_rect_window,m_use_smaller_matching_window,m_use_21); 14130+ 14131+ /*Collect the correspondences*/ 14132+ db_CollectMatches_u(m_bp_l,m_nr_h,m_nr_v,m_target,id_l,id_r,nr_matches); 14133+} 14134+ 14135+int db_Matcher_u::IsAllocated() 14136+{ 14137+ return (int)(m_w != 0); 14138+} 14139diff --git a/benchmark/feature_stab/db_vlvm/db_feature_matching.h b/benchmark/feature_stab/db_vlvm/db_feature_matching.h 14140new file mode 100644 14141index 00000000..6c056b9a 14142--- /dev/null 14143+++ b/benchmark/feature_stab/db_vlvm/db_feature_matching.h 14144@@ -0,0 +1,260 @@ 14145+/* 14146+ * Copyright (C) 2011 The Android Open Source Project 14147+ * 14148+ * Licensed under the Apache License, Version 2.0 (the "License"); 14149+ * you may not use this file except in compliance with the License. 14150+ * You may obtain a copy of the License at 14151+ * 14152+ * http://www.apache.org/licenses/LICENSE-2.0 14153+ * 14154+ * Unless required by applicable law or agreed to in writing, software 14155+ * distributed under the License is distributed on an "AS IS" BASIS, 14156+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14157+ * See the License for the specific language governing permissions and 14158+ * limitations under the License. 14159+ */ 14160+ 14161+/*$Id: db_feature_matching.h,v 1.3 2011/06/17 14:03:30 mbansal Exp $*/ 14162+ 14163+#ifndef DB_FEATURE_MATCHING_H 14164+#define DB_FEATURE_MATCHING_H 14165+ 14166+/***************************************************************** 14167+* Lean and mean begins here * 14168+*****************************************************************/ 14169+/*! 14170+ * \defgroup FeatureMatching Feature Matching 14171+ */ 14172+#include "db_utilities.h" 14173+#include "db_utilities_constants.h" 14174+ 14175+DB_API void db_SignedSquareNormCorr21x21_PreAlign_u(short *patch,const unsigned char * const *f_img,int x_f,int y_f,float *sum,float *recip); 14176+DB_API void db_SignedSquareNormCorr11x11_PreAlign_u(short *patch,const unsigned char * const *f_img,int x_f,int y_f,float *sum,float *recip); 14177+float db_SignedSquareNormCorr21x21Aligned_Post_s(const short *f_patch,const short *g_patch,float fsum_gsum,float f_recip_g_recip); 14178+float db_SignedSquareNormCorr11x11Aligned_Post_s(const short *f_patch,const short *g_patch,float fsum_gsum,float f_recip_g_recip); 14179+ 14180+class db_PointInfo_f 14181+{ 14182+public: 14183+ /*Coordinates of point*/ 14184+ int x; 14185+ int y; 14186+ /*Id nr of point*/ 14187+ int id; 14188+ /*Best match score*/ 14189+ double s; 14190+ /*Best match candidate*/ 14191+ db_PointInfo_f *pir; 14192+ /*Precomputed coefficients 14193+ of image patch*/ 14194+ float sum; 14195+ float recip; 14196+ /*Pointer to patch layout*/ 14197+ const float *patch; 14198+}; 14199+ 14200+class db_Bucket_f 14201+{ 14202+public: 14203+ db_PointInfo_f *ptr; 14204+ int nr; 14205+}; 14206+ 14207+class db_PointInfo_u 14208+{ 14209+public: 14210+ /*Coordinates of point*/ 14211+ int x; 14212+ int y; 14213+ /*Id nr of point*/ 14214+ int id; 14215+ /*Best match score*/ 14216+ double s; 14217+ /*Best match candidate*/ 14218+ db_PointInfo_u *pir; 14219+ /*Precomputed coefficients 14220+ of image patch*/ 14221+ float sum; 14222+ float recip; 14223+ /*Pointer to patch layout*/ 14224+ const short *patch; 14225+}; 14226+ 14227+class db_Bucket_u 14228+{ 14229+public: 14230+ db_PointInfo_u *ptr; 14231+ int nr; 14232+}; 14233+/*! 14234+ * \class db_Matcher_f 14235+ * \ingroup FeatureMatching 14236+ * \brief Feature matcher for float images. 14237+ * 14238+ * Normalized correlation feature matcher for <b>float</b> images. 14239+ * Correlation window size is constant and set to 11x11. 14240+ * See \ref FeatureDetection to detect Harris corners. 14241+ * Images are managed with functions in \ref LMImageBasicUtilities. 14242+ */ 14243+class DB_API db_Matcher_f 14244+{ 14245+public: 14246+ db_Matcher_f(); 14247+ ~db_Matcher_f(); 14248+ 14249+ /*! 14250+ * Set parameters and pre-allocate memory. Return an upper bound 14251+ * on the number of matches. 14252+ * \param im_width width 14253+ * \param im_height height 14254+ * \param max_disparity maximum distance (as fraction of image size) between matches 14255+ * \param target_nr_corners maximum number of matches 14256+ * \return maximum number of matches 14257+ */ 14258+ unsigned long Init(int im_width,int im_height, 14259+ double max_disparity=DB_DEFAULT_MAX_DISPARITY, 14260+ int target_nr_corners=DB_DEFAULT_TARGET_NR_CORNERS); 14261+ 14262+ /*! 14263+ * Match two sets of features. 14264+ * If the prewarp H is not NULL it will be applied to the features 14265+ * in the right image before matching. 14266+ * Parameters id_l and id_r must point to arrays of size target_nr_corners 14267+ * (returned by Init()). 14268+ * The results of matching are in id_l and id_r. 14269+ * Interpretaqtion of results: if id_l[i] = m and id_r[i] = n, 14270+ * feature at (x_l[m],y_l[m]) matched to (x_r[n],y_r[n]). 14271+ * \param l_img left image 14272+ * \param r_img right image 14273+ * \param x_l left x coordinates of features 14274+ * \param y_l left y coordinates of features 14275+ * \param nr_l number of features in left image 14276+ * \param x_r right x coordinates of features 14277+ * \param y_r right y coordinates of features 14278+ * \param nr_r number of features in right image 14279+ * \param id_l indices of left features that matched 14280+ * \param id_r indices of right features that matched 14281+ * \param nr_matches number of features actually matched 14282+ * \param H image homography (prewarp) to be applied to right image features 14283+ */ 14284+ void Match(const float * const *l_img,const float * const *r_img, 14285+ const double *x_l,const double *y_l,int nr_l,const double *x_r,const double *y_r,int nr_r, 14286+ int *id_l,int *id_r,int *nr_matches,const double H[9]=0); 14287+ 14288+protected: 14289+ void Clean(); 14290+ 14291+ int m_w,m_h,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,m_target; 14292+ unsigned long m_kA,m_kB; 14293+ db_Bucket_f **m_bp_l; 14294+ db_Bucket_f **m_bp_r; 14295+ float *m_patch_space,*m_aligned_patch_space; 14296+}; 14297+/*! 14298+ * \class db_Matcher_u 14299+ * \ingroup FeatureMatching 14300+ * \brief Feature matcher for byte images. 14301+ * 14302+ * Normalized correlation feature matcher for <b>byte</b> images. 14303+ * Correlation window size is constant and set to 11x11. 14304+ * See \ref FeatureDetection to detect Harris corners. 14305+ * Images are managed with functions in \ref LMImageBasicUtilities. 14306+ * 14307+ * If the prewarp matrix H is supplied, the feature coordinates are warped by H before being placed in 14308+ * appropriate buckets. If H is an affine transform and the "affine" parameter is set to 1 or 2, 14309+ * then the correlation patches themselves are warped before being placed in the patch space. 14310+ */ 14311+class DB_API db_Matcher_u 14312+{ 14313+public: 14314+ db_Matcher_u(); 14315+ 14316+ int GetPatchSize(){return 11;}; 14317+ 14318+ virtual ~db_Matcher_u(); 14319+ 14320+ /*! 14321+ Copy ctor duplicates settings. 14322+ Memory not copied. 14323+ */ 14324+ db_Matcher_u(const db_Matcher_u& cm); 14325+ 14326+ /*! 14327+ Assignment optor duplicates settings 14328+ Memory not copied. 14329+ */ 14330+ db_Matcher_u& operator= (const db_Matcher_u& cm); 14331+ 14332+ /*! 14333+ * Set parameters and pre-allocate memory. Return an upper bound 14334+ * on the number of matches. 14335+ * If max_disparity_v is DB_DEFAULT_NO_DISPARITY, look for matches 14336+ * in a ellipse around a feature of radius max_disparity*im_width by max_disparity*im_height. 14337+ * If max_disparity_v is specified, use a rectangle max_disparity*im_width by max_disparity_v*im_height. 14338+ * \param im_width width 14339+ * \param im_height height 14340+ * \param max_disparity maximum distance (as fraction of image size) between matches 14341+ * \param target_nr_corners maximum number of matches 14342+ * \param max_disparity_v maximum vertical disparity (distance between matches) 14343+ * \param use_smaller_matching_window if set to true, uses a correlation window of 5x5 instead of the default 11x11 14344+ * \return maximum number of matches 14345+ */ 14346+ virtual unsigned long Init(int im_width,int im_height, 14347+ double max_disparity=DB_DEFAULT_MAX_DISPARITY, 14348+ int target_nr_corners=DB_DEFAULT_TARGET_NR_CORNERS, 14349+ double max_disparity_v=DB_DEFAULT_NO_DISPARITY, 14350+ bool use_smaller_matching_window=false, int use_21=0); 14351+ 14352+ /*! 14353+ * Match two sets of features. 14354+ * If the prewarp H is not NULL it will be applied to the features 14355+ * in the right image before matching. 14356+ * Parameters id_l and id_r must point to arrays of size target_nr_corners 14357+ * (returned by Init()). 14358+ * The results of matching are in id_l and id_r. 14359+ * Interpretaqtion of results: if id_l[i] = m and id_r[i] = n, 14360+ * feature at (x_l[m],y_l[m]) matched to (x_r[n],y_r[n]). 14361+ * \param l_img left image 14362+ * \param r_img right image 14363+ * \param x_l left x coordinates of features 14364+ * \param y_l left y coordinates of features 14365+ * \param nr_l number of features in left image 14366+ * \param x_r right x coordinates of features 14367+ * \param y_r right y coordinates of features 14368+ * \param nr_r number of features in right image 14369+ * \param id_l indices of left features that matched 14370+ * \param id_r indices of right features that matched 14371+ * \param nr_matches number of features actually matched 14372+ * \param H image homography (prewarp) to be applied to right image features 14373+ * \param affine prewarp the 11x11 patches by given affine transform. 0 means no warping, 14374+ 1 means nearest neighbor, 2 means bilinear warping. 14375+ */ 14376+ virtual void Match(const unsigned char * const *l_img,const unsigned char * const *r_img, 14377+ const double *x_l,const double *y_l,int nr_l,const double *x_r,const double *y_r,int nr_r, 14378+ int *id_l,int *id_r,int *nr_matches,const double H[9]=0,int affine=0); 14379+ 14380+ /*! 14381+ * Checks if Init() was called. 14382+ * \return 1 if Init() was called, 0 otherwise. 14383+ */ 14384+ int IsAllocated(); 14385+ 14386+protected: 14387+ virtual void Clean(); 14388+ 14389+ 14390+ int m_w,m_h,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,m_target; 14391+ unsigned long m_kA,m_kB; 14392+ db_Bucket_u **m_bp_l; 14393+ db_Bucket_u **m_bp_r; 14394+ short *m_patch_space,*m_aligned_patch_space; 14395+ 14396+ double m_max_disparity, m_max_disparity_v; 14397+ int m_rect_window; 14398+ bool m_use_smaller_matching_window; 14399+ int m_use_21; 14400+}; 14401+ 14402+ 14403+ 14404+#endif /*DB_FEATURE_MATCHING_H*/ 14405diff --git a/benchmark/feature_stab/db_vlvm/db_framestitching.cpp b/benchmark/feature_stab/db_vlvm/db_framestitching.cpp 14406new file mode 100644 14407index 00000000..b574f7a0 14408--- /dev/null 14409+++ b/benchmark/feature_stab/db_vlvm/db_framestitching.cpp 14410@@ -0,0 +1,169 @@ 14411+/* 14412+ * Copyright (C) 2011 The Android Open Source Project 14413+ * 14414+ * Licensed under the Apache License, Version 2.0 (the "License"); 14415+ * you may not use this file except in compliance with the License. 14416+ * You may obtain a copy of the License at 14417+ * 14418+ * http://www.apache.org/licenses/LICENSE-2.0 14419+ * 14420+ * Unless required by applicable law or agreed to in writing, software 14421+ * distributed under the License is distributed on an "AS IS" BASIS, 14422+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14423+ * See the License for the specific language governing permissions and 14424+ * limitations under the License. 14425+ */ 14426+ 14427+/* $Id: db_framestitching.cpp,v 1.2 2011/06/17 14:03:30 mbansal Exp $ */ 14428+ 14429+#include "db_utilities.h" 14430+#include "db_framestitching.h" 14431+ 14432+ 14433+ 14434+/***************************************************************** 14435+* Lean and mean begins here * 14436+*****************************************************************/ 14437+ 14438+inline void db_RotationFromMOuterProductSum(double R[9],double *score,double M[9]) 14439+{ 14440+ double N[16],q[4],lambda[4],lambda_max; 14441+ double y[4]; 14442+ int nr_roots; 14443+ 14444+ N[0]= M[0]+M[4]+M[8]; 14445+ N[5]= M[0]-M[4]-M[8]; 14446+ N[10]= -M[0]+M[4]-M[8]; 14447+ N[15]= -M[0]-M[4]+M[8]; 14448+ N[1] =N[4] =M[5]-M[7]; 14449+ N[2] =N[8] =M[6]-M[2]; 14450+ N[3] =N[12]=M[1]-M[3]; 14451+ N[6] =N[9] =M[1]+M[3]; 14452+ N[7] =N[13]=M[6]+M[2]; 14453+ N[11]=N[14]=M[5]+M[7]; 14454+ 14455+ /*get the quaternion representing the rotation 14456+ by finding the eigenvector corresponding to the most 14457+ positive eigenvalue. Force eigenvalue solutions, since the matrix 14458+ is symmetric and solutions might otherwise be lost 14459+ when the data is planar*/ 14460+ db_RealEigenvalues4x4(lambda,&nr_roots,N,1); 14461+ if(nr_roots) 14462+ { 14463+ lambda_max=lambda[0]; 14464+ if(nr_roots>=2) 14465+ { 14466+ if(lambda[1]>lambda_max) lambda_max=lambda[1]; 14467+ if(nr_roots>=3) 14468+ { 14469+ if(lambda[2]>lambda_max) lambda_max=lambda[2]; 14470+ { 14471+ if(nr_roots>=4) if(lambda[3]>lambda_max) lambda_max=lambda[3]; 14472+ } 14473+ } 14474+ } 14475+ } 14476+ else lambda_max=1.0; 14477+ db_EigenVector4x4(q,lambda_max,N); 14478+ 14479+ /*Compute the rotation matrix*/ 14480+ db_QuaternionToRotation(R,q); 14481+ 14482+ if(score) 14483+ { 14484+ /*Compute score=transpose(q)*N*q */ 14485+ db_Multiply4x4_4x1(y,N,q); 14486+ *score=db_ScalarProduct4(q,y); 14487+ } 14488+} 14489+ 14490+void db_StitchSimilarity3DRaw(double *scale,double R[9],double t[3], 14491+ double **Xp,double **X,int nr_points,int orientation_preserving, 14492+ int allow_scaling,int allow_rotation,int allow_translation) 14493+{ 14494+ int i; 14495+ double c[3],cp[3],r[3],rp[3],M[9],s,sp,sc; 14496+ double Rr[9],score_p,score_r; 14497+ double *temp,*temp_p; 14498+ 14499+ if(allow_translation) 14500+ { 14501+ db_PointCentroid3D(c,X,nr_points); 14502+ db_PointCentroid3D(cp,Xp,nr_points); 14503+ } 14504+ else 14505+ { 14506+ db_Zero3(c); 14507+ db_Zero3(cp); 14508+ } 14509+ 14510+ db_Zero9(M); 14511+ s=sp=0; 14512+ for(i=0;i<nr_points;i++) 14513+ { 14514+ temp= *X++; 14515+ temp_p= *Xp++; 14516+ r[0]=(*temp++)-c[0]; 14517+ r[1]=(*temp++)-c[1]; 14518+ r[2]=(*temp++)-c[2]; 14519+ rp[0]=(*temp_p++)-cp[0]; 14520+ rp[1]=(*temp_p++)-cp[1]; 14521+ rp[2]=(*temp_p++)-cp[2]; 14522+ 14523+ M[0]+=r[0]*rp[0]; 14524+ M[1]+=r[0]*rp[1]; 14525+ M[2]+=r[0]*rp[2]; 14526+ M[3]+=r[1]*rp[0]; 14527+ M[4]+=r[1]*rp[1]; 14528+ M[5]+=r[1]*rp[2]; 14529+ M[6]+=r[2]*rp[0]; 14530+ M[7]+=r[2]*rp[1]; 14531+ M[8]+=r[2]*rp[2]; 14532+ 14533+ s+=db_sqr(r[0])+db_sqr(r[1])+db_sqr(r[2]); 14534+ sp+=db_sqr(rp[0])+db_sqr(rp[1])+db_sqr(rp[2]); 14535+ } 14536+ 14537+ /*Compute scale*/ 14538+ if(allow_scaling) sc=sqrt(db_SafeDivision(sp,s)); 14539+ else sc=1.0; 14540+ *scale=sc; 14541+ 14542+ /*Compute rotation*/ 14543+ if(allow_rotation) 14544+ { 14545+ if(orientation_preserving) 14546+ { 14547+ db_RotationFromMOuterProductSum(R,0,M); 14548+ } 14549+ else 14550+ { 14551+ /*Try preserving*/ 14552+ db_RotationFromMOuterProductSum(R,&score_p,M); 14553+ /*Try reversing*/ 14554+ M[6]= -M[6]; 14555+ M[7]= -M[7]; 14556+ M[8]= -M[8]; 14557+ db_RotationFromMOuterProductSum(Rr,&score_r,M); 14558+ if(score_r>score_p) 14559+ { 14560+ /*Reverse is better*/ 14561+ R[0]=Rr[0]; R[1]=Rr[1]; R[2]= -Rr[2]; 14562+ R[3]=Rr[3]; R[4]=Rr[4]; R[5]= -Rr[5]; 14563+ R[6]=Rr[6]; R[7]=Rr[7]; R[8]= -Rr[8]; 14564+ } 14565+ } 14566+ } 14567+ else db_Identity3x3(R); 14568+ 14569+ /*Compute translation*/ 14570+ if(allow_translation) 14571+ { 14572+ t[0]=cp[0]-sc*(R[0]*c[0]+R[1]*c[1]+R[2]*c[2]); 14573+ t[1]=cp[1]-sc*(R[3]*c[0]+R[4]*c[1]+R[5]*c[2]); 14574+ t[2]=cp[2]-sc*(R[6]*c[0]+R[7]*c[1]+R[8]*c[2]); 14575+ } 14576+ else db_Zero3(t); 14577+} 14578+ 14579+ 14580diff --git a/benchmark/feature_stab/db_vlvm/db_framestitching.h b/benchmark/feature_stab/db_vlvm/db_framestitching.h 14581new file mode 100644 14582index 00000000..5fef5f37 14583--- /dev/null 14584+++ b/benchmark/feature_stab/db_vlvm/db_framestitching.h 14585@@ -0,0 +1,94 @@ 14586+/* 14587+ * Copyright (C) 2011 The Android Open Source Project 14588+ * 14589+ * Licensed under the Apache License, Version 2.0 (the "License"); 14590+ * you may not use this file except in compliance with the License. 14591+ * You may obtain a copy of the License at 14592+ * 14593+ * http://www.apache.org/licenses/LICENSE-2.0 14594+ * 14595+ * Unless required by applicable law or agreed to in writing, software 14596+ * distributed under the License is distributed on an "AS IS" BASIS, 14597+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14598+ * See the License for the specific language governing permissions and 14599+ * limitations under the License. 14600+ */ 14601+ 14602+/* $Id: db_framestitching.h,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */ 14603+ 14604+#ifndef DB_FRAMESTITCHING_H 14605+#define DB_FRAMESTITCHING_H 14606+/*! 14607+ * \defgroup FrameStitching Frame Stitching (2D and 3D homography estimation) 14608+ */ 14609+/*\{*/ 14610+ 14611+ 14612+/***************************************************************** 14613+* Lean and mean begins here * 14614+*****************************************************************/ 14615+/*! 14616+ * \defgroup LMFrameStitching (LM) Frame Stitching (2D and 3D homography estimation) 14617+ */ 14618+/*\{*/ 14619+ 14620+/*! 14621+Find scale, rotation and translation of the similarity that 14622+takes the nr_points inhomogenous 3D points X to Xp 14623+(left to right according to Horn), i.e. for the homogenous equivalents 14624+Xp and X we would have 14625+\code 14626+ Xp~ 14627+ [sR t]*X 14628+ [0 1] 14629+\endcode 14630+If orientation_preserving is true, R is restricted such that det(R)>0. 14631+allow_scaling, allow_rotation and allow_translation allow s,R and t 14632+to differ from 1,Identity and 0 14633+ 14634+Full similarity takes the following on 550MHz: 14635+\code 14636+4.5 microseconds with 3 points 14637+4.7 microseconds with 4 points 14638+5.0 microseconds with 5 points 14639+5.2 microseconds with 6 points 14640+5.8 microseconds with 10 points 14641+20 microseconds with 100 points 14642+205 microseconds with 1000 points 14643+2.9 milliseconds with 10000 points 14644+50 milliseconds with 100000 points 14645+0.5 seconds with 1000000 points 14646+\endcode 14647+Without orientation_preserving: 14648+\code 14649+4 points is minimal for (s,R,t) (R,t) 14650+3 points is minimal for (s,R) (R) 14651+2 points is minimal for (s,t) 14652+1 point is minimal for (s) (t) 14653+\endcode 14654+With orientation_preserving: 14655+\code 14656+3 points is minimal for (s,R,t) (R,t) 14657+2 points is minimal for (s,R) (s,t) (R) 14658+1 point is minimal for (s) (t) 14659+\endcode 14660+ 14661+\param scale scale 14662+\param R rotation 14663+\param t translation 14664+\param Xp inhomogenouse 3D points in first coordinate system 14665+\param X inhomogenouse 3D points in second coordinate system 14666+\param nr_points number of points 14667+\param orientation_preserving if true, R is restricted such that det(R)>0. 14668+\param allow_scaling estimate scale 14669+\param allow_rotation estimate rotation 14670+\param allow_translation estimate translation 14671+*/ 14672+DB_API void db_StitchSimilarity3DRaw(double *scale,double R[9],double t[3], 14673+ double **Xp,double **X,int nr_points,int orientation_preserving=1, 14674+ int allow_scaling=1,int allow_rotation=1,int allow_translation=1); 14675+ 14676+ 14677+/*\}*/ 14678+ 14679+#endif /* DB_FRAMESTITCHING_H */ 14680diff --git a/benchmark/feature_stab/db_vlvm/db_image_homography.cpp b/benchmark/feature_stab/db_vlvm/db_image_homography.cpp 14681new file mode 100644 14682index 00000000..aaad7f85 14683--- /dev/null 14684+++ b/benchmark/feature_stab/db_vlvm/db_image_homography.cpp 14685@@ -0,0 +1,332 @@ 14686+/* 14687+ * Copyright (C) 2011 The Android Open Source Project 14688+ * 14689+ * Licensed under the Apache License, Version 2.0 (the "License"); 14690+ * you may not use this file except in compliance with the License. 14691+ * You may obtain a copy of the License at 14692+ * 14693+ * http://www.apache.org/licenses/LICENSE-2.0 14694+ * 14695+ * Unless required by applicable law or agreed to in writing, software 14696+ * distributed under the License is distributed on an "AS IS" BASIS, 14697+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14698+ * See the License for the specific language governing permissions and 14699+ * limitations under the License. 14700+ */ 14701+ 14702+/* $Id: db_image_homography.cpp,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */ 14703+ 14704+#include "db_utilities.h" 14705+#include "db_image_homography.h" 14706+#include "db_framestitching.h" 14707+#include "db_metrics.h" 14708+ 14709+ 14710+ 14711+/***************************************************************** 14712+* Lean and mean begins here * 14713+*****************************************************************/ 14714+ 14715+/*Compute the linear constraint on H obtained by requiring that the 14716+ratio between coordinate i_num and i_den of xp is equal to the ratio 14717+between coordinate i_num and i_den of Hx. i_zero should be set to 14718+the coordinate not equal to i_num or i_den. No normalization is used*/ 14719+inline void db_SProjImagePointPointConstraint(double c[9],int i_num,int i_den,int i_zero, 14720+ double xp[3],double x[3]) 14721+{ 14722+ db_MultiplyScalarCopy3(c+3*i_den,x, xp[i_num]); 14723+ db_MultiplyScalarCopy3(c+3*i_num,x, -xp[i_den]); 14724+ db_Zero3(c+3*i_zero); 14725+} 14726+ 14727+/*Compute two constraints on H generated by the correspondence (Xp,X), 14728+assuming that Xp ~= H*X. No normalization is used*/ 14729+inline void db_SProjImagePointPointConstraints(double c1[9],double c2[9],double xp[3],double x[3]) 14730+{ 14731+ int ma_ind; 14732+ 14733+ /*Find index of coordinate of Xp with largest absolute value*/ 14734+ ma_ind=db_MaxAbsIndex3(xp); 14735+ 14736+ /*Generate 2 constraints, 14737+ each constraint is generated by considering the ratio between a 14738+ coordinate and the largest absolute value coordinate*/ 14739+ switch(ma_ind) 14740+ { 14741+ case 0: 14742+ db_SProjImagePointPointConstraint(c1,1,0,2,xp,x); 14743+ db_SProjImagePointPointConstraint(c2,2,0,1,xp,x); 14744+ break; 14745+ case 1: 14746+ db_SProjImagePointPointConstraint(c1,0,1,2,xp,x); 14747+ db_SProjImagePointPointConstraint(c2,2,1,0,xp,x); 14748+ break; 14749+ default: 14750+ db_SProjImagePointPointConstraint(c1,0,2,1,xp,x); 14751+ db_SProjImagePointPointConstraint(c2,1,2,0,xp,x); 14752+ } 14753+} 14754+ 14755+inline void db_SAffineImagePointPointConstraints(double c1[7],double c2[7],double xp[3],double x[3]) 14756+{ 14757+ double ct1[9],ct2[9]; 14758+ 14759+ db_SProjImagePointPointConstraints(ct1,ct2,xp,x); 14760+ db_Copy6(c1,ct1); c1[6]=ct1[8]; 14761+ db_Copy6(c2,ct2); c2[6]=ct2[8]; 14762+} 14763+ 14764+void db_StitchProjective2D_4Points(double H[9], 14765+ double x1[3],double x2[3],double x3[3],double x4[3], 14766+ double xp1[3],double xp2[3],double xp3[3],double xp4[3]) 14767+{ 14768+ double c[72]; 14769+ 14770+ /*Collect the constraints*/ 14771+ db_SProjImagePointPointConstraints(c ,c+9 ,xp1,x1); 14772+ db_SProjImagePointPointConstraints(c+18,c+27,xp2,x2); 14773+ db_SProjImagePointPointConstraints(c+36,c+45,xp3,x3); 14774+ db_SProjImagePointPointConstraints(c+54,c+63,xp4,x4); 14775+ /*Solve for the nullvector*/ 14776+ db_NullVector8x9Destructive(H,c); 14777+} 14778+ 14779+void db_StitchAffine2D_3Points(double H[9], 14780+ double x1[3],double x2[3],double x3[3], 14781+ double xp1[3],double xp2[3],double xp3[3]) 14782+{ 14783+ double c[42]; 14784+ 14785+ /*Collect the constraints*/ 14786+ db_SAffineImagePointPointConstraints(c ,c+7 ,xp1,x1); 14787+ db_SAffineImagePointPointConstraints(c+14,c+21,xp2,x2); 14788+ db_SAffineImagePointPointConstraints(c+28,c+35,xp3,x3); 14789+ /*Solve for the nullvector*/ 14790+ db_NullVector6x7Destructive(H,c); 14791+ db_MultiplyScalar6(H,db_SafeReciprocal(H[6])); 14792+ H[6]=H[7]=0; H[8]=1.0; 14793+} 14794+ 14795+/*Compute up to three solutions for the focal length given two point correspondences 14796+generated by a rotation with a common unknown focal length. No specific normalization 14797+of the input points is required. If signed_disambiguation is true, the points are 14798+required to be in front of the camera*/ 14799+inline void db_CommonFocalLengthFromRotation_2Point(double fsol[3],int *nr_sols,double x1[3],double x2[3],double xp1[3],double xp2[3],int signed_disambiguation=1) 14800+{ 14801+ double m,ax,ay,apx,apy,bx,by,bpx,bpy; 14802+ double p1[2],p2[2],p3[2],p4[2],p5[2],p6[2]; 14803+ double p7[3],p8[4],p9[5],p10[3],p11[4]; 14804+ double roots[3]; 14805+ int nr_roots,i,j; 14806+ 14807+ /*Solve for focal length using the equation 14808+ <a,b>^2*<ap,ap><bp,bp>=<ap,bp>^2*<a,a><b,b> 14809+ where a and ap are the homogenous vectors in the first image 14810+ after focal length scaling and b,bp are the vectors in the 14811+ second image*/ 14812+ 14813+ /*Normalize homogenous coordinates so that last coordinate is one*/ 14814+ m=db_SafeReciprocal(x1[2]); 14815+ ax=x1[0]*m; 14816+ ay=x1[1]*m; 14817+ m=db_SafeReciprocal(xp1[2]); 14818+ apx=xp1[0]*m; 14819+ apy=xp1[1]*m; 14820+ m=db_SafeReciprocal(x2[2]); 14821+ bx=x2[0]*m; 14822+ by=x2[1]*m; 14823+ m=db_SafeReciprocal(xp2[2]); 14824+ bpx=xp2[0]*m; 14825+ bpy=xp2[1]*m; 14826+ 14827+ /*Compute cubic in l=1/(f^2) 14828+ by dividing out the root l=0 from the equation 14829+ (l(ax*bx+ay*by)+1)^2*(l(apx^2+apy^2)+1)*(l(bpx^2+bpy^2)+1)= 14830+ (l(apx*bpx+apy*bpy)+1)^2*(l(ax^2+ay^2)+1)*(l(bx^2+by^2)+1)*/ 14831+ p1[1]=ax*bx+ay*by; 14832+ p2[1]=db_sqr(apx)+db_sqr(apy); 14833+ p3[1]=db_sqr(bpx)+db_sqr(bpy); 14834+ p4[1]=apx*bpx+apy*bpy; 14835+ p5[1]=db_sqr(ax)+db_sqr(ay); 14836+ p6[1]=db_sqr(bx)+db_sqr(by); 14837+ p1[0]=p2[0]=p3[0]=p4[0]=p5[0]=p6[0]=1; 14838+ 14839+ db_MultiplyPoly1_1(p7,p1,p1); 14840+ db_MultiplyPoly1_2(p8,p2,p7); 14841+ db_MultiplyPoly1_3(p9,p3,p8); 14842+ 14843+ db_MultiplyPoly1_1(p10,p4,p4); 14844+ db_MultiplyPoly1_2(p11,p5,p10); 14845+ db_SubtractPolyProduct1_3(p9,p6,p11); 14846+ /*Cubic starts at p9[1]*/ 14847+ db_SolveCubic(roots,&nr_roots,p9[4],p9[3],p9[2],p9[1]); 14848+ 14849+ for(j=0,i=0;i<nr_roots;i++) 14850+ { 14851+ if(roots[i]>0) 14852+ { 14853+ if((!signed_disambiguation) || (db_PolyEval1(p1,roots[i])*db_PolyEval1(p4,roots[i])>0)) 14854+ { 14855+ fsol[j++]=db_SafeSqrtReciprocal(roots[i]); 14856+ } 14857+ } 14858+ } 14859+ *nr_sols=j; 14860+} 14861+ 14862+int db_StitchRotationCommonFocalLength_3Points(double H[9],double x1[3],double x2[3],double x3[3],double xp1[3],double xp2[3],double xp3[3],double *f,int signed_disambiguation) 14863+{ 14864+ double fsol[3]; 14865+ int nr_sols,i,best_sol,done; 14866+ double cost,best_cost; 14867+ double m,hyp[27],x1_temp[3],x2_temp[3],xp1_temp[3],xp2_temp[3]; 14868+ double *hyp_point,ft; 14869+ double y[2]; 14870+ 14871+ db_CommonFocalLengthFromRotation_2Point(fsol,&nr_sols,x1,x2,xp1,xp2,signed_disambiguation); 14872+ if(nr_sols) 14873+ { 14874+ db_DeHomogenizeImagePoint(y,xp3); 14875+ done=0; 14876+ for(i=0;i<nr_sols;i++) 14877+ { 14878+ ft=fsol[i]; 14879+ m=db_SafeReciprocal(ft); 14880+ x1_temp[0]=x1[0]*m; 14881+ x1_temp[1]=x1[1]*m; 14882+ x1_temp[2]=x1[2]; 14883+ x2_temp[0]=x2[0]*m; 14884+ x2_temp[1]=x2[1]*m; 14885+ x2_temp[2]=x2[2]; 14886+ xp1_temp[0]=xp1[0]*m; 14887+ xp1_temp[1]=xp1[1]*m; 14888+ xp1_temp[2]=xp1[2]; 14889+ xp2_temp[0]=xp2[0]*m; 14890+ xp2_temp[1]=xp2[1]*m; 14891+ xp2_temp[2]=xp2[2]; 14892+ 14893+ hyp_point=hyp+9*i; 14894+ db_StitchCameraRotation_2Points(hyp_point,x1_temp,x2_temp,xp1_temp,xp2_temp); 14895+ hyp_point[2]*=ft; 14896+ hyp_point[5]*=ft; 14897+ hyp_point[6]*=m; 14898+ hyp_point[7]*=m; 14899+ cost=db_SquaredReprojectionErrorHomography(y,hyp_point,x3); 14900+ 14901+ if(!done || cost<best_cost) 14902+ { 14903+ done=1; 14904+ best_cost=cost; 14905+ best_sol=i; 14906+ } 14907+ } 14908+ 14909+ if(f) *f=fsol[best_sol]; 14910+ db_Copy9(H,hyp+9*best_sol); 14911+ return(1); 14912+ } 14913+ else 14914+ { 14915+ db_Identity3x3(H); 14916+ if(f) *f=1.0; 14917+ return(0); 14918+ } 14919+} 14920+ 14921+void db_StitchSimilarity2DRaw(double *scale,double R[4],double t[2], 14922+ double **Xp,double **X,int nr_points,int orientation_preserving, 14923+ int allow_scaling,int allow_rotation,int allow_translation) 14924+{ 14925+ int i; 14926+ double c[2],cp[2],r[2],rp[2],M[4],s,sp,sc; 14927+ double *temp,*temp_p; 14928+ double Aacc,Bacc,Aacc2,Bacc2,divisor,divisor2,m,Am,Bm; 14929+ 14930+ if(allow_translation) 14931+ { 14932+ db_PointCentroid2D(c,X,nr_points); 14933+ db_PointCentroid2D(cp,Xp,nr_points); 14934+ } 14935+ else 14936+ { 14937+ db_Zero2(c); 14938+ db_Zero2(cp); 14939+ } 14940+ 14941+ db_Zero4(M); 14942+ s=sp=0; 14943+ for(i=0;i<nr_points;i++) 14944+ { 14945+ temp= *X++; 14946+ temp_p= *Xp++; 14947+ r[0]=(*temp++)-c[0]; 14948+ r[1]=(*temp++)-c[1]; 14949+ rp[0]=(*temp_p++)-cp[0]; 14950+ rp[1]=(*temp_p++)-cp[1]; 14951+ 14952+ M[0]+=r[0]*rp[0]; 14953+ M[1]+=r[0]*rp[1]; 14954+ M[2]+=r[1]*rp[0]; 14955+ M[3]+=r[1]*rp[1]; 14956+ 14957+ s+=db_sqr(r[0])+db_sqr(r[1]); 14958+ sp+=db_sqr(rp[0])+db_sqr(rp[1]); 14959+ } 14960+ 14961+ /*Compute scale*/ 14962+ if(allow_scaling) sc=sqrt(db_SafeDivision(sp,s)); 14963+ else sc=1.0; 14964+ *scale=sc; 14965+ 14966+ /*Compute rotation*/ 14967+ if(allow_rotation) 14968+ { 14969+ /*orientation preserving*/ 14970+ Aacc=M[0]+M[3]; 14971+ Bacc=M[2]-M[1]; 14972+ /*orientation reversing*/ 14973+ Aacc2=M[0]-M[3]; 14974+ Bacc2=M[2]+M[1]; 14975+ if(Aacc!=0.0 || Bacc!=0.0) 14976+ { 14977+ divisor=sqrt(Aacc*Aacc+Bacc*Bacc); 14978+ m=db_SafeReciprocal(divisor); 14979+ Am=Aacc*m; 14980+ Bm=Bacc*m; 14981+ R[0]= Am; 14982+ R[1]= Bm; 14983+ R[2]= -Bm; 14984+ R[3]= Am; 14985+ } 14986+ else 14987+ { 14988+ db_Identity2x2(R); 14989+ divisor=0.0; 14990+ } 14991+ if(!orientation_preserving && (Aacc2!=0.0 || Bacc2!=0.0)) 14992+ { 14993+ divisor2=sqrt(Aacc2*Aacc2+Bacc2*Bacc2); 14994+ if(divisor2>divisor) 14995+ { 14996+ m=db_SafeReciprocal(divisor2); 14997+ Am=Aacc2*m; 14998+ Bm=Bacc2*m; 14999+ R[0]= Am; 15000+ R[1]= Bm; 15001+ R[2]= Bm; 15002+ R[3]= -Am; 15003+ } 15004+ } 15005+ } 15006+ else db_Identity2x2(R); 15007+ 15008+ /*Compute translation*/ 15009+ if(allow_translation) 15010+ { 15011+ t[0]=cp[0]-sc*(R[0]*c[0]+R[1]*c[1]); 15012+ t[1]=cp[1]-sc*(R[2]*c[0]+R[3]*c[1]); 15013+ } 15014+ else db_Zero2(t); 15015+} 15016+ 15017+ 15018diff --git a/benchmark/feature_stab/db_vlvm/db_image_homography.h b/benchmark/feature_stab/db_vlvm/db_image_homography.h 15019new file mode 100644 15020index 00000000..165447dd 15021--- /dev/null 15022+++ b/benchmark/feature_stab/db_vlvm/db_image_homography.h 15023@@ -0,0 +1,183 @@ 15024+/* 15025+ * Copyright (C) 2011 The Android Open Source Project 15026+ * 15027+ * Licensed under the Apache License, Version 2.0 (the "License"); 15028+ * you may not use this file except in compliance with the License. 15029+ * You may obtain a copy of the License at 15030+ * 15031+ * http://www.apache.org/licenses/LICENSE-2.0 15032+ * 15033+ * Unless required by applicable law or agreed to in writing, software 15034+ * distributed under the License is distributed on an "AS IS" BASIS, 15035+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15036+ * See the License for the specific language governing permissions and 15037+ * limitations under the License. 15038+ */ 15039+ 15040+/* $Id: db_image_homography.h,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */ 15041+ 15042+#ifndef DB_IMAGE_HOMOGRAPHY 15043+#define DB_IMAGE_HOMOGRAPHY 15044+ 15045+ 15046+ 15047+/***************************************************************** 15048+* Lean and mean begins here * 15049+*****************************************************************/ 15050+ 15051+#include "db_framestitching.h" 15052+/*! 15053+ * \defgroup LMImageHomography (LM) Image Homography Estimation (feature based) 15054+ */ 15055+/*\{*/ 15056+/*! 15057+Solve for projective H such that xp~Hx. Prior normalization is not necessary, 15058+although desirable for numerical conditioning 15059+\param H image projective (out) 15060+\param x1 image 1 point 1 15061+\param x2 image 1 point 2 15062+\param x3 image 1 point 3 15063+\param x4 image 1 point 4 15064+\param xp1 image 2 point 1 15065+\param xp2 image 2 point 2 15066+\param xp3 image 2 point 3 15067+\param xp4 image 2 point 4 15068+*/ 15069+DB_API void db_StitchProjective2D_4Points(double H[9], 15070+ double x1[3],double x2[3],double x3[3],double x4[3], 15071+ double xp1[3],double xp2[3],double xp3[3],double xp4[3]); 15072+ 15073+/*! 15074+Solve for affine H such that xp~Hx. Prior normalization is not necessary, 15075+although desirable for numerical conditioning 15076+\param H image projective (out) 15077+\param x1 image 1 point 1 15078+\param x2 image 1 point 2 15079+\param x3 image 1 point 3 15080+\param xp1 image 2 point 1 15081+\param xp2 image 2 point 2 15082+\param xp3 image 2 point 3 15083+*/ 15084+DB_API void db_StitchAffine2D_3Points(double H[9], 15085+ double x1[3],double x2[3],double x3[3], 15086+ double xp1[3],double xp2[3],double xp3[3]); 15087+ 15088+/*! 15089+Solve for rotation R such that xp~Rx. 15090+Image points have to be of unit norm for the least squares to be meaningful. 15091+\param R image rotation (out) 15092+\param x1 image 1 point 1 15093+\param x2 image 1 point 2 15094+\param xp1 image 2 point 1 15095+\param xp2 image 2 point 2 15096+*/ 15097+inline void db_StitchCameraRotation_2Points(double R[9], 15098+ /*Image points have to be of unit norm 15099+ for the least squares to be meaningful*/ 15100+ double x1[3],double x2[3], 15101+ double xp1[3],double xp2[3]) 15102+{ 15103+ double* x[2]; 15104+ double* xp[2]; 15105+ double scale,t[3]; 15106+ 15107+ x[0]=x1; 15108+ x[1]=x2; 15109+ xp[0]=xp1; 15110+ xp[1]=xp2; 15111+ db_StitchSimilarity3DRaw(&scale,R,t,xp,x,2,1,0,1,0); 15112+} 15113+ 15114+/*! 15115+Solve for a homography H generated by a rotation R with a common unknown focal length f, i.e. 15116+H=diag(f,f,1)*R*diag(1/f,1/f,1) such that xp~Hx. 15117+If signed_disambiguation is true, the points are 15118+required to be in front of the camera. No specific normalization of the homogenous points 15119+is required, although it could be desirable to keep x1,x2,xp1 and xp2 of reasonable magnitude. 15120+If a solution is obtained the function returns 1, otherwise 0. If the focal length is desired 15121+a valid pointer should be passed in f 15122+*/ 15123+DB_API int db_StitchRotationCommonFocalLength_3Points(double H[9],double x1[3],double x2[3],double x3[3], 15124+ double xp1[3],double xp2[3],double xp3[3],double *f=0,int signed_disambiguation=1); 15125+ 15126+/*! 15127+Find scale, rotation and translation of the similarity that 15128+takes the nr_points inhomogenous 2D points X to Xp, 15129+i.e. for the homogenous equivalents 15130+Xp and X we would have 15131+\code 15132+Xp~ 15133+[sR t]*X 15134+[0 1] 15135+\endcode 15136+If orientation_preserving is true, R is restricted such that det(R)>0. 15137+allow_scaling, allow_rotation and allow_translation allow s,R and t 15138+to differ from 1,Identity and 0 15139+ 15140+Full similarity takes the following on 550MHz: 15141+\code 15142+0.9 microseconds with 2 points 15143+1.0 microseconds with 3 points 15144+1.1 microseconds with 4 points 15145+1.3 microseconds with 5 points 15146+1.4 microseconds with 6 points 15147+1.7 microseconds with 10 points 15148+9 microseconds with 100 points 15149+130 microseconds with 1000 points 15150+1.3 milliseconds with 10000 points 15151+35 milliseconds with 100000 points 15152+350 milliseconds with 1000000 points 15153+\endcode 15154+ 15155+Without orientation_preserving: 15156+\code 15157+3 points is minimal for (s,R,t) (R,t) 15158+2 points is minimal for (s,t) (s,R) (R) 15159+1 point is minimal for (s) (t) 15160+\endcode 15161+ 15162+With orientation_preserving: 15163+\code 15164+2 points is minimal for (s,R,t) (R,t) (s,t) 15165+1 point is minimal for (s,R) (R) (s) (t) 15166+\endcode 15167+\param scale (out) 15168+\param R 2D rotation (out) 15169+\param t 2D translation (out) 15170+\param Xp (nr_points x 2) pointer to array of image points 15171+\param X (nr_points x 2 ) pointer to array of image points 15172+\param nr_points number of points 15173+\param orientation_preserving 15174+\param allow_scaling compute scale (if 0, scale=1) 15175+\param allow_rotation compute rotation (if 0, R=[I]) 15176+\param allow_translation compute translation (if 0 t = [0,0]') 15177+*/ 15178+DB_API void db_StitchSimilarity2DRaw(double *scale,double R[4],double t[2], 15179+ double **Xp,double **X,int nr_points,int orientation_preserving=1, 15180+ int allow_scaling=1,int allow_rotation=1,int allow_translation=1); 15181+/*! 15182+See db_StitchRotationCommonFocalLength_3Points(). 15183+\param H Image similarity transformation (out) 15184+\param Xp (nr_points x 2) pointer to array of image points 15185+\param X (nr_points x 2) pointer to array of image points 15186+\param nr_points number of points 15187+\param orientation_preserving 15188+\param allow_scaling compute scale (if 0, scale=1) 15189+\param allow_rotation compute rotation (if 0, R=[I]) 15190+\param allow_translation compute translation (if 0 t = [0,0]') 15191+*/ 15192+inline void db_StitchSimilarity2D(double H[9],double **Xp,double **X,int nr_points,int orientation_preserving=1, 15193+ int allow_scaling=1,int allow_rotation=1,int allow_translation=1) 15194+{ 15195+ double s,R[4],t[2]; 15196+ 15197+ db_StitchSimilarity2DRaw(&s,R,t,Xp,X,nr_points,orientation_preserving, 15198+ allow_scaling,allow_rotation,allow_translation); 15199+ 15200+ H[0]=s*R[0]; H[1]=s*R[1]; H[2]=t[0]; 15201+ H[3]=s*R[2]; H[4]=s*R[3]; H[5]=t[1]; 15202+ db_Zero2(H+6); 15203+ H[8]=1.0; 15204+} 15205+/*\}*/ 15206+#endif /* DB_IMAGE_HOMOGRAPHY */ 15207diff --git a/benchmark/feature_stab/db_vlvm/db_metrics.h b/benchmark/feature_stab/db_vlvm/db_metrics.h 15208new file mode 100644 15209index 00000000..6b95458f 15210--- /dev/null 15211+++ b/benchmark/feature_stab/db_vlvm/db_metrics.h 15212@@ -0,0 +1,408 @@ 15213+/* 15214+ * Copyright (C) 2011 The Android Open Source Project 15215+ * 15216+ * Licensed under the Apache License, Version 2.0 (the "License"); 15217+ * you may not use this file except in compliance with the License. 15218+ * You may obtain a copy of the License at 15219+ * 15220+ * http://www.apache.org/licenses/LICENSE-2.0 15221+ * 15222+ * Unless required by applicable law or agreed to in writing, software 15223+ * distributed under the License is distributed on an "AS IS" BASIS, 15224+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15225+ * See the License for the specific language governing permissions and 15226+ * limitations under the License. 15227+ */ 15228+ 15229+/* $Id: db_metrics.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */ 15230+ 15231+#ifndef DB_METRICS 15232+#define DB_METRICS 15233+ 15234+ 15235+ 15236+/***************************************************************** 15237+* Lean and mean begins here * 15238+*****************************************************************/ 15239+ 15240+#include "db_utilities.h" 15241+/*! 15242+ * \defgroup LMMetrics (LM) Metrics 15243+ */ 15244+/*\{*/ 15245+ 15246+ 15247+ 15248+ 15249+/*! 15250+Compute function value fp and Jacobian J of robustifier given input value f*/ 15251+inline void db_CauchyDerivative(double J[4],double fp[2],const double f[2],double one_over_scale2) 15252+{ 15253+ double x2,y2,r,r2,r2s,one_over_r2,fu,r_fu,one_over_r_fu; 15254+ double one_plus_r2s,half_dfu_dx,half_dfu_dy,coeff,coeff2,coeff3; 15255+ int at_zero; 15256+ 15257+ /*The robustifier takes the input (x,y) and makes a new 15258+ vector (xp,yp) where 15259+ xp=sqrt(log(1+(x^2+y^2)*one_over_scale2))*x/sqrt(x^2+y^2) 15260+ yp=sqrt(log(1+(x^2+y^2)*one_over_scale2))*y/sqrt(x^2+y^2) 15261+ The new vector has the property 15262+ xp^2+yp^2=log(1+(x^2+y^2)*one_over_scale2) 15263+ i.e. when it is square-summed it gives the robust 15264+ reprojection error 15265+ Define 15266+ r2=(x^2+y^2) and 15267+ r2s=r2*one_over_scale2 15268+ fu=log(1+r2s)/r2 15269+ then 15270+ xp=sqrt(fu)*x 15271+ yp=sqrt(fu)*y 15272+ and 15273+ d(r2)/dx=2x 15274+ d(r2)/dy=2y 15275+ and 15276+ dfu/dx=d(r2)/dx*(r2s/(1+r2s)-log(1+r2s))/(r2*r2) 15277+ dfu/dy=d(r2)/dy*(r2s/(1+r2s)-log(1+r2s))/(r2*r2) 15278+ and 15279+ d(xp)/dx=1/(2sqrt(fu))*(dfu/dx)*x+sqrt(fu) 15280+ d(xp)/dy=1/(2sqrt(fu))*(dfu/dy)*x 15281+ d(yp)/dx=1/(2sqrt(fu))*(dfu/dx)*y 15282+ d(yp)/dy=1/(2sqrt(fu))*(dfu/dy)*y+sqrt(fu) 15283+ */ 15284+ 15285+ x2=db_sqr(f[0]); 15286+ y2=db_sqr(f[1]); 15287+ r2=x2+y2; 15288+ r=sqrt(r2); 15289+ 15290+ if(r2<=0.0) at_zero=1; 15291+ else 15292+ { 15293+ one_over_r2=1.0/r2; 15294+ r2s=r2*one_over_scale2; 15295+ one_plus_r2s=1.0+r2s; 15296+ fu=log(one_plus_r2s)*one_over_r2; 15297+ r_fu=sqrt(fu); 15298+ if(r_fu<=0.0) at_zero=1; 15299+ else 15300+ { 15301+ one_over_r_fu=1.0/r_fu; 15302+ fp[0]=r_fu*f[0]; 15303+ fp[1]=r_fu*f[1]; 15304+ /*r2s is always >= 0*/ 15305+ coeff=(r2s/one_plus_r2s*one_over_r2-fu)*one_over_r2; 15306+ half_dfu_dx=f[0]*coeff; 15307+ half_dfu_dy=f[1]*coeff; 15308+ coeff2=one_over_r_fu*half_dfu_dx; 15309+ coeff3=one_over_r_fu*half_dfu_dy; 15310+ 15311+ J[0]=coeff2*f[0]+r_fu; 15312+ J[1]=coeff3*f[0]; 15313+ J[2]=coeff2*f[1]; 15314+ J[3]=coeff3*f[1]+r_fu; 15315+ at_zero=0; 15316+ } 15317+ } 15318+ if(at_zero) 15319+ { 15320+ /*Close to zero the robustifying mapping 15321+ becomes identity*sqrt(one_over_scale2)*/ 15322+ fp[0]=0.0; 15323+ fp[1]=0.0; 15324+ J[0]=sqrt(one_over_scale2); 15325+ J[1]=0.0; 15326+ J[2]=0.0; 15327+ J[3]=J[0]; 15328+ } 15329+} 15330+ 15331+inline double db_SquaredReprojectionErrorHomography(const double y[2],const double H[9],const double x[3]) 15332+{ 15333+ double x0,x1,x2,mult; 15334+ double sd; 15335+ 15336+ x0=H[0]*x[0]+H[1]*x[1]+H[2]*x[2]; 15337+ x1=H[3]*x[0]+H[4]*x[1]+H[5]*x[2]; 15338+ x2=H[6]*x[0]+H[7]*x[1]+H[8]*x[2]; 15339+ mult=1.0/((x2!=0.0)?x2:1.0); 15340+ sd=db_sqr((y[0]-x0*mult))+db_sqr((y[1]-x1*mult)); 15341+ 15342+ return(sd); 15343+} 15344+ 15345+inline double db_SquaredInhomogenousHomographyError(const double y[2],const double H[9],const double x[2]) 15346+{ 15347+ double x0,x1,x2,mult; 15348+ double sd; 15349+ 15350+ x0=H[0]*x[0]+H[1]*x[1]+H[2]; 15351+ x1=H[3]*x[0]+H[4]*x[1]+H[5]; 15352+ x2=H[6]*x[0]+H[7]*x[1]+H[8]; 15353+ mult=1.0/((x2!=0.0)?x2:1.0); 15354+ sd=db_sqr((y[0]-x0*mult))+db_sqr((y[1]-x1*mult)); 15355+ 15356+ return(sd); 15357+} 15358+ 15359+/*! 15360+Return a constant divided by likelihood of a Cauchy distributed 15361+reprojection error given the image point y, homography H, image point 15362+point x and the squared scale coefficient one_over_scale2=1.0/(scale*scale) 15363+where scale is the half width at half maximum (hWahM) of the 15364+Cauchy distribution*/ 15365+inline double db_ExpCauchyInhomogenousHomographyError(const double y[2],const double H[9],const double x[2], 15366+ double one_over_scale2) 15367+{ 15368+ double sd; 15369+ sd=db_SquaredInhomogenousHomographyError(y,H,x); 15370+ return(1.0+sd*one_over_scale2); 15371+} 15372+ 15373+/*! 15374+Compute residual vector f between image point y and homography Hx of 15375+image point x. Also compute Jacobian of f with respect 15376+to an update dx of H*/ 15377+inline void db_DerivativeInhomHomographyError(double Jf_dx[18],double f[2],const double y[2],const double H[9], 15378+ const double x[2]) 15379+{ 15380+ double xh,yh,zh,mult,mult2,xh_mult2,yh_mult2; 15381+ /*The Jacobian of the inhomogenous coordinates with respect to 15382+ the homogenous is 15383+ [1/zh 0 -xh/(zh*zh)] 15384+ [ 0 1/zh -yh/(zh*zh)] 15385+ The Jacobian of the homogenous coordinates with respect to dH is 15386+ [x0 x1 1 0 0 0 0 0 0] 15387+ [ 0 0 0 x0 x1 1 0 0 0] 15388+ [ 0 0 0 0 0 0 x0 x1 1] 15389+ The output Jacobian is minus their product, i.e. 15390+ [-x0/zh -x1/zh -1/zh 0 0 0 x0*xh/(zh*zh) x1*xh/(zh*zh) xh/(zh*zh)] 15391+ [ 0 0 0 -x0/zh -x1/zh -1/zh x0*yh/(zh*zh) x1*yh/(zh*zh) yh/(zh*zh)]*/ 15392+ 15393+ /*Compute warped point, which is the same as 15394+ homogenous coordinates of reprojection*/ 15395+ xh=H[0]*x[0]+H[1]*x[1]+H[2]; 15396+ yh=H[3]*x[0]+H[4]*x[1]+H[5]; 15397+ zh=H[6]*x[0]+H[7]*x[1]+H[8]; 15398+ mult=1.0/((zh!=0.0)?zh:1.0); 15399+ /*Compute inhomogenous residual*/ 15400+ f[0]=y[0]-xh*mult; 15401+ f[1]=y[1]-yh*mult; 15402+ /*Compute Jacobian*/ 15403+ mult2=mult*mult; 15404+ xh_mult2=xh*mult2; 15405+ yh_mult2=yh*mult2; 15406+ Jf_dx[0]= -x[0]*mult; 15407+ Jf_dx[1]= -x[1]*mult; 15408+ Jf_dx[2]= -mult; 15409+ Jf_dx[3]=0; 15410+ Jf_dx[4]=0; 15411+ Jf_dx[5]=0; 15412+ Jf_dx[6]=x[0]*xh_mult2; 15413+ Jf_dx[7]=x[1]*xh_mult2; 15414+ Jf_dx[8]=xh_mult2; 15415+ Jf_dx[9]=0; 15416+ Jf_dx[10]=0; 15417+ Jf_dx[11]=0; 15418+ Jf_dx[12]=Jf_dx[0]; 15419+ Jf_dx[13]=Jf_dx[1]; 15420+ Jf_dx[14]=Jf_dx[2]; 15421+ Jf_dx[15]=x[0]*yh_mult2; 15422+ Jf_dx[16]=x[1]*yh_mult2; 15423+ Jf_dx[17]=yh_mult2; 15424+} 15425+ 15426+/*! 15427+Compute robust residual vector f between image point y and homography Hx of 15428+image point x. Also compute Jacobian of f with respect 15429+to an update dH of H*/ 15430+inline void db_DerivativeCauchyInhomHomographyReprojection(double Jf_dx[18],double f[2],const double y[2],const double H[9], 15431+ const double x[2],double one_over_scale2) 15432+{ 15433+ double Jf_dx_loc[18],f_loc[2]; 15434+ double J[4],J0,J1,J2,J3; 15435+ 15436+ /*Compute reprojection Jacobian*/ 15437+ db_DerivativeInhomHomographyError(Jf_dx_loc,f_loc,y,H,x); 15438+ /*Compute robustifier Jacobian*/ 15439+ db_CauchyDerivative(J,f,f_loc,one_over_scale2); 15440+ 15441+ /*Multiply the robustifier Jacobian with 15442+ the reprojection Jacobian*/ 15443+ J0=J[0];J1=J[1];J2=J[2];J3=J[3]; 15444+ Jf_dx[0]=J0*Jf_dx_loc[0]; 15445+ Jf_dx[1]=J0*Jf_dx_loc[1]; 15446+ Jf_dx[2]=J0*Jf_dx_loc[2]; 15447+ Jf_dx[3]= J1*Jf_dx_loc[12]; 15448+ Jf_dx[4]= J1*Jf_dx_loc[13]; 15449+ Jf_dx[5]= J1*Jf_dx_loc[14]; 15450+ Jf_dx[6]=J0*Jf_dx_loc[6]+J1*Jf_dx_loc[15]; 15451+ Jf_dx[7]=J0*Jf_dx_loc[7]+J1*Jf_dx_loc[16]; 15452+ Jf_dx[8]=J0*Jf_dx_loc[8]+J1*Jf_dx_loc[17]; 15453+ Jf_dx[9]= J2*Jf_dx_loc[0]; 15454+ Jf_dx[10]=J2*Jf_dx_loc[1]; 15455+ Jf_dx[11]=J2*Jf_dx_loc[2]; 15456+ Jf_dx[12]= J3*Jf_dx_loc[12]; 15457+ Jf_dx[13]= J3*Jf_dx_loc[13]; 15458+ Jf_dx[14]= J3*Jf_dx_loc[14]; 15459+ Jf_dx[15]=J2*Jf_dx_loc[6]+J3*Jf_dx_loc[15]; 15460+ Jf_dx[16]=J2*Jf_dx_loc[7]+J3*Jf_dx_loc[16]; 15461+ Jf_dx[17]=J2*Jf_dx_loc[8]+J3*Jf_dx_loc[17]; 15462+} 15463+/*! 15464+Compute residual vector f between image point y and rotation of 15465+image point x by R. Also compute Jacobian of f with respect 15466+to an update dx of R*/ 15467+inline void db_DerivativeInhomRotationReprojection(double Jf_dx[6],double f[2],const double y[2],const double R[9], 15468+ const double x[2]) 15469+{ 15470+ double xh,yh,zh,mult,mult2,xh_mult2,yh_mult2; 15471+ /*The Jacobian of the inhomogenous coordinates with respect to 15472+ the homogenous is 15473+ [1/zh 0 -xh/(zh*zh)] 15474+ [ 0 1/zh -yh/(zh*zh)] 15475+ The Jacobian at zero of the homogenous coordinates with respect to 15476+ [sin(phi) sin(ohm) sin(kap)] is 15477+ [-rx2 0 rx1 ] 15478+ [ 0 rx2 -rx0 ] 15479+ [ rx0 -rx1 0 ] 15480+ The output Jacobian is minus their product, i.e. 15481+ [1+xh*xh/(zh*zh) -xh*yh/(zh*zh) -yh/zh] 15482+ [xh*yh/(zh*zh) -1-yh*yh/(zh*zh) xh/zh]*/ 15483+ 15484+ /*Compute rotated point, which is the same as 15485+ homogenous coordinates of reprojection*/ 15486+ xh=R[0]*x[0]+R[1]*x[1]+R[2]; 15487+ yh=R[3]*x[0]+R[4]*x[1]+R[5]; 15488+ zh=R[6]*x[0]+R[7]*x[1]+R[8]; 15489+ mult=1.0/((zh!=0.0)?zh:1.0); 15490+ /*Compute inhomogenous residual*/ 15491+ f[0]=y[0]-xh*mult; 15492+ f[1]=y[1]-yh*mult; 15493+ /*Compute Jacobian*/ 15494+ mult2=mult*mult; 15495+ xh_mult2=xh*mult2; 15496+ yh_mult2=yh*mult2; 15497+ Jf_dx[0]= 1.0+xh*xh_mult2; 15498+ Jf_dx[1]= -yh*xh_mult2; 15499+ Jf_dx[2]= -yh*mult; 15500+ Jf_dx[3]= -Jf_dx[1]; 15501+ Jf_dx[4]= -1-yh*yh_mult2; 15502+ Jf_dx[5]= xh*mult; 15503+} 15504+ 15505+/*! 15506+Compute robust residual vector f between image point y and rotation of 15507+image point x by R. Also compute Jacobian of f with respect 15508+to an update dx of R*/ 15509+inline void db_DerivativeCauchyInhomRotationReprojection(double Jf_dx[6],double f[2],const double y[2],const double R[9], 15510+ const double x[2],double one_over_scale2) 15511+{ 15512+ double Jf_dx_loc[6],f_loc[2]; 15513+ double J[4],J0,J1,J2,J3; 15514+ 15515+ /*Compute reprojection Jacobian*/ 15516+ db_DerivativeInhomRotationReprojection(Jf_dx_loc,f_loc,y,R,x); 15517+ /*Compute robustifier Jacobian*/ 15518+ db_CauchyDerivative(J,f,f_loc,one_over_scale2); 15519+ 15520+ /*Multiply the robustifier Jacobian with 15521+ the reprojection Jacobian*/ 15522+ J0=J[0];J1=J[1];J2=J[2];J3=J[3]; 15523+ Jf_dx[0]=J0*Jf_dx_loc[0]+J1*Jf_dx_loc[3]; 15524+ Jf_dx[1]=J0*Jf_dx_loc[1]+J1*Jf_dx_loc[4]; 15525+ Jf_dx[2]=J0*Jf_dx_loc[2]+J1*Jf_dx_loc[5]; 15526+ Jf_dx[3]=J2*Jf_dx_loc[0]+J3*Jf_dx_loc[3]; 15527+ Jf_dx[4]=J2*Jf_dx_loc[1]+J3*Jf_dx_loc[4]; 15528+ Jf_dx[5]=J2*Jf_dx_loc[2]+J3*Jf_dx_loc[5]; 15529+} 15530+ 15531+ 15532+ 15533+/*! 15534+// remove the outliers whose projection error is larger than pre-defined 15535+*/ 15536+inline int db_RemoveOutliers_Homography(const double H[9], double *x_i,double *xp_i, double *wp,double *im, double *im_p, double *im_r, double *im_raw,double *im_raw_p,int point_count,double scale, double thresh=DB_OUTLIER_THRESHOLD) 15537+{ 15538+ double temp_valueE, t2; 15539+ int c; 15540+ int k1=0; 15541+ int k2=0; 15542+ int k3=0; 15543+ int numinliers=0; 15544+ int ind1; 15545+ int ind2; 15546+ int ind3; 15547+ int isinlier; 15548+ 15549+ // experimentally determined 15550+ t2=1.0/(thresh*thresh*thresh*thresh); 15551+ 15552+ // count the inliers 15553+ for(c=0;c<point_count;c++) 15554+ { 15555+ ind1=c<<1; 15556+ ind2=c<<2; 15557+ ind3=3*c; 15558+ 15559+ temp_valueE=db_SquaredInhomogenousHomographyError(im_p+ind3,H,im+ind3); 15560+ 15561+ isinlier=((temp_valueE<=t2)?1:0); 15562+ 15563+ // if it is inlier, then copy the 3d and 2d correspondences 15564+ if (isinlier) 15565+ { 15566+ numinliers++; 15567+ 15568+ x_i[k1]=x_i[ind1]; 15569+ x_i[k1+1]=x_i[ind1+1]; 15570+ 15571+ xp_i[k1]=xp_i[ind1]; 15572+ xp_i[k1+1]=xp_i[ind1+1]; 15573+ 15574+ k1=k1+2; 15575+ 15576+ // original normalized pixel coordinates 15577+ im[k3]=im[ind3]; 15578+ im[k3+1]=im[ind3+1]; 15579+ im[k3+2]=im[ind3+2]; 15580+ 15581+ im_r[k3]=im_r[ind3]; 15582+ im_r[k3+1]=im_r[ind3+1]; 15583+ im_r[k3+2]=im_r[ind3+2]; 15584+ 15585+ im_p[k3]=im_p[ind3]; 15586+ im_p[k3+1]=im_p[ind3+1]; 15587+ im_p[k3+2]=im_p[ind3+2]; 15588+ 15589+ // left and right raw pixel coordinates 15590+ im_raw[k3] = im_raw[ind3]; 15591+ im_raw[k3+1] = im_raw[ind3+1]; 15592+ im_raw[k3+2] = im_raw[ind3+2]; // the index 15593+ 15594+ im_raw_p[k3] = im_raw_p[ind3]; 15595+ im_raw_p[k3+1] = im_raw_p[ind3+1]; 15596+ im_raw_p[k3+2] = im_raw_p[ind3+2]; // the index 15597+ 15598+ k3=k3+3; 15599+ 15600+ // 3D coordinates 15601+ wp[k2]=wp[ind2]; 15602+ wp[k2+1]=wp[ind2+1]; 15603+ wp[k2+2]=wp[ind2+2]; 15604+ wp[k2+3]=wp[ind2+3]; 15605+ 15606+ k2=k2+4; 15607+ 15608+ } 15609+ } 15610+ 15611+ return numinliers; 15612+} 15613+ 15614+ 15615+ 15616+ 15617+ 15618+/*\}*/ 15619+ 15620+#endif /* DB_METRICS */ 15621diff --git a/benchmark/feature_stab/db_vlvm/db_rob_image_homography.cpp b/benchmark/feature_stab/db_vlvm/db_rob_image_homography.cpp 15622new file mode 100644 15623index 00000000..82dec0cb 15624--- /dev/null 15625+++ b/benchmark/feature_stab/db_vlvm/db_rob_image_homography.cpp 15626@@ -0,0 +1,1082 @@ 15627+/* 15628+ * Copyright (C) 2011 The Android Open Source Project 15629+ * 15630+ * Licensed under the Apache License, Version 2.0 (the "License"); 15631+ * you may not use this file except in compliance with the License. 15632+ * You may obtain a copy of the License at 15633+ * 15634+ * http://www.apache.org/licenses/LICENSE-2.0 15635+ * 15636+ * Unless required by applicable law or agreed to in writing, software 15637+ * distributed under the License is distributed on an "AS IS" BASIS, 15638+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15639+ * See the License for the specific language governing permissions and 15640+ * limitations under the License. 15641+ */ 15642+ 15643+/* $Id: db_rob_image_homography.cpp,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */ 15644+ 15645+#include "db_utilities.h" 15646+#include "db_rob_image_homography.h" 15647+#include "db_bundle.h" 15648+ 15649+ 15650+ 15651+/***************************************************************** 15652+* Lean and mean begins here * 15653+*****************************************************************/ 15654+ 15655+#include "db_image_homography.h" 15656+ 15657+#ifdef _VERBOSE_ 15658+#include <iostream> 15659+using namespace std; 15660+#endif /*VERBOSE*/ 15661+ 15662+inline double db_RobImageHomography_Cost(double H[9],int point_count,double *x_i,double *xp_i,double one_over_scale2) 15663+{ 15664+ int c; 15665+ double back,acc,*x_i_temp,*xp_i_temp; 15666+ 15667+ for(back=0.0,c=0;c<point_count;) 15668+ { 15669+ /*Take log of product of ten reprojection 15670+ errors to reduce nr of expensive log operations*/ 15671+ if(c+9<point_count) 15672+ { 15673+ x_i_temp=x_i+(c<<1); 15674+ xp_i_temp=xp_i+(c<<1); 15675+ 15676+ acc=db_ExpCauchyInhomogenousHomographyError(xp_i_temp,H,x_i_temp,one_over_scale2); 15677+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+2,H,x_i_temp+2,one_over_scale2); 15678+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+4,H,x_i_temp+4,one_over_scale2); 15679+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+6,H,x_i_temp+6,one_over_scale2); 15680+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+8,H,x_i_temp+8,one_over_scale2); 15681+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+10,H,x_i_temp+10,one_over_scale2); 15682+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+12,H,x_i_temp+12,one_over_scale2); 15683+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+14,H,x_i_temp+14,one_over_scale2); 15684+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+16,H,x_i_temp+16,one_over_scale2); 15685+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+18,H,x_i_temp+18,one_over_scale2); 15686+ c+=10; 15687+ } 15688+ else 15689+ { 15690+ for(acc=1.0;c<point_count;c++) 15691+ { 15692+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i+(c<<1),H,x_i+(c<<1),one_over_scale2); 15693+ } 15694+ } 15695+ back+=log(acc); 15696+ } 15697+ return(back); 15698+} 15699+ 15700+inline double db_RobImageHomography_Statistics(double H[9],int point_count,double *x_i,double *xp_i,double one_over_scale2,db_Statistics *stat,double thresh=DB_OUTLIER_THRESHOLD) 15701+{ 15702+ int c,i; 15703+ double t2,frac; 15704+ 15705+ t2=thresh*thresh; 15706+ for(i=0,c=0;c<point_count;c++) 15707+ { 15708+ i+=(db_SquaredInhomogenousHomographyError(xp_i+(c<<1),H,x_i+(c<<1))*one_over_scale2<=t2)?1:0; 15709+ } 15710+ frac=((double)i)/((double)(db_maxi(point_count,1))); 15711+ 15712+#ifdef _VERBOSE_ 15713+ std::cout << "Inlier Percentage RobImageHomography: " << frac*100.0 << "% out of " << point_count << " constraints" << std::endl; 15714+#endif /*_VERBOSE_*/ 15715+ 15716+ if(stat) 15717+ { 15718+ stat->nr_points=point_count; 15719+ stat->one_over_scale2=one_over_scale2; 15720+ stat->nr_inliers=i; 15721+ stat->inlier_fraction=frac; 15722+ 15723+ stat->cost=db_RobImageHomography_Cost(H,point_count,x_i,xp_i,one_over_scale2); 15724+ stat->model_dimension=0; 15725+ /*stat->nr_parameters=;*/ 15726+ 15727+ stat->lambda1=log(4.0); 15728+ stat->lambda2=log(4.0*((double)db_maxi(1,stat->nr_points))); 15729+ stat->lambda3=10.0; 15730+ stat->gric=stat->cost+stat->lambda1*stat->model_dimension*((double)stat->nr_points)+stat->lambda2*((double)stat->nr_parameters); 15731+ stat->inlier_evidence=((double)stat->nr_inliers)-stat->lambda3*((double)stat->nr_parameters); 15732+ } 15733+ 15734+ return(frac); 15735+} 15736+ 15737+/*Compute min_Jtf and upper right of JtJ. Return cost.*/ 15738+inline double db_RobImageHomography_Jacobians(double JtJ[81],double min_Jtf[9],double H[9],int point_count,double *x_i,double *xp_i,double one_over_scale2) 15739+{ 15740+ double back,Jf_dx[18],f[2],temp,temp2; 15741+ int i; 15742+ 15743+ db_Zero(JtJ,81); 15744+ db_Zero(min_Jtf,9); 15745+ for(back=0.0,i=0;i<point_count;i++) 15746+ { 15747+ /*Compute reprojection error vector and its Jacobian 15748+ for this point*/ 15749+ db_DerivativeCauchyInhomHomographyReprojection(Jf_dx,f,xp_i+(i<<1),H,x_i+(i<<1),one_over_scale2); 15750+ /*Perform 15751+ min_Jtf-=Jf_dx*f[0] and 15752+ min_Jtf-=(Jf_dx+9)*f[1] to accumulate -Jt%f*/ 15753+ db_RowOperation9(min_Jtf,Jf_dx,f[0]); 15754+ db_RowOperation9(min_Jtf,Jf_dx+9,f[1]); 15755+ /*Accumulate upper right of JtJ with outer product*/ 15756+ temp=Jf_dx[0]; temp2=Jf_dx[9]; 15757+ JtJ[0]+=temp*Jf_dx[0]+temp2*Jf_dx[9]; 15758+ JtJ[1]+=temp*Jf_dx[1]+temp2*Jf_dx[10]; 15759+ JtJ[2]+=temp*Jf_dx[2]+temp2*Jf_dx[11]; 15760+ JtJ[3]+=temp*Jf_dx[3]+temp2*Jf_dx[12]; 15761+ JtJ[4]+=temp*Jf_dx[4]+temp2*Jf_dx[13]; 15762+ JtJ[5]+=temp*Jf_dx[5]+temp2*Jf_dx[14]; 15763+ JtJ[6]+=temp*Jf_dx[6]+temp2*Jf_dx[15]; 15764+ JtJ[7]+=temp*Jf_dx[7]+temp2*Jf_dx[16]; 15765+ JtJ[8]+=temp*Jf_dx[8]+temp2*Jf_dx[17]; 15766+ temp=Jf_dx[1]; temp2=Jf_dx[10]; 15767+ JtJ[10]+=temp*Jf_dx[1]+temp2*Jf_dx[10]; 15768+ JtJ[11]+=temp*Jf_dx[2]+temp2*Jf_dx[11]; 15769+ JtJ[12]+=temp*Jf_dx[3]+temp2*Jf_dx[12]; 15770+ JtJ[13]+=temp*Jf_dx[4]+temp2*Jf_dx[13]; 15771+ JtJ[14]+=temp*Jf_dx[5]+temp2*Jf_dx[14]; 15772+ JtJ[15]+=temp*Jf_dx[6]+temp2*Jf_dx[15]; 15773+ JtJ[16]+=temp*Jf_dx[7]+temp2*Jf_dx[16]; 15774+ JtJ[17]+=temp*Jf_dx[8]+temp2*Jf_dx[17]; 15775+ temp=Jf_dx[2]; temp2=Jf_dx[11]; 15776+ JtJ[20]+=temp*Jf_dx[2]+temp2*Jf_dx[11]; 15777+ JtJ[21]+=temp*Jf_dx[3]+temp2*Jf_dx[12]; 15778+ JtJ[22]+=temp*Jf_dx[4]+temp2*Jf_dx[13]; 15779+ JtJ[23]+=temp*Jf_dx[5]+temp2*Jf_dx[14]; 15780+ JtJ[24]+=temp*Jf_dx[6]+temp2*Jf_dx[15]; 15781+ JtJ[25]+=temp*Jf_dx[7]+temp2*Jf_dx[16]; 15782+ JtJ[26]+=temp*Jf_dx[8]+temp2*Jf_dx[17]; 15783+ temp=Jf_dx[3]; temp2=Jf_dx[12]; 15784+ JtJ[30]+=temp*Jf_dx[3]+temp2*Jf_dx[12]; 15785+ JtJ[31]+=temp*Jf_dx[4]+temp2*Jf_dx[13]; 15786+ JtJ[32]+=temp*Jf_dx[5]+temp2*Jf_dx[14]; 15787+ JtJ[33]+=temp*Jf_dx[6]+temp2*Jf_dx[15]; 15788+ JtJ[34]+=temp*Jf_dx[7]+temp2*Jf_dx[16]; 15789+ JtJ[35]+=temp*Jf_dx[8]+temp2*Jf_dx[17]; 15790+ temp=Jf_dx[4]; temp2=Jf_dx[13]; 15791+ JtJ[40]+=temp*Jf_dx[4]+temp2*Jf_dx[13]; 15792+ JtJ[41]+=temp*Jf_dx[5]+temp2*Jf_dx[14]; 15793+ JtJ[42]+=temp*Jf_dx[6]+temp2*Jf_dx[15]; 15794+ JtJ[43]+=temp*Jf_dx[7]+temp2*Jf_dx[16]; 15795+ JtJ[44]+=temp*Jf_dx[8]+temp2*Jf_dx[17]; 15796+ temp=Jf_dx[5]; temp2=Jf_dx[14]; 15797+ JtJ[50]+=temp*Jf_dx[5]+temp2*Jf_dx[14]; 15798+ JtJ[51]+=temp*Jf_dx[6]+temp2*Jf_dx[15]; 15799+ JtJ[52]+=temp*Jf_dx[7]+temp2*Jf_dx[16]; 15800+ JtJ[53]+=temp*Jf_dx[8]+temp2*Jf_dx[17]; 15801+ temp=Jf_dx[6]; temp2=Jf_dx[15]; 15802+ JtJ[60]+=temp*Jf_dx[6]+temp2*Jf_dx[15]; 15803+ JtJ[61]+=temp*Jf_dx[7]+temp2*Jf_dx[16]; 15804+ JtJ[62]+=temp*Jf_dx[8]+temp2*Jf_dx[17]; 15805+ temp=Jf_dx[7]; temp2=Jf_dx[16]; 15806+ JtJ[70]+=temp*Jf_dx[7]+temp2*Jf_dx[16]; 15807+ JtJ[71]+=temp*Jf_dx[8]+temp2*Jf_dx[17]; 15808+ temp=Jf_dx[8]; temp2=Jf_dx[17]; 15809+ JtJ[80]+=temp*Jf_dx[8]+temp2*Jf_dx[17]; 15810+ 15811+ /*Add square-sum to cost*/ 15812+ back+=db_sqr(f[0])+db_sqr(f[1]); 15813+ } 15814+ 15815+ return(back); 15816+} 15817+ 15818+/*Compute min_Jtf and upper right of JtJ. Return cost*/ 15819+inline double db_RobCamRotation_Jacobians(double JtJ[9],double min_Jtf[3],double H[9],int point_count,double *x_i,double *xp_i,double one_over_scale2) 15820+{ 15821+ double back,Jf_dx[6],f[2]; 15822+ int i,j; 15823+ 15824+ db_Zero(JtJ,9); 15825+ db_Zero(min_Jtf,3); 15826+ for(back=0.0,i=0;i<point_count;i++) 15827+ { 15828+ /*Compute reprojection error vector and its Jacobian 15829+ for this point*/ 15830+ j=(i<<1); 15831+ db_DerivativeCauchyInhomRotationReprojection(Jf_dx,f,xp_i+j,H,x_i+j,one_over_scale2); 15832+ /*Perform 15833+ min_Jtf-=Jf_dx*f[0] and 15834+ min_Jtf-=(Jf_dx+3)*f[1] to accumulate -Jt%f*/ 15835+ db_RowOperation3(min_Jtf,Jf_dx,f[0]); 15836+ db_RowOperation3(min_Jtf,Jf_dx+3,f[1]); 15837+ /*Accumulate upper right of JtJ with outer product*/ 15838+ JtJ[0]+=Jf_dx[0]*Jf_dx[0]+Jf_dx[3]*Jf_dx[3]; 15839+ JtJ[1]+=Jf_dx[0]*Jf_dx[1]+Jf_dx[3]*Jf_dx[4]; 15840+ JtJ[2]+=Jf_dx[0]*Jf_dx[2]+Jf_dx[3]*Jf_dx[5]; 15841+ JtJ[4]+=Jf_dx[1]*Jf_dx[1]+Jf_dx[4]*Jf_dx[4]; 15842+ JtJ[5]+=Jf_dx[1]*Jf_dx[2]+Jf_dx[4]*Jf_dx[5]; 15843+ JtJ[8]+=Jf_dx[2]*Jf_dx[2]+Jf_dx[5]*Jf_dx[5]; 15844+ 15845+ /*Add square-sum to cost*/ 15846+ back+=db_sqr(f[0])+db_sqr(f[1]); 15847+ } 15848+ 15849+ return(back); 15850+} 15851+ 15852+void db_RobCamRotation_Polish(double H[9],int point_count,double *x_i,double *xp_i,double one_over_scale2, 15853+ int max_iterations,double improvement_requirement) 15854+{ 15855+ int i,update,stop; 15856+ double lambda,cost,current_cost; 15857+ double JtJ[9],min_Jtf[3],dx[3],H_p_dx[9]; 15858+ 15859+ lambda=0.001; 15860+ for(update=1,stop=0,i=0;(stop<2) && (i<max_iterations);i++) 15861+ { 15862+ /*if first time since improvement, compute Jacobian and residual*/ 15863+ if(update) 15864+ { 15865+ current_cost=db_RobCamRotation_Jacobians(JtJ,min_Jtf,H,point_count,x_i,xp_i,one_over_scale2); 15866+ update=0; 15867+ } 15868+ 15869+#ifdef _VERBOSE_ 15870+ /*std::cout << "Cost:" << current_cost << " ";*/ 15871+#endif /*_VERBOSE_*/ 15872+ 15873+ /*Come up with a hypothesis dx 15874+ based on the current lambda*/ 15875+ db_Compute_dx_3x3(dx,JtJ,min_Jtf,lambda); 15876+ 15877+ /*Compute Cost(x+dx)*/ 15878+ db_UpdateRotation(H_p_dx,H,dx); 15879+ cost=db_RobImageHomography_Cost(H_p_dx,point_count,x_i,xp_i,one_over_scale2); 15880+ 15881+ /*Is there an improvement?*/ 15882+ if(cost<current_cost) 15883+ { 15884+ /*improvement*/ 15885+ if(current_cost-cost<current_cost*improvement_requirement) stop++; 15886+ else stop=0; 15887+ lambda*=0.1; 15888+ /*Move to the hypothesised position x+dx*/ 15889+ current_cost=cost; 15890+ db_Copy9(H,H_p_dx); 15891+ db_OrthonormalizeRotation(H); 15892+ update=1; 15893+ 15894+#ifdef _VERBOSE_ 15895+ std::cout << "Step" << i << "Imp,Lambda=" << lambda << "Cost:" << current_cost << std::endl; 15896+#endif /*_VERBOSE_*/ 15897+ } 15898+ else 15899+ { 15900+ /*no improvement*/ 15901+ lambda*=10.0; 15902+ stop=0; 15903+ } 15904+ } 15905+} 15906+ 15907+inline void db_RobImageHomographyFetchJacobian(double **JtJ_ref,double *min_Jtf,double **JtJ_temp_ref,double *min_Jtf_temp,int n,int *fetch_vector) 15908+{ 15909+ int i,j,t; 15910+ double *t1,*t2; 15911+ 15912+ for(i=0;i<n;i++) 15913+ { 15914+ t=fetch_vector[i]; 15915+ min_Jtf[i]=min_Jtf_temp[t]; 15916+ t1=JtJ_ref[i]; 15917+ t2=JtJ_temp_ref[t]; 15918+ for(j=i;j<n;j++) 15919+ { 15920+ t1[j]=t2[fetch_vector[j]]; 15921+ } 15922+ } 15923+} 15924+ 15925+inline void db_RobImageHomographyMultiplyJacobian(double **JtJ_ref,double *min_Jtf,double **JtJ_temp_ref,double *min_Jtf_temp,double **JE_dx_ref,int n) 15926+{ 15927+ double JtJ_JE[72],*JtJ_JE_ref[9]; 15928+ 15929+ db_SetupMatrixRefs(JtJ_JE_ref,9,8,JtJ_JE); 15930+ 15931+ db_SymmetricExtendUpperToLower(JtJ_temp_ref,9,9); 15932+ db_MultiplyMatricesAB(JtJ_JE_ref,JtJ_temp_ref,JE_dx_ref,9,9,n); 15933+ db_UpperMultiplyMatricesAtB(JtJ_ref,JE_dx_ref,JtJ_JE_ref,n,9,n); 15934+ db_MultiplyMatrixVectorAtb(min_Jtf,JE_dx_ref,min_Jtf_temp,n,9); 15935+} 15936+ 15937+inline void db_RobImageHomographyJH_Js(double **JE_dx_ref,int j,double H[9]) 15938+{ 15939+ /*Update of upper 2x2 is multiplication by 15940+ [s 0][ cos(theta) sin(theta)] 15941+ [0 s][-sin(theta) cos(theta)]*/ 15942+ JE_dx_ref[0][j]=H[0]; 15943+ JE_dx_ref[1][j]=H[1]; 15944+ JE_dx_ref[2][j]=0; 15945+ JE_dx_ref[3][j]=H[2]; 15946+ JE_dx_ref[4][j]=H[3]; 15947+ JE_dx_ref[5][j]=0; 15948+ JE_dx_ref[6][j]=0; 15949+ JE_dx_ref[7][j]=0; 15950+ JE_dx_ref[8][j]=0; 15951+} 15952+ 15953+inline void db_RobImageHomographyJH_JR(double **JE_dx_ref,int j,double H[9]) 15954+{ 15955+ /*Update of upper 2x2 is multiplication by 15956+ [s 0][ cos(theta) sin(theta)] 15957+ [0 s][-sin(theta) cos(theta)]*/ 15958+ JE_dx_ref[0][j]= H[3]; 15959+ JE_dx_ref[1][j]= H[4]; 15960+ JE_dx_ref[2][j]=0; 15961+ JE_dx_ref[3][j]= -H[0]; 15962+ JE_dx_ref[4][j]= -H[1]; 15963+ JE_dx_ref[5][j]=0; 15964+ JE_dx_ref[6][j]=0; 15965+ JE_dx_ref[7][j]=0; 15966+ JE_dx_ref[8][j]=0; 15967+} 15968+ 15969+inline void db_RobImageHomographyJH_Jt(double **JE_dx_ref,int j,int k,double H[9]) 15970+{ 15971+ JE_dx_ref[0][j]=0; 15972+ JE_dx_ref[1][j]=0; 15973+ JE_dx_ref[2][j]=1.0; 15974+ JE_dx_ref[3][j]=0; 15975+ JE_dx_ref[4][j]=0; 15976+ JE_dx_ref[5][j]=0; 15977+ JE_dx_ref[6][j]=0; 15978+ JE_dx_ref[7][j]=0; 15979+ JE_dx_ref[8][j]=0; 15980+ 15981+ JE_dx_ref[0][k]=0; 15982+ JE_dx_ref[1][k]=0; 15983+ JE_dx_ref[2][k]=0; 15984+ JE_dx_ref[3][k]=0; 15985+ JE_dx_ref[4][k]=0; 15986+ JE_dx_ref[5][k]=1.0; 15987+ JE_dx_ref[6][k]=0; 15988+ JE_dx_ref[7][k]=0; 15989+ JE_dx_ref[8][k]=0; 15990+} 15991+ 15992+inline void db_RobImageHomographyJH_dRotFocal(double **JE_dx_ref,int j,int k,int l,int m,double H[9]) 15993+{ 15994+ double f,fi,fi2; 15995+ double R[9],J[9]; 15996+ 15997+ /*Updated matrix is diag(f+df,f+df)*dR*R*diag(1/(f+df),1/(f+df),1)*/ 15998+ f=db_FocalAndRotFromCamRotFocalHomography(R,H); 15999+ fi=db_SafeReciprocal(f); 16000+ fi2=db_sqr(fi); 16001+ db_JacobianOfRotatedPointStride(J,R,3); 16002+ JE_dx_ref[0][j]= J[0]; 16003+ JE_dx_ref[1][j]= J[1]; 16004+ JE_dx_ref[2][j]=f* J[2]; 16005+ JE_dx_ref[3][j]= J[3]; 16006+ JE_dx_ref[4][j]= J[4]; 16007+ JE_dx_ref[5][j]=f* J[5]; 16008+ JE_dx_ref[6][j]=fi*J[6]; 16009+ JE_dx_ref[7][j]=fi*J[7]; 16010+ JE_dx_ref[8][j]= J[8]; 16011+ db_JacobianOfRotatedPointStride(J,R+1,3); 16012+ JE_dx_ref[0][k]= J[0]; 16013+ JE_dx_ref[1][k]= J[1]; 16014+ JE_dx_ref[2][k]=f* J[2]; 16015+ JE_dx_ref[3][k]= J[3]; 16016+ JE_dx_ref[4][k]= J[4]; 16017+ JE_dx_ref[5][k]=f* J[5]; 16018+ JE_dx_ref[6][k]=fi*J[6]; 16019+ JE_dx_ref[7][k]=fi*J[7]; 16020+ JE_dx_ref[8][k]= J[8]; 16021+ db_JacobianOfRotatedPointStride(J,R+2,3); 16022+ JE_dx_ref[0][l]= J[0]; 16023+ JE_dx_ref[1][l]= J[1]; 16024+ JE_dx_ref[2][l]=f* J[2]; 16025+ JE_dx_ref[3][l]= J[3]; 16026+ JE_dx_ref[4][l]= J[4]; 16027+ JE_dx_ref[5][l]=f* J[5]; 16028+ JE_dx_ref[6][l]=fi*J[6]; 16029+ JE_dx_ref[7][l]=fi*J[7]; 16030+ JE_dx_ref[8][l]= J[8]; 16031+ 16032+ JE_dx_ref[0][m]=0; 16033+ JE_dx_ref[1][m]=0; 16034+ JE_dx_ref[2][m]=H[2]; 16035+ JE_dx_ref[3][m]=0; 16036+ JE_dx_ref[4][m]=0; 16037+ JE_dx_ref[5][m]=H[5]; 16038+ JE_dx_ref[6][m]= -fi2*H[6]; 16039+ JE_dx_ref[7][m]= -fi2*H[7]; 16040+ JE_dx_ref[8][m]=0; 16041+} 16042+ 16043+inline double db_RobImageHomography_Jacobians_Generic(double *JtJ_ref[8],double min_Jtf[8],int *num_param,int *frozen_coord,double H[9],int point_count,double *x_i,double *xp_i,int homography_type,double one_over_scale2) 16044+{ 16045+ double back; 16046+ int i,j,fetch_vector[8],n; 16047+ double JtJ_temp[81],min_Jtf_temp[9],JE_dx[72]; 16048+ double *JE_dx_ref[9],*JtJ_temp_ref[9]; 16049+ 16050+ /*Compute cost and JtJ,min_Jtf with respect to H*/ 16051+ back=db_RobImageHomography_Jacobians(JtJ_temp,min_Jtf_temp,H,point_count,x_i,xp_i,one_over_scale2); 16052+ 16053+ /*Compute JtJ,min_Jtf with respect to the right parameters 16054+ The formulas are 16055+ JtJ=transpose(JE_dx)*JtJ*JE_dx and 16056+ min_Jtf=transpose(JE_dx)*min_Jtf, 16057+ where the 9xN matrix JE_dx is the Jacobian of H with respect 16058+ to the update*/ 16059+ db_SetupMatrixRefs(JtJ_temp_ref,9,9,JtJ_temp); 16060+ db_SetupMatrixRefs(JE_dx_ref,9,8,JE_dx); 16061+ switch(homography_type) 16062+ { 16063+ case DB_HOMOGRAPHY_TYPE_SIMILARITY: 16064+ case DB_HOMOGRAPHY_TYPE_SIMILARITY_U: 16065+ n=4; 16066+ db_RobImageHomographyJH_Js(JE_dx_ref,0,H); 16067+ db_RobImageHomographyJH_JR(JE_dx_ref,1,H); 16068+ db_RobImageHomographyJH_Jt(JE_dx_ref,2,3,H); 16069+ db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n); 16070+ break; 16071+ case DB_HOMOGRAPHY_TYPE_ROTATION: 16072+ case DB_HOMOGRAPHY_TYPE_ROTATION_U: 16073+ n=1; 16074+ db_RobImageHomographyJH_JR(JE_dx_ref,0,H); 16075+ db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n); 16076+ break; 16077+ case DB_HOMOGRAPHY_TYPE_SCALING: 16078+ n=1; 16079+ db_RobImageHomographyJH_Js(JE_dx_ref,0,H); 16080+ db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n); 16081+ break; 16082+ case DB_HOMOGRAPHY_TYPE_S_T: 16083+ n=3; 16084+ db_RobImageHomographyJH_Js(JE_dx_ref,0,H); 16085+ db_RobImageHomographyJH_Jt(JE_dx_ref,1,2,H); 16086+ db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n); 16087+ break; 16088+ case DB_HOMOGRAPHY_TYPE_R_T: 16089+ n=3; 16090+ db_RobImageHomographyJH_JR(JE_dx_ref,0,H); 16091+ db_RobImageHomographyJH_Jt(JE_dx_ref,1,2,H); 16092+ db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n); 16093+ break; 16094+ case DB_HOMOGRAPHY_TYPE_R_S: 16095+ n=2; 16096+ db_RobImageHomographyJH_Js(JE_dx_ref,0,H); 16097+ db_RobImageHomographyJH_JR(JE_dx_ref,1,H); 16098+ db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n); 16099+ break; 16100+ 16101+ case DB_HOMOGRAPHY_TYPE_TRANSLATION: 16102+ n=2; 16103+ fetch_vector[0]=2; 16104+ fetch_vector[1]=5; 16105+ db_RobImageHomographyFetchJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,n,fetch_vector); 16106+ break; 16107+ case DB_HOMOGRAPHY_TYPE_AFFINE: 16108+ n=6; 16109+ fetch_vector[0]=0; 16110+ fetch_vector[1]=1; 16111+ fetch_vector[2]=2; 16112+ fetch_vector[3]=3; 16113+ fetch_vector[4]=4; 16114+ fetch_vector[5]=5; 16115+ db_RobImageHomographyFetchJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,n,fetch_vector); 16116+ break; 16117+ case DB_HOMOGRAPHY_TYPE_PROJECTIVE: 16118+ n=8; 16119+ *frozen_coord=db_MaxAbsIndex9(H); 16120+ for(j=0,i=0;i<9;i++) if(i!=(*frozen_coord)) 16121+ { 16122+ fetch_vector[j]=i; 16123+ j++; 16124+ } 16125+ db_RobImageHomographyFetchJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,n,fetch_vector); 16126+ break; 16127+ case DB_HOMOGRAPHY_TYPE_CAMROTATION_F: 16128+ case DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD: 16129+ n=4; 16130+ db_RobImageHomographyJH_dRotFocal(JE_dx_ref,0,1,2,3,H); 16131+ db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n); 16132+ break; 16133+ } 16134+ *num_param=n; 16135+ 16136+ return(back); 16137+} 16138+ 16139+inline void db_ImageHomographyUpdateGeneric(double H_p_dx[9],double H[9],double *dx,int homography_type,int frozen_coord) 16140+{ 16141+ switch(homography_type) 16142+ { 16143+ case DB_HOMOGRAPHY_TYPE_SIMILARITY: 16144+ case DB_HOMOGRAPHY_TYPE_SIMILARITY_U: 16145+ db_Copy9(H_p_dx,H); 16146+ db_MultiplyScaleOntoImageHomography(H,1.0+dx[0]); 16147+ db_MultiplyRotationOntoImageHomography(H,dx[1]); 16148+ H_p_dx[2]+=dx[2]; 16149+ H_p_dx[5]+=dx[3]; 16150+ break; 16151+ case DB_HOMOGRAPHY_TYPE_ROTATION: 16152+ case DB_HOMOGRAPHY_TYPE_ROTATION_U: 16153+ db_MultiplyRotationOntoImageHomography(H,dx[0]); 16154+ break; 16155+ case DB_HOMOGRAPHY_TYPE_SCALING: 16156+ db_MultiplyScaleOntoImageHomography(H,1.0+dx[0]); 16157+ break; 16158+ case DB_HOMOGRAPHY_TYPE_S_T: 16159+ db_Copy9(H_p_dx,H); 16160+ db_MultiplyScaleOntoImageHomography(H,1.0+dx[0]); 16161+ H_p_dx[2]+=dx[1]; 16162+ H_p_dx[5]+=dx[2]; 16163+ break; 16164+ case DB_HOMOGRAPHY_TYPE_R_T: 16165+ db_Copy9(H_p_dx,H); 16166+ db_MultiplyRotationOntoImageHomography(H,dx[0]); 16167+ H_p_dx[2]+=dx[1]; 16168+ H_p_dx[5]+=dx[2]; 16169+ break; 16170+ case DB_HOMOGRAPHY_TYPE_R_S: 16171+ db_Copy9(H_p_dx,H); 16172+ db_MultiplyScaleOntoImageHomography(H,1.0+dx[0]); 16173+ db_MultiplyRotationOntoImageHomography(H,dx[1]); 16174+ break; 16175+ case DB_HOMOGRAPHY_TYPE_TRANSLATION: 16176+ db_Copy9(H_p_dx,H); 16177+ H_p_dx[2]+=dx[0]; 16178+ H_p_dx[5]+=dx[1]; 16179+ break; 16180+ case DB_HOMOGRAPHY_TYPE_AFFINE: 16181+ db_UpdateImageHomographyAffine(H_p_dx,H,dx); 16182+ break; 16183+ case DB_HOMOGRAPHY_TYPE_PROJECTIVE: 16184+ db_UpdateImageHomographyProjective(H_p_dx,H,dx,frozen_coord); 16185+ break; 16186+ case DB_HOMOGRAPHY_TYPE_CAMROTATION_F: 16187+ case DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD: 16188+ db_UpdateRotFocalHomography(H_p_dx,H,dx); 16189+ break; 16190+ } 16191+} 16192+ 16193+void db_RobCamRotation_Polish_Generic(double H[9],int point_count,int homography_type,double *x_i,double *xp_i,double one_over_scale2, 16194+ int max_iterations,double improvement_requirement) 16195+{ 16196+ int i,update,stop,n; 16197+ int frozen_coord = 0; 16198+ double lambda,cost,current_cost; 16199+ double JtJ[72],min_Jtf[9],dx[8],H_p_dx[9]; 16200+ double *JtJ_ref[9],d[8]; 16201+ 16202+ lambda=0.001; 16203+ for(update=1,stop=0,i=0;(stop<2) && (i<max_iterations);i++) 16204+ { 16205+ /*if first time since improvement, compute Jacobian and residual*/ 16206+ if(update) 16207+ { 16208+ db_SetupMatrixRefs(JtJ_ref,9,8,JtJ); 16209+ current_cost=db_RobImageHomography_Jacobians_Generic(JtJ_ref,min_Jtf,&n,&frozen_coord,H,point_count,x_i,xp_i,homography_type,one_over_scale2); 16210+ update=0; 16211+ } 16212+ 16213+#ifdef _VERBOSE_ 16214+ /*std::cout << "Cost:" << current_cost << " ";*/ 16215+#endif /*_VERBOSE_*/ 16216+ 16217+ /*Come up with a hypothesis dx 16218+ based on the current lambda*/ 16219+ db_Compute_dx(dx,JtJ_ref,min_Jtf,lambda,d,n); 16220+ 16221+ /*Compute Cost(x+dx)*/ 16222+ db_ImageHomographyUpdateGeneric(H_p_dx,H,dx,homography_type,frozen_coord); 16223+ cost=db_RobImageHomography_Cost(H_p_dx,point_count,x_i,xp_i,one_over_scale2); 16224+ 16225+ /*Is there an improvement?*/ 16226+ if(cost<current_cost) 16227+ { 16228+ /*improvement*/ 16229+ if(current_cost-cost<current_cost*improvement_requirement) stop++; 16230+ else stop=0; 16231+ lambda*=0.1; 16232+ /*Move to the hypothesised position x+dx*/ 16233+ current_cost=cost; 16234+ db_Copy9(H,H_p_dx); 16235+ update=1; 16236+ 16237+#ifdef _VERBOSE_ 16238+ std::cout << "Step" << i << "Imp,Lambda=" << lambda << "Cost:" << current_cost << std::endl; 16239+#endif /*_VERBOSE_*/ 16240+ } 16241+ else 16242+ { 16243+ /*no improvement*/ 16244+ lambda*=10.0; 16245+ stop=0; 16246+ } 16247+ } 16248+} 16249+void db_RobImageHomography( 16250+ /*Best homography*/ 16251+ double H[9], 16252+ /*2DPoint to 2DPoint constraints 16253+ Points are assumed to be given in 16254+ homogenous coordinates*/ 16255+ double *im, double *im_p, 16256+ /*Nr of points in total*/ 16257+ int nr_points, 16258+ /*Calibration matrices 16259+ used to normalize the points*/ 16260+ double K[9], 16261+ double Kp[9], 16262+ /*Pre-allocated space temp_d 16263+ should point to at least 16264+ 12*nr_samples+10*nr_points 16265+ allocated positions*/ 16266+ double *temp_d, 16267+ /*Pre-allocated space temp_i 16268+ should point to at least 16269+ max(nr_samples,nr_points) 16270+ allocated positions*/ 16271+ int *temp_i, 16272+ int homography_type, 16273+ db_Statistics *stat, 16274+ int max_iterations, 16275+ int max_points, 16276+ double scale, 16277+ int nr_samples, 16278+ int chunk_size, 16279+ ///////////////////////////////////////////// 16280+ // regular use: set outlierremoveflagE =0; 16281+ // flag for the outlier removal 16282+ int outlierremoveflagE, 16283+ // if flag is 1, then the following variables 16284+ // need the input 16285+ ////////////////////////////////////// 16286+ // 3D coordinates 16287+ double *wp, 16288+ // its corresponding stereo pair's points 16289+ double *im_r, 16290+ // raw image coordinates 16291+ double *im_raw, double *im_raw_p, 16292+ // final matches 16293+ int *finalNumE) 16294+{ 16295+ /*Random seed*/ 16296+ int r_seed; 16297+ 16298+ int point_count_new; 16299+ /*Counters*/ 16300+ int i,j,c,point_count,hyp_count; 16301+ int last_hyp,new_last_hyp,last_corr; 16302+ int pos,point_pos,last_point; 16303+ /*Accumulator*/ 16304+ double acc; 16305+ /*Hypothesis pointer*/ 16306+ double *hyp_point; 16307+ /*Random sample*/ 16308+ int s[4]; 16309+ /*Pivot for hypothesis pruning*/ 16310+ double pivot; 16311+ /*Best hypothesis position*/ 16312+ int best_pos; 16313+ /*Best score*/ 16314+ double lowest_cost; 16315+ /*One over the squared scale of 16316+ Cauchy distribution*/ 16317+ double one_over_scale2; 16318+ /*temporary pointers*/ 16319+ double *x_i_temp,*xp_i_temp; 16320+ /*Temporary space for inverse calibration matrices*/ 16321+ double K_inv[9]; 16322+ double Kp_inv[9]; 16323+ /*Temporary space for homography*/ 16324+ double H_temp[9],H_temp2[9]; 16325+ /*Pointers to homogenous coordinates*/ 16326+ double *x_h_point,*xp_h_point; 16327+ /*Array of pointers to inhomogenous coordinates*/ 16328+ double *X[3],*Xp[3]; 16329+ /*Similarity parameters*/ 16330+ int orientation_preserving,allow_scaling,allow_rotation,allow_translation,sample_size; 16331+ 16332+ /*Homogenous coordinates of image points in first image*/ 16333+ double *x_h; 16334+ /*Homogenous coordinates of image points in second image*/ 16335+ double *xp_h; 16336+ /*Inhomogenous coordinates of image points in first image*/ 16337+ double *x_i; 16338+ /*Inhomogenous coordinates of image points in second image*/ 16339+ double *xp_i; 16340+ /*Homography hypotheses*/ 16341+ double *hyp_H_array; 16342+ /*Cost array*/ 16343+ double *hyp_cost_array; 16344+ /*Permutation of the hypotheses*/ 16345+ int *hyp_perm; 16346+ /*Sample of the points*/ 16347+ int *point_perm; 16348+ /*Temporary space for quick-select 16349+ 2*nr_samples*/ 16350+ double *temp_select; 16351+ 16352+ /*Get inverse calibration matrices*/ 16353+ db_InvertCalibrationMatrix(K_inv,K); 16354+ db_InvertCalibrationMatrix(Kp_inv,Kp); 16355+ /*Compute scale coefficient*/ 16356+ one_over_scale2=1.0/(scale*scale); 16357+ /*Initialize random seed*/ 16358+ r_seed=12345; 16359+ /*Set pointers to pre-allocated space*/ 16360+ hyp_cost_array=temp_d; 16361+ hyp_H_array=temp_d+nr_samples; 16362+ temp_select=temp_d+10*nr_samples; 16363+ x_h=temp_d+12*nr_samples; 16364+ xp_h=temp_d+12*nr_samples+3*nr_points; 16365+ x_i=temp_d+12*nr_samples+6*nr_points; 16366+ xp_i=temp_d+12*nr_samples+8*nr_points; 16367+ hyp_perm=temp_i; 16368+ point_perm=temp_i; 16369+ 16370+ /*Prepare a randomly permuted subset of size 16371+ point_count from the input points*/ 16372+ 16373+ point_count=db_mini(nr_points,(int)(chunk_size*log((double)nr_samples)/DB_LN2)); 16374+ 16375+ point_count_new = point_count; 16376+ 16377+ for(i=0;i<nr_points;i++) point_perm[i]=i; 16378+ 16379+ for(last_point=nr_points-1,i=0;i<point_count;i++,last_point--) 16380+ { 16381+ pos=db_RandomInt(r_seed,last_point); 16382+ point_pos=point_perm[pos]; 16383+ point_perm[pos]=point_perm[last_point]; 16384+ 16385+ /*Normalize image points with calibration 16386+ matrices and move them to x_h and xp_h*/ 16387+ c=3*point_pos; 16388+ j=3*i; 16389+ x_h_point=x_h+j; 16390+ xp_h_point=xp_h+j; 16391+ db_Multiply3x3_3x1(x_h_point,K_inv,im+c); 16392+ db_Multiply3x3_3x1(xp_h_point,Kp_inv,im_p+c); 16393+ 16394+ db_HomogenousNormalize3(x_h_point); 16395+ db_HomogenousNormalize3(xp_h_point); 16396+ 16397+ /*Dehomogenize image points and move them 16398+ to x_i and xp_i*/ 16399+ c=(i<<1); 16400+ db_DeHomogenizeImagePoint(x_i+c,x_h_point); // 2-dimension 16401+ db_DeHomogenizeImagePoint(xp_i+c,xp_h_point); //2-dimension 16402+ } 16403+ 16404+ 16405+ /*Generate Hypotheses*/ 16406+ hyp_count=0; 16407+ switch(homography_type) 16408+ { 16409+ case DB_HOMOGRAPHY_TYPE_SIMILARITY: 16410+ case DB_HOMOGRAPHY_TYPE_SIMILARITY_U: 16411+ case DB_HOMOGRAPHY_TYPE_TRANSLATION: 16412+ case DB_HOMOGRAPHY_TYPE_ROTATION: 16413+ case DB_HOMOGRAPHY_TYPE_ROTATION_U: 16414+ case DB_HOMOGRAPHY_TYPE_SCALING: 16415+ case DB_HOMOGRAPHY_TYPE_S_T: 16416+ case DB_HOMOGRAPHY_TYPE_R_T: 16417+ case DB_HOMOGRAPHY_TYPE_R_S: 16418+ 16419+ switch(homography_type) 16420+ { 16421+ case DB_HOMOGRAPHY_TYPE_SIMILARITY: 16422+ orientation_preserving=1; 16423+ allow_scaling=1; 16424+ allow_rotation=1; 16425+ allow_translation=1; 16426+ sample_size=2; 16427+ break; 16428+ case DB_HOMOGRAPHY_TYPE_SIMILARITY_U: 16429+ orientation_preserving=0; 16430+ allow_scaling=1; 16431+ allow_rotation=1; 16432+ allow_translation=1; 16433+ sample_size=3; 16434+ break; 16435+ case DB_HOMOGRAPHY_TYPE_TRANSLATION: 16436+ orientation_preserving=1; 16437+ allow_scaling=0; 16438+ allow_rotation=0; 16439+ allow_translation=1; 16440+ sample_size=1; 16441+ break; 16442+ case DB_HOMOGRAPHY_TYPE_ROTATION: 16443+ orientation_preserving=1; 16444+ allow_scaling=0; 16445+ allow_rotation=1; 16446+ allow_translation=0; 16447+ sample_size=1; 16448+ break; 16449+ case DB_HOMOGRAPHY_TYPE_ROTATION_U: 16450+ orientation_preserving=0; 16451+ allow_scaling=0; 16452+ allow_rotation=1; 16453+ allow_translation=0; 16454+ sample_size=2; 16455+ break; 16456+ case DB_HOMOGRAPHY_TYPE_SCALING: 16457+ orientation_preserving=1; 16458+ allow_scaling=1; 16459+ allow_rotation=0; 16460+ allow_translation=0; 16461+ sample_size=1; 16462+ break; 16463+ case DB_HOMOGRAPHY_TYPE_S_T: 16464+ orientation_preserving=1; 16465+ allow_scaling=1; 16466+ allow_rotation=0; 16467+ allow_translation=1; 16468+ sample_size=2; 16469+ break; 16470+ case DB_HOMOGRAPHY_TYPE_R_T: 16471+ orientation_preserving=1; 16472+ allow_scaling=0; 16473+ allow_rotation=1; 16474+ allow_translation=1; 16475+ sample_size=2; 16476+ break; 16477+ case DB_HOMOGRAPHY_TYPE_R_S: 16478+ orientation_preserving=1; 16479+ allow_scaling=1; 16480+ allow_rotation=0; 16481+ allow_translation=0; 16482+ sample_size=1; 16483+ break; 16484+ } 16485+ 16486+ if(point_count>=sample_size) for(i=0;i<nr_samples;i++) 16487+ { 16488+ db_RandomSample(s,3,point_count,r_seed); 16489+ X[0]= &x_i[s[0]<<1]; 16490+ X[1]= &x_i[s[1]<<1]; 16491+ X[2]= &x_i[s[2]<<1]; 16492+ Xp[0]= &xp_i[s[0]<<1]; 16493+ Xp[1]= &xp_i[s[1]<<1]; 16494+ Xp[2]= &xp_i[s[2]<<1]; 16495+ db_StitchSimilarity2D(&hyp_H_array[9*hyp_count],Xp,X,sample_size,orientation_preserving, 16496+ allow_scaling,allow_rotation,allow_translation); 16497+ hyp_count++; 16498+ } 16499+ break; 16500+ 16501+ case DB_HOMOGRAPHY_TYPE_CAMROTATION: 16502+ if(point_count>=2) for(i=0;i<nr_samples;i++) 16503+ { 16504+ db_RandomSample(s,2,point_count,r_seed); 16505+ db_StitchCameraRotation_2Points(&hyp_H_array[9*hyp_count], 16506+ &x_h[3*s[0]],&x_h[3*s[1]], 16507+ &xp_h[3*s[0]],&xp_h[3*s[1]]); 16508+ hyp_count++; 16509+ } 16510+ break; 16511+ 16512+ case DB_HOMOGRAPHY_TYPE_CAMROTATION_F: 16513+ if(point_count>=3) for(i=0;i<nr_samples;i++) 16514+ { 16515+ db_RandomSample(s,3,point_count,r_seed); 16516+ hyp_count+=db_StitchRotationCommonFocalLength_3Points(&hyp_H_array[9*hyp_count], 16517+ &x_h[3*s[0]],&x_h[3*s[1]],&x_h[3*s[2]], 16518+ &xp_h[3*s[0]],&xp_h[3*s[1]],&xp_h[3*s[2]]); 16519+ } 16520+ break; 16521+ 16522+ case DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD: 16523+ if(point_count>=3) for(i=0;i<nr_samples;i++) 16524+ { 16525+ db_RandomSample(s,3,point_count,r_seed); 16526+ hyp_count+=db_StitchRotationCommonFocalLength_3Points(&hyp_H_array[9*hyp_count], 16527+ &x_h[3*s[0]],&x_h[3*s[1]],&x_h[3*s[2]], 16528+ &xp_h[3*s[0]],&xp_h[3*s[1]],&xp_h[3*s[2]],NULL,0); 16529+ } 16530+ break; 16531+ 16532+ case DB_HOMOGRAPHY_TYPE_AFFINE: 16533+ if(point_count>=3) for(i=0;i<nr_samples;i++) 16534+ { 16535+ db_RandomSample(s,3,point_count,r_seed); 16536+ db_StitchAffine2D_3Points(&hyp_H_array[9*hyp_count], 16537+ &x_h[3*s[0]],&x_h[3*s[1]],&x_h[3*s[2]], 16538+ &xp_h[3*s[0]],&xp_h[3*s[1]],&xp_h[3*s[2]]); 16539+ hyp_count++; 16540+ } 16541+ break; 16542+ 16543+ case DB_HOMOGRAPHY_TYPE_PROJECTIVE: 16544+ default: 16545+ if(point_count>=4) for(i=0;i<nr_samples;i++) 16546+ { 16547+ db_RandomSample(s,4,point_count,r_seed); 16548+ db_StitchProjective2D_4Points(&hyp_H_array[9*hyp_count], 16549+ &x_h[3*s[0]],&x_h[3*s[1]],&x_h[3*s[2]],&x_h[3*s[3]], 16550+ &xp_h[3*s[0]],&xp_h[3*s[1]],&xp_h[3*s[2]],&xp_h[3*s[3]]); 16551+ hyp_count++; 16552+ } 16553+ } 16554+ 16555+ if(hyp_count) 16556+ { 16557+ /*Count cost in chunks and decimate hypotheses 16558+ until only one remains or the correspondences are 16559+ exhausted*/ 16560+ for(i=0;i<hyp_count;i++) 16561+ { 16562+ hyp_perm[i]=i; 16563+ hyp_cost_array[i]=0.0; 16564+ } 16565+ for(i=0,last_hyp=hyp_count-1;(last_hyp>0) && (i<point_count);i+=chunk_size) 16566+ { 16567+ /*Update cost with the next chunk*/ 16568+ last_corr=db_mini(i+chunk_size-1,point_count-1); 16569+ for(j=0;j<=last_hyp;j++) 16570+ { 16571+ hyp_point=hyp_H_array+9*hyp_perm[j]; 16572+ for(c=i;c<=last_corr;) 16573+ { 16574+ /*Take log of product of ten reprojection 16575+ errors to reduce nr of expensive log operations*/ 16576+ if(c+9<=last_corr) 16577+ { 16578+ x_i_temp=x_i+(c<<1); 16579+ xp_i_temp=xp_i+(c<<1); 16580+ 16581+ acc=db_ExpCauchyInhomogenousHomographyError(xp_i_temp,hyp_point,x_i_temp,one_over_scale2); 16582+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+2,hyp_point,x_i_temp+2,one_over_scale2); 16583+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+4,hyp_point,x_i_temp+4,one_over_scale2); 16584+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+6,hyp_point,x_i_temp+6,one_over_scale2); 16585+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+8,hyp_point,x_i_temp+8,one_over_scale2); 16586+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+10,hyp_point,x_i_temp+10,one_over_scale2); 16587+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+12,hyp_point,x_i_temp+12,one_over_scale2); 16588+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+14,hyp_point,x_i_temp+14,one_over_scale2); 16589+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+16,hyp_point,x_i_temp+16,one_over_scale2); 16590+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+18,hyp_point,x_i_temp+18,one_over_scale2); 16591+ c+=10; 16592+ } 16593+ else 16594+ { 16595+ for(acc=1.0;c<=last_corr;c++) 16596+ { 16597+ acc*=db_ExpCauchyInhomogenousHomographyError(xp_i+(c<<1),hyp_point,x_i+(c<<1),one_over_scale2); 16598+ } 16599+ } 16600+ hyp_cost_array[j]+=log(acc); 16601+ } 16602+ } 16603+ if (chunk_size<point_count){ 16604+ /*Prune out half of the hypotheses*/ 16605+ new_last_hyp=(last_hyp+1)/2-1; 16606+ pivot=db_LeanQuickSelect(hyp_cost_array,last_hyp+1,new_last_hyp,temp_select); 16607+ for(j=0,c=0;(j<=last_hyp) && (c<=new_last_hyp);j++) 16608+ { 16609+ if(hyp_cost_array[j]<=pivot) 16610+ { 16611+ hyp_cost_array[c]=hyp_cost_array[j]; 16612+ hyp_perm[c]=hyp_perm[j]; 16613+ c++; 16614+ } 16615+ } 16616+ last_hyp=new_last_hyp; 16617+ } 16618+ } 16619+ /*Find the best hypothesis*/ 16620+ lowest_cost=hyp_cost_array[0]; 16621+ best_pos=0; 16622+ for(j=1;j<=last_hyp;j++) 16623+ { 16624+ if(hyp_cost_array[j]<lowest_cost) 16625+ { 16626+ lowest_cost=hyp_cost_array[j]; 16627+ best_pos=j; 16628+ } 16629+ } 16630+ 16631+ /*Move the best hypothesis*/ 16632+ db_Copy9(H_temp,hyp_H_array+9*hyp_perm[best_pos]); 16633+ 16634+ // outlier removal 16635+ if (outlierremoveflagE) // no polishment needed 16636+ { 16637+ point_count_new = db_RemoveOutliers_Homography(H_temp,x_i,xp_i,wp,im,im_p,im_r,im_raw,im_raw_p,point_count,one_over_scale2); 16638+ } 16639+ else 16640+ { 16641+ /*Polish*/ 16642+ switch(homography_type) 16643+ { 16644+ case DB_HOMOGRAPHY_TYPE_SIMILARITY: 16645+ case DB_HOMOGRAPHY_TYPE_SIMILARITY_U: 16646+ case DB_HOMOGRAPHY_TYPE_TRANSLATION: 16647+ case DB_HOMOGRAPHY_TYPE_ROTATION: 16648+ case DB_HOMOGRAPHY_TYPE_ROTATION_U: 16649+ case DB_HOMOGRAPHY_TYPE_SCALING: 16650+ case DB_HOMOGRAPHY_TYPE_S_T: 16651+ case DB_HOMOGRAPHY_TYPE_R_T: 16652+ case DB_HOMOGRAPHY_TYPE_R_S: 16653+ case DB_HOMOGRAPHY_TYPE_AFFINE: 16654+ case DB_HOMOGRAPHY_TYPE_PROJECTIVE: 16655+ case DB_HOMOGRAPHY_TYPE_CAMROTATION_F: 16656+ case DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD: 16657+ db_RobCamRotation_Polish_Generic(H_temp,db_mini(point_count,max_points),homography_type,x_i,xp_i,one_over_scale2,max_iterations); 16658+ break; 16659+ case DB_HOMOGRAPHY_TYPE_CAMROTATION: 16660+ db_RobCamRotation_Polish(H_temp,db_mini(point_count,max_points),x_i,xp_i,one_over_scale2,max_iterations); 16661+ break; 16662+ } 16663+ 16664+ } 16665+ 16666+ } 16667+ else db_Identity3x3(H_temp); 16668+ 16669+ switch(homography_type) 16670+ { 16671+ case DB_HOMOGRAPHY_TYPE_PROJECTIVE: 16672+ if(stat) stat->nr_parameters=8; 16673+ break; 16674+ case DB_HOMOGRAPHY_TYPE_AFFINE: 16675+ if(stat) stat->nr_parameters=6; 16676+ break; 16677+ case DB_HOMOGRAPHY_TYPE_SIMILARITY: 16678+ case DB_HOMOGRAPHY_TYPE_SIMILARITY_U: 16679+ case DB_HOMOGRAPHY_TYPE_CAMROTATION_F: 16680+ case DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD: 16681+ if(stat) stat->nr_parameters=4; 16682+ break; 16683+ case DB_HOMOGRAPHY_TYPE_CAMROTATION: 16684+ if(stat) stat->nr_parameters=3; 16685+ break; 16686+ case DB_HOMOGRAPHY_TYPE_TRANSLATION: 16687+ case DB_HOMOGRAPHY_TYPE_S_T: 16688+ case DB_HOMOGRAPHY_TYPE_R_T: 16689+ case DB_HOMOGRAPHY_TYPE_R_S: 16690+ if(stat) stat->nr_parameters=2; 16691+ break; 16692+ case DB_HOMOGRAPHY_TYPE_ROTATION: 16693+ case DB_HOMOGRAPHY_TYPE_ROTATION_U: 16694+ case DB_HOMOGRAPHY_TYPE_SCALING: 16695+ if(stat) stat->nr_parameters=1; 16696+ break; 16697+ } 16698+ 16699+ db_RobImageHomography_Statistics(H_temp,db_mini(point_count,max_points),x_i,xp_i,one_over_scale2,stat); 16700+ 16701+ /*Put on the calibration matrices*/ 16702+ db_Multiply3x3_3x3(H_temp2,H_temp,K_inv); 16703+ db_Multiply3x3_3x3(H,Kp,H_temp2); 16704+ 16705+ if (finalNumE) 16706+ *finalNumE = point_count_new; 16707+ 16708+} 16709diff --git a/benchmark/feature_stab/db_vlvm/db_rob_image_homography.h b/benchmark/feature_stab/db_vlvm/db_rob_image_homography.h 16710new file mode 100644 16711index 00000000..59cde7da 16712--- /dev/null 16713+++ b/benchmark/feature_stab/db_vlvm/db_rob_image_homography.h 16714@@ -0,0 +1,148 @@ 16715+/* 16716+ * Copyright (C) 2011 The Android Open Source Project 16717+ * 16718+ * Licensed under the Apache License, Version 2.0 (the "License"); 16719+ * you may not use this file except in compliance with the License. 16720+ * You may obtain a copy of the License at 16721+ * 16722+ * http://www.apache.org/licenses/LICENSE-2.0 16723+ * 16724+ * Unless required by applicable law or agreed to in writing, software 16725+ * distributed under the License is distributed on an "AS IS" BASIS, 16726+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16727+ * See the License for the specific language governing permissions and 16728+ * limitations under the License. 16729+ */ 16730+ 16731+/* $Id: db_rob_image_homography.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */ 16732+ 16733+#ifndef DB_ROB_IMAGE_HOMOGRAPHY 16734+#define DB_ROB_IMAGE_HOMOGRAPHY 16735+ 16736+#include "db_utilities.h" 16737+#include "db_robust.h" 16738+#include "db_metrics.h" 16739+ 16740+#include <stdlib.h> // for NULL 16741+ 16742+ 16743+/***************************************************************** 16744+* Lean and mean begins here * 16745+*****************************************************************/ 16746+/*! 16747+ * \defgroup LMRobImageHomography (LM) Robust Image Homography 16748+ */ 16749+/*\{*/ 16750+ 16751+#define DB_HOMOGRAPHY_TYPE_DEFAULT 0 16752+#define DB_HOMOGRAPHY_TYPE_PROJECTIVE 0 16753+#define DB_HOMOGRAPHY_TYPE_AFFINE 1 16754+#define DB_HOMOGRAPHY_TYPE_SIMILARITY 2 16755+#define DB_HOMOGRAPHY_TYPE_SIMILARITY_U 3 16756+#define DB_HOMOGRAPHY_TYPE_TRANSLATION 4 16757+#define DB_HOMOGRAPHY_TYPE_ROTATION 5 16758+#define DB_HOMOGRAPHY_TYPE_ROTATION_U 6 16759+#define DB_HOMOGRAPHY_TYPE_SCALING 7 16760+#define DB_HOMOGRAPHY_TYPE_S_T 8 16761+#define DB_HOMOGRAPHY_TYPE_R_T 9 16762+#define DB_HOMOGRAPHY_TYPE_R_S 10 16763+#define DB_HOMOGRAPHY_TYPE_CAMROTATION 11 16764+#define DB_HOMOGRAPHY_TYPE_CAMROTATION_F 12 16765+#define DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD 13 16766+ 16767+/*! 16768+Solve for homography H such that xp~Hx 16769+\param H best homography 16770+ 16771+2D point to 2D point constraints: 16772+ 16773+\param im first image points 16774+\param im_p second image points 16775+\param nr_points number of points 16776+ 16777+Calibration matrices: 16778+ 16779+\param K first camera 16780+\param Kp second camera 16781+ 16782+ Temporary space: 16783+ 16784+ \param temp_d pre-allocated space of size 12*nr_samples+10*nr_points doubles 16785+ \param temp_i pre-allocated space of size max(nr_samples,nr_points) ints 16786+ 16787+ Statistics for this estimation 16788+ 16789+ \param stat NULL - do not compute 16790+ 16791+ \param homography_type see DB_HOMOGRAPHY_TYPE_* definitions above 16792+ 16793+ Estimation parameters: 16794+ 16795+ \param max_iterations max number of polishing steps 16796+ \param max_points only use this many points 16797+ \param scale Cauchy scale coefficient (see db_ExpCauchyReprojectionError() ) 16798+ \param nr_samples number of times to compute a hypothesis 16799+ \param chunk_size size of cost chunks 16800+*/ 16801+DB_API void db_RobImageHomography( 16802+ /*Best homography*/ 16803+ double H[9], 16804+ /*2DPoint to 2DPoint constraints 16805+ Points are assumed to be given in 16806+ homogenous coordinates*/ 16807+ double *im,double *im_p, 16808+ /*Nr of points in total*/ 16809+ int nr_points, 16810+ /*Calibration matrices 16811+ used to normalize the points*/ 16812+ double K[9], 16813+ double Kp[9], 16814+ /*Pre-allocated space temp_d 16815+ should point to at least 16816+ 12*nr_samples+10*nr_points 16817+ allocated positions*/ 16818+ double *temp_d, 16819+ /*Pre-allocated space temp_i 16820+ should point to at least 16821+ max(nr_samples,nr_points) 16822+ allocated positions*/ 16823+ int *temp_i, 16824+ int homography_type=DB_HOMOGRAPHY_TYPE_DEFAULT, 16825+ db_Statistics *stat=NULL, 16826+ int max_iterations=DB_DEFAULT_MAX_ITERATIONS, 16827+ int max_points=DB_DEFAULT_MAX_POINTS, 16828+ double scale=DB_POINT_STANDARDDEV, 16829+ int nr_samples=DB_DEFAULT_NR_SAMPLES, 16830+ int chunk_size=DB_DEFAULT_CHUNK_SIZE, 16831+ /////////////////////////////////////////////////// 16832+ // flag for the outlier removal 16833+ int outlierremoveflagE = 0, 16834+ // if flag is 1, then the following variables 16835+ // need to input 16836+ /////////////////////////////////////////////////// 16837+ // 3D coordinates 16838+ double *wp=NULL, 16839+ // its corresponding stereo pair's points 16840+ double *im_r=NULL, 16841+ // raw image coordinates 16842+ double *im_raw=NULL, double *im_raw_p=NULL, 16843+ // final matches 16844+ int *final_NumE=0); 16845+ 16846+DB_API double db_RobImageHomography_Cost(double H[9],int point_count,double *x_i, 16847+ double *xp_i,double one_over_scale2); 16848+ 16849+ 16850+DB_API void db_RobCamRotation_Polish(double H[9],int point_count,double *x_i, 16851+ double *xp_i, double one_over_scale2, 16852+ int max_iterations=DB_DEFAULT_MAX_ITERATIONS, 16853+ double improvement_requirement=DB_DEFAULT_IMP_REQ); 16854+ 16855+ 16856+DB_API void db_RobCamRotation_Polish_Generic(double H[9],int point_count,int homography_type, 16857+ double *x_i,double *xp_i,double one_over_scale2, 16858+ int max_iterations=DB_DEFAULT_MAX_ITERATIONS, 16859+ double improvement_requirement=DB_DEFAULT_IMP_REQ); 16860+ 16861+ 16862+#endif /* DB_ROB_IMAGE_HOMOGRAPHY */ 16863diff --git a/benchmark/feature_stab/db_vlvm/db_robust.h b/benchmark/feature_stab/db_vlvm/db_robust.h 16864new file mode 100644 16865index 00000000..be0794c6 16866--- /dev/null 16867+++ b/benchmark/feature_stab/db_vlvm/db_robust.h 16868@@ -0,0 +1,61 @@ 16869+/* 16870+ * Copyright (C) 2011 The Android Open Source Project 16871+ * 16872+ * Licensed under the Apache License, Version 2.0 (the "License"); 16873+ * you may not use this file except in compliance with the License. 16874+ * You may obtain a copy of the License at 16875+ * 16876+ * http://www.apache.org/licenses/LICENSE-2.0 16877+ * 16878+ * Unless required by applicable law or agreed to in writing, software 16879+ * distributed under the License is distributed on an "AS IS" BASIS, 16880+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16881+ * See the License for the specific language governing permissions and 16882+ * limitations under the License. 16883+ */ 16884+ 16885+/* $Id: db_robust.h,v 1.4 2011/06/17 14:03:31 mbansal Exp $ */ 16886+ 16887+#ifndef DB_ROBUST 16888+#define DB_ROBUST 16889+ 16890+ 16891+ 16892+/***************************************************************** 16893+* Lean and mean begins here * 16894+*****************************************************************/ 16895+/*! 16896+ * \defgroup LMRobust (LM) Robust Estimation 16897+ */ 16898+ 16899+/*! 16900+ \struct db_Statistics 16901+ \ingroup LMRobust 16902+ \brief (LnM) Sampling problem statistics 16903+ \date Mon Sep 10 10:28:08 EDT 2007 16904+ \par Copyright: 2007 Sarnoff Corporation. All Rights Reserved 16905+ */ 16906+ struct db_stat_struct 16907+ { 16908+ int nr_points; 16909+ int nr_inliers; 16910+ double inlier_fraction; 16911+ double cost; 16912+ double one_over_scale2; 16913+ double lambda1; 16914+ double lambda2; 16915+ double lambda3; 16916+ int nr_parameters; 16917+ int model_dimension; 16918+ double gric; 16919+ double inlier_evidence; 16920+ double posestd[6]; 16921+ double rotationvecCov[9]; 16922+ double translationvecCov[9]; 16923+ int posecov_inliercount; 16924+ int posecovready; 16925+ double median_reprojection_error; 16926+ }; 16927+ typedef db_stat_struct db_Statistics; 16928+ 16929+#endif /* DB_ROBUST */ 16930diff --git a/benchmark/feature_stab/db_vlvm/db_utilities.cpp b/benchmark/feature_stab/db_vlvm/db_utilities.cpp 16931new file mode 100644 16932index 00000000..ce2093b0 16933--- /dev/null 16934+++ b/benchmark/feature_stab/db_vlvm/db_utilities.cpp 16935@@ -0,0 +1,176 @@ 16936+/* 16937+ * Copyright (C) 2011 The Android Open Source Project 16938+ * 16939+ * Licensed under the Apache License, Version 2.0 (the "License"); 16940+ * you may not use this file except in compliance with the License. 16941+ * You may obtain a copy of the License at 16942+ * 16943+ * http://www.apache.org/licenses/LICENSE-2.0 16944+ * 16945+ * Unless required by applicable law or agreed to in writing, software 16946+ * distributed under the License is distributed on an "AS IS" BASIS, 16947+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16948+ * See the License for the specific language governing permissions and 16949+ * limitations under the License. 16950+ */ 16951+ 16952+/* $Id: db_utilities.cpp,v 1.4 2011/06/17 14:03:31 mbansal Exp $ */ 16953+ 16954+#include "db_utilities.h" 16955+#include <string.h> 16956+#include <stdio.h> 16957+ 16958+float** db_SetupImageReferences_f(float *im,int w,int h) 16959+{ 16960+ int i; 16961+ float **img; 16962+ assert(im); 16963+ img=new float* [h]; 16964+ for(i=0;i<h;i++) 16965+ { 16966+ img[i]=im+w*i; 16967+ } 16968+ return(img); 16969+} 16970+ 16971+unsigned char** db_SetupImageReferences_u(unsigned char *im,int w,int h) 16972+{ 16973+ int i; 16974+ unsigned char **img; 16975+ 16976+ assert(im); 16977+ 16978+ img=new unsigned char* [h]; 16979+ for(i=0;i<h;i++) 16980+ { 16981+ img[i]=im+w*i; 16982+ } 16983+ return(img); 16984+} 16985+float** db_AllocImage_f(int w,int h,int over_allocation) 16986+{ 16987+ float **img,*im; 16988+ 16989+ im=new float [w*h+over_allocation]; 16990+ img=db_SetupImageReferences_f(im,w,h); 16991+ 16992+ return(img); 16993+} 16994+ 16995+unsigned char** db_AllocImage_u(int w,int h,int over_allocation) 16996+{ 16997+ unsigned char **img,*im; 16998+ 16999+ im=new unsigned char [w*h+over_allocation]; 17000+ img=db_SetupImageReferences_u(im,w,h); 17001+ 17002+ return(img); 17003+} 17004+ 17005+void db_FreeImage_f(float **img,int h) 17006+{ 17007+ delete [] (img[0]); 17008+ delete [] img; 17009+} 17010+ 17011+void db_FreeImage_u(unsigned char **img,int h) 17012+{ 17013+ delete [] (img[0]); 17014+ delete [] img; 17015+} 17016+ 17017+// ----------------------------------------------------------------------------------------------------------- ; 17018+// 17019+// copy image (source to destination) 17020+// ---> must be a 2D image array with the same image size 17021+// ---> the size of the input and output images must be same 17022+// 17023+// ------------------------------------------------------------------------------------------------------------ ; 17024+void db_CopyImage_u(unsigned char **d,const unsigned char * const *s, int w, int h, int over_allocation) 17025+{ 17026+ int i; 17027+ 17028+ for (i=0;i<h;i++) 17029+ { 17030+ memcpy(d[i],s[i],w*sizeof(unsigned char)); 17031+ } 17032+ 17033+ memcpy(&d[h],&d[h],over_allocation); 17034+ 17035+} 17036+ 17037+inline void db_WarpImageLutFast_u(const unsigned char * const * src, unsigned char ** dst, int w, int h, 17038+ const float * const * lut_x, const float * const * lut_y) 17039+{ 17040+ assert(src && dst); 17041+ int xd=0, yd=0; 17042+ 17043+ for ( int i = 0; i < w; ++i ) 17044+ for ( int j = 0; j < h; ++j ) 17045+ { 17046+ //xd = static_cast<unsigned int>(lut_x[j][i]); 17047+ //yd = static_cast<unsigned int>(lut_y[j][i]); 17048+ xd = (unsigned int)(lut_x[j][i]); 17049+ yd = (unsigned int)(lut_y[j][i]); 17050+ if ( xd >= w || yd >= h || 17051+ xd < 0 || yd < 0) 17052+ dst[j][i] = 0; 17053+ else 17054+ dst[j][i] = src[yd][xd]; 17055+ } 17056+} 17057+ 17058+inline void db_WarpImageLutBilinear_u(const unsigned char * const * src, unsigned char ** dst, int w, int h, 17059+ const float * const * lut_x,const float * const* lut_y) 17060+{ 17061+ assert(src && dst); 17062+ double xd=0.0, yd=0.0; 17063+ 17064+ for ( int i = 0; i < w; ++i ) 17065+ for ( int j = 0; j < h; ++j ) 17066+ { 17067+ xd = static_cast<double>(lut_x[j][i]); 17068+ yd = static_cast<double>(lut_y[j][i]); 17069+ if ( xd > w || yd > h || 17070+ xd < 0.0 || yd < 0.0) 17071+ dst[j][i] = 0; 17072+ else 17073+ dst[j][i] = db_BilinearInterpolation(yd, xd, src); 17074+ } 17075+} 17076+ 17077+ 17078+void db_WarpImageLut_u(const unsigned char * const * src, unsigned char ** dst, int w, int h, 17079+ const float * const * lut_x,const float * const * lut_y, int type) 17080+{ 17081+ switch (type) 17082+ { 17083+ case DB_WARP_FAST: 17084+ db_WarpImageLutFast_u(src,dst,w,h,lut_x,lut_y); 17085+ break; 17086+ case DB_WARP_BILINEAR: 17087+ db_WarpImageLutBilinear_u(src,dst,w,h,lut_x,lut_y); 17088+ break; 17089+ default: 17090+ break; 17091+ } 17092+} 17093+ 17094+ 17095+void db_PrintDoubleVector(double *a,long size) 17096+{ 17097+ printf("[ "); 17098+ for(long i=0;i<size;i++) printf("%lf ",a[i]); 17099+ printf("]"); 17100+} 17101+ 17102+void db_PrintDoubleMatrix(double *a,long rows,long cols) 17103+{ 17104+ printf("[\n"); 17105+ for(long i=0;i<rows;i++) 17106+ { 17107+ for(long j=0;j<cols;j++) printf("%lf ",a[i*cols+j]); 17108+ printf("\n"); 17109+ } 17110+ printf("]"); 17111+} 17112diff --git a/benchmark/feature_stab/db_vlvm/db_utilities.h b/benchmark/feature_stab/db_vlvm/db_utilities.h 17113new file mode 100644 17114index 00000000..fa9c8774 17115--- /dev/null 17116+++ b/benchmark/feature_stab/db_vlvm/db_utilities.h 17117@@ -0,0 +1,571 @@ 17118+/* 17119+ * Copyright (C) 2011 The Android Open Source Project 17120+ * 17121+ * Licensed under the Apache License, Version 2.0 (the "License"); 17122+ * you may not use this file except in compliance with the License. 17123+ * You may obtain a copy of the License at 17124+ * 17125+ * http://www.apache.org/licenses/LICENSE-2.0 17126+ * 17127+ * Unless required by applicable law or agreed to in writing, software 17128+ * distributed under the License is distributed on an "AS IS" BASIS, 17129+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17130+ * See the License for the specific language governing permissions and 17131+ * limitations under the License. 17132+ */ 17133+ 17134+/* $Id: db_utilities.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */ 17135+ 17136+#ifndef DB_UTILITIES_H 17137+#define DB_UTILITIES_H 17138+ 17139+ 17140+#ifdef _WIN32 17141+#pragma warning(disable: 4275) 17142+#pragma warning(disable: 4251) 17143+#pragma warning(disable: 4786) 17144+#pragma warning(disable: 4800) 17145+#pragma warning(disable: 4018) /* signed-unsigned mismatch */ 17146+#endif /* _WIN32 */ 17147+ 17148+#ifdef _WIN32 17149+ #ifdef DBDYNAMIC_EXPORTS 17150+ #define DB_API __declspec(dllexport) 17151+ #else 17152+ #ifdef DBDYNAMIC_IMPORTS 17153+ #define DB_API __declspec(dllimport) 17154+ #else 17155+ #define DB_API 17156+ #endif 17157+ #endif 17158+#else 17159+ #define DB_API 17160+#endif /* _WIN32 */ 17161+ 17162+#ifdef _VERBOSE_ 17163+#include <iostream> 17164+#endif 17165+ 17166+#include <math.h> 17167+ 17168+#include <assert.h> 17169+#include "db_utilities_constants.h" 17170+/*! 17171+ * \defgroup LMBasicUtilities (LM) Utility Functions (basic math, linear algebra and array manipulations) 17172+ */ 17173+/*\{*/ 17174+ 17175+/*! 17176+ * Round double into int using fld and fistp instructions. 17177+ */ 17178+inline int db_roundi (double x) { 17179+#ifdef WIN32_ASM 17180+ int n; 17181+ __asm 17182+ { 17183+ fld x; 17184+ fistp n; 17185+ } 17186+ return n; 17187+#else 17188+ return static_cast<int>(floor(x+0.5)); 17189+#endif 17190+} 17191+ 17192+/*! 17193+ * Square a double. 17194+ */ 17195+inline double db_sqr(double a) 17196+{ 17197+ return(a*a); 17198+} 17199+ 17200+/*! 17201+ * Square a long. 17202+ */ 17203+inline long db_sqr(long a) 17204+{ 17205+ return(a*a); 17206+} 17207+ 17208+/*! 17209+ * Square an int. 17210+ */ 17211+inline long db_sqr(int a) 17212+{ 17213+ return(a*a); 17214+} 17215+ 17216+/*! 17217+ * Maximum of two doubles. 17218+ */ 17219+inline double db_maxd(double a,double b) 17220+{ 17221+ if(b>a) return(b); 17222+ else return(a); 17223+} 17224+/*! 17225+ * Minumum of two doubles. 17226+ */ 17227+inline double db_mind(double a,double b) 17228+{ 17229+ if(b<a) return(b); 17230+ else return(a); 17231+} 17232+ 17233+ 17234+/*! 17235+ * Maximum of two ints. 17236+ */ 17237+inline int db_maxi(int a,int b) 17238+{ 17239+ if(b>a) return(b); 17240+ else return(a); 17241+} 17242+ 17243+/*! 17244+ * Minimum of two numbers. 17245+ */ 17246+inline int db_mini(int a,int b) 17247+{ 17248+ if(b<a) return(b); 17249+ else return(a); 17250+} 17251+/*! 17252+ * Maximum of two numbers. 17253+ */ 17254+inline long db_maxl(long a,long b) 17255+{ 17256+ if(b>a) return(b); 17257+ else return(a); 17258+} 17259+ 17260+/*! 17261+ * Minimum of two numbers. 17262+ */ 17263+inline long db_minl(long a,long b) 17264+{ 17265+ if(b<a) return(b); 17266+ else return(a); 17267+} 17268+ 17269+/*! 17270+ * Sign of a number. 17271+ * \return -1.0 if negative, 1.0 if positive. 17272+ */ 17273+inline double db_sign(double x) 17274+{ 17275+ if(x>=0.0) return(1.0); 17276+ else return(-1.0); 17277+} 17278+/*! 17279+ * Absolute value. 17280+ */ 17281+inline int db_absi(int a) 17282+{ 17283+ if(a<0) return(-a); 17284+ else return(a); 17285+} 17286+/*! 17287+ * Absolute value. 17288+ */ 17289+inline float db_absf(float a) 17290+{ 17291+ if(a<0) return(-a); 17292+ else return(a); 17293+} 17294+ 17295+/*! 17296+ * Absolute value. 17297+ */ 17298+inline double db_absd(double a) 17299+{ 17300+ if(a<0) return(-a); 17301+ else return(a); 17302+} 17303+ 17304+/*! 17305+ * Reciprocal (1/a). Prevents divide by 0. 17306+ * \return 1/a if a != 0. 1.0 otherwise. 17307+ */ 17308+inline double db_SafeReciprocal(double a) 17309+{ 17310+ return((a!=0.0)?(1.0/a):1.0); 17311+} 17312+ 17313+/*! 17314+ * Division. Prevents divide by 0. 17315+ * \return a/b if b!=0. a otherwise. 17316+ */ 17317+inline double db_SafeDivision(double a,double b) 17318+{ 17319+ return((b!=0.0)?(a/b):a); 17320+} 17321+ 17322+/*! 17323+ * Square root. Prevents imaginary output. 17324+ * \return sqrt(a) if a > 0.0. 0.0 otherewise. 17325+ */ 17326+inline double db_SafeSqrt(double a) 17327+{ 17328+ return((a>=0.0)?(sqrt(a)):0.0); 17329+} 17330+ 17331+/*! 17332+ * Square root of a reciprocal. Prevents divide by 0 and imaginary output. 17333+ * \return sqrt(1/a) if a > 0.0. 1.0 otherewise. 17334+ */ 17335+inline double db_SafeSqrtReciprocal(double a) 17336+{ 17337+ return((a>0.0)?(sqrt(1.0/a)):1.0); 17338+} 17339+/*! 17340+ * Cube root. 17341+ */ 17342+inline double db_CubRoot(double x) 17343+{ 17344+ if(x>=0.0) return(pow(x,1.0/3.0)); 17345+ else return(-pow(-x,1.0/3.0)); 17346+} 17347+/*! 17348+ * Sum of squares of elements of x. 17349+ */ 17350+inline double db_SquareSum3(const double x[3]) 17351+{ 17352+ return(db_sqr(x[0])+db_sqr(x[1])+db_sqr(x[2])); 17353+} 17354+/*! 17355+ * Sum of squares of elements of x. 17356+ */ 17357+inline double db_SquareSum7(double x[7]) 17358+{ 17359+ return(db_sqr(x[0])+db_sqr(x[1])+db_sqr(x[2])+ 17360+ db_sqr(x[3])+db_sqr(x[4])+db_sqr(x[5])+ 17361+ db_sqr(x[6])); 17362+} 17363+/*! 17364+ * Sum of squares of elements of x. 17365+ */ 17366+inline double db_SquareSum9(double x[9]) 17367+{ 17368+ return(db_sqr(x[0])+db_sqr(x[1])+db_sqr(x[2])+ 17369+ db_sqr(x[3])+db_sqr(x[4])+db_sqr(x[5])+ 17370+ db_sqr(x[6])+db_sqr(x[7])+db_sqr(x[8])); 17371+} 17372+/*! 17373+ * Copy a vector. 17374+ * \param xd destination 17375+ * \param xs source 17376+ */ 17377+void inline db_Copy3(double xd[3],const double xs[3]) 17378+{ 17379+ xd[0]=xs[0];xd[1]=xs[1];xd[2]=xs[2]; 17380+} 17381+/*! 17382+ * Copy a vector. 17383+ * \param xd destination 17384+ * \param xs source 17385+ */ 17386+void inline db_Copy6(double xd[6],const double xs[6]) 17387+{ 17388+ xd[0]=xs[0];xd[1]=xs[1];xd[2]=xs[2]; 17389+ xd[3]=xs[3];xd[4]=xs[4];xd[5]=xs[5]; 17390+} 17391+/*! 17392+ * Copy a vector. 17393+ * \param xd destination 17394+ * \param xs source 17395+ */ 17396+void inline db_Copy9(double xd[9],const double xs[9]) 17397+{ 17398+ xd[0]=xs[0];xd[1]=xs[1];xd[2]=xs[2]; 17399+ xd[3]=xs[3];xd[4]=xs[4];xd[5]=xs[5]; 17400+ xd[6]=xs[6];xd[7]=xs[7];xd[8]=xs[8]; 17401+} 17402+ 17403+/*! 17404+ * Scalar product: Transpose(A)*B. 17405+ */ 17406+inline double db_ScalarProduct4(const double A[4],const double B[4]) 17407+{ 17408+ return(A[0]*B[0]+A[1]*B[1]+A[2]*B[2]+A[3]*B[3]); 17409+} 17410+/*! 17411+ * Scalar product: Transpose(A)*B. 17412+ */ 17413+inline double db_ScalarProduct7(const double A[7],const double B[7]) 17414+{ 17415+ return(A[0]*B[0]+A[1]*B[1]+A[2]*B[2]+ 17416+ A[3]*B[3]+A[4]*B[4]+A[5]*B[5]+ 17417+ A[6]*B[6]); 17418+} 17419+/*! 17420+ * Scalar product: Transpose(A)*B. 17421+ */ 17422+inline double db_ScalarProduct9(const double A[9],const double B[9]) 17423+{ 17424+ return(A[0]*B[0]+A[1]*B[1]+A[2]*B[2]+ 17425+ A[3]*B[3]+A[4]*B[4]+A[5]*B[5]+ 17426+ A[6]*B[6]+A[7]*B[7]+A[8]*B[8]); 17427+} 17428+/*! 17429+ * Vector addition: S=A+B. 17430+ */ 17431+inline void db_AddVectors6(double S[6],const double A[6],const double B[6]) 17432+{ 17433+ S[0]=A[0]+B[0]; S[1]=A[1]+B[1]; S[2]=A[2]+B[2]; S[3]=A[3]+B[3]; S[4]=A[4]+B[4]; 17434+ S[5]=A[5]+B[5]; 17435+} 17436+/*! 17437+ * Multiplication: C(3x1)=A(3x3)*B(3x1). 17438+ */ 17439+inline void db_Multiply3x3_3x1(double y[3],const double A[9],const double x[3]) 17440+{ 17441+ y[0]=A[0]*x[0]+A[1]*x[1]+A[2]*x[2]; 17442+ y[1]=A[3]*x[0]+A[4]*x[1]+A[5]*x[2]; 17443+ y[2]=A[6]*x[0]+A[7]*x[1]+A[8]*x[2]; 17444+} 17445+inline void db_Multiply3x3_3x3(double C[9], const double A[9],const double B[9]) 17446+{ 17447+ C[0]=A[0]*B[0]+A[1]*B[3]+A[2]*B[6]; 17448+ C[1]=A[0]*B[1]+A[1]*B[4]+A[2]*B[7]; 17449+ C[2]=A[0]*B[2]+A[1]*B[5]+A[2]*B[8]; 17450+ 17451+ C[3]=A[3]*B[0]+A[4]*B[3]+A[5]*B[6]; 17452+ C[4]=A[3]*B[1]+A[4]*B[4]+A[5]*B[7]; 17453+ C[5]=A[3]*B[2]+A[4]*B[5]+A[5]*B[8]; 17454+ 17455+ C[6]=A[6]*B[0]+A[7]*B[3]+A[8]*B[6]; 17456+ C[7]=A[6]*B[1]+A[7]*B[4]+A[8]*B[7]; 17457+ C[8]=A[6]*B[2]+A[7]*B[5]+A[8]*B[8]; 17458+} 17459+/*! 17460+ * Multiplication: C(4x1)=A(4x4)*B(4x1). 17461+ */ 17462+inline void db_Multiply4x4_4x1(double y[4],const double A[16],const double x[4]) 17463+{ 17464+ y[0]=A[0]*x[0]+A[1]*x[1]+A[2]*x[2]+A[3]*x[3]; 17465+ y[1]=A[4]*x[0]+A[5]*x[1]+A[6]*x[2]+A[7]*x[3]; 17466+ y[2]=A[8]*x[0]+A[9]*x[1]+A[10]*x[2]+A[11]*x[3]; 17467+ y[3]=A[12]*x[0]+A[13]*x[1]+A[14]*x[2]+A[15]*x[3]; 17468+} 17469+/*! 17470+ * Scalar multiplication in place: A(3)=mult*A(3). 17471+ */ 17472+inline void db_MultiplyScalar3(double *A,double mult) 17473+{ 17474+ (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; 17475+} 17476+ 17477+/*! 17478+ * Scalar multiplication: A(3)=mult*B(3). 17479+ */ 17480+inline void db_MultiplyScalarCopy3(double *A,const double *B,double mult) 17481+{ 17482+ (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; 17483+} 17484+ 17485+/*! 17486+ * Scalar multiplication: A(4)=mult*B(4). 17487+ */ 17488+inline void db_MultiplyScalarCopy4(double *A,const double *B,double mult) 17489+{ 17490+ (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; 17491+} 17492+/*! 17493+ * Scalar multiplication: A(7)=mult*B(7). 17494+ */ 17495+inline void db_MultiplyScalarCopy7(double *A,const double *B,double mult) 17496+{ 17497+ (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; 17498+ (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; 17499+} 17500+/*! 17501+ * Scalar multiplication: A(9)=mult*B(9). 17502+ */ 17503+inline void db_MultiplyScalarCopy9(double *A,const double *B,double mult) 17504+{ 17505+ (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; 17506+ (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; 17507+} 17508+ 17509+/*! 17510+ * \defgroup LMImageBasicUtilities (LM) Basic Image Utility Functions 17511+ 17512+ Images in db are simply 2D arrays of unsigned char or float types. 17513+ Only the very basic operations are supported: allocation/deallocation, 17514+copying, simple pyramid construction and LUT warping. These images are used 17515+by db_CornerDetector_u and db_Matcher_u. The db_Image class is an attempt 17516+to wrap these images. It has not been tested well. 17517+ 17518+ */ 17519+/*\{*/ 17520+/*! 17521+ * Given a float image array, allocates and returns the set of row poiners. 17522+ * \param im image pointer 17523+ * \param w image width 17524+ * \param h image height 17525+ */ 17526+DB_API float** db_SetupImageReferences_f(float *im,int w,int h); 17527+/*! 17528+ * Allocate a float image. 17529+ * Note: for feature detection images must be overallocated by 256 bytes. 17530+ * \param w width 17531+ * \param h height 17532+ * \param over_allocation allocate this many extra bytes at the end 17533+ * \return row array pointer 17534+ */ 17535+DB_API float** db_AllocImage_f(int w,int h,int over_allocation=256); 17536+/*! 17537+ * Free a float image 17538+ * \param img row array pointer 17539+ * \param h image height (number of rows) 17540+ */ 17541+DB_API void db_FreeImage_f(float **img,int h); 17542+/*! 17543+ * Given an unsigned char image array, allocates and returns the set of row poiners. 17544+ * \param im image pointer 17545+ * \param w image width 17546+ * \param h image height 17547+ */ 17548+DB_API unsigned char** db_SetupImageReferences_u(unsigned char *im,int w,int h); 17549+/*! 17550+ * Allocate an unsigned char image. 17551+ * Note: for feature detection images must be overallocated by 256 bytes. 17552+ * \param w width 17553+ * \param h height 17554+ * \param over_allocation allocate this many extra bytes at the end 17555+ * \return row array pointer 17556+ */ 17557+DB_API unsigned char** db_AllocImage_u(int w,int h,int over_allocation=256); 17558+/*! 17559+ * Free an unsigned char image 17560+ * \param img row array pointer 17561+ * \param h image height (number of rows) 17562+ */ 17563+DB_API void db_FreeImage_u(unsigned char **img,int h); 17564+ 17565+/*! 17566+ Copy an image from s to d. Both s and d must be pre-allocated at of the same size. 17567+ Copy is done row by row. 17568+ \param s source 17569+ \param d destination 17570+ \param w width 17571+ \param h height 17572+ \param over_allocation copy this many bytes after the end of the last line 17573+ */ 17574+DB_API void db_CopyImage_u(unsigned char **d,const unsigned char * const *s,int w,int h,int over_allocation=0); 17575+ 17576+DB_API inline unsigned char db_BilinearInterpolation(double y, double x, const unsigned char * const * v) 17577+{ 17578+ int floor_x=(int) x; 17579+ int floor_y=(int) y; 17580+ 17581+ int ceil_x=floor_x+1; 17582+ int ceil_y=floor_y+1; 17583+ 17584+ unsigned char f00 = v[floor_y][floor_x]; 17585+ unsigned char f01 = v[floor_y][ceil_x]; 17586+ unsigned char f10 = v[ceil_y][floor_x]; 17587+ unsigned char f11 = v[ceil_y][ceil_x]; 17588+ 17589+ double xl = x-floor_x; 17590+ double yl = y-floor_y; 17591+ 17592+ return (unsigned char)(f00*(1-yl)*(1-xl) + f10*yl*(1-xl) + f01*(1-yl)*xl + f11*yl*xl); 17593+} 17594+/*\}*/ 17595+/*! 17596+ * \ingroup LMRotation 17597+ * Compute an incremental rotation matrix using the update dx=[sin(phi) sin(ohm) sin(kap)] 17598+ */ 17599+inline void db_IncrementalRotationMatrix(double R[9],const double dx[3]) 17600+{ 17601+ double sp,so,sk,om_sp2,om_so2,om_sk2,cp,co,ck,sp_so,cp_so; 17602+ 17603+ /*Store sines*/ 17604+ sp=dx[0]; so=dx[1]; sk=dx[2]; 17605+ om_sp2=1.0-sp*sp; 17606+ om_so2=1.0-so*so; 17607+ om_sk2=1.0-sk*sk; 17608+ /*Compute cosines*/ 17609+ cp=(om_sp2>=0.0)?sqrt(om_sp2):1.0; 17610+ co=(om_so2>=0.0)?sqrt(om_so2):1.0; 17611+ ck=(om_sk2>=0.0)?sqrt(om_sk2):1.0; 17612+ /*Compute matrix*/ 17613+ sp_so=sp*so; 17614+ cp_so=cp*so; 17615+ R[0]=sp_so*sk+cp*ck; R[1]=co*sk; R[2]=cp_so*sk-sp*ck; 17616+ R[3]=sp_so*ck-cp*sk; R[4]=co*ck; R[5]=cp_so*ck+sp*sk; 17617+ R[6]=sp*co; R[7]= -so; R[8]=cp*co; 17618+} 17619+/*! 17620+ * Zero out 2 vector in place. 17621+ */ 17622+void inline db_Zero2(double x[2]) 17623+{ 17624+ x[0]=x[1]=0; 17625+} 17626+/*! 17627+ * Zero out 3 vector in place. 17628+ */ 17629+void inline db_Zero3(double x[3]) 17630+{ 17631+ x[0]=x[1]=x[2]=0; 17632+} 17633+/*! 17634+ * Zero out 4 vector in place. 17635+ */ 17636+void inline db_Zero4(double x[4]) 17637+{ 17638+ x[0]=x[1]=x[2]=x[3]=0; 17639+} 17640+/*! 17641+ * Zero out 9 vector in place. 17642+ */ 17643+void inline db_Zero9(double x[9]) 17644+{ 17645+ x[0]=x[1]=x[2]=x[3]=x[4]=x[5]=x[6]=x[7]=x[8]=0; 17646+} 17647+ 17648+#define DB_WARP_FAST 0 17649+#define DB_WARP_BILINEAR 1 17650+ 17651+/*! 17652+ * Perform a look-up table warp. 17653+ * The LUTs must be float images of the same size as source image. 17654+ * The source value x_s is determined from destination (x_d,y_d) through lut_x 17655+ * and y_s is determined from lut_y: 17656+ \code 17657+ x_s = lut_x[y_d][x_d]; 17658+ y_s = lut_y[y_d][x_d]; 17659+ \endcode 17660+ 17661+ * \param src source image 17662+ * \param dst destination image 17663+ * \param w width 17664+ * \param h height 17665+ * \param lut_x LUT for x 17666+ * \param lut_y LUT for y 17667+ * \param type warp type (DB_WARP_FAST or DB_WARP_BILINEAR) 17668+ */ 17669+DB_API void db_WarpImageLut_u(const unsigned char * const * src,unsigned char ** dst, int w, int h, 17670+ const float * const * lut_x, const float * const * lut_y, int type=DB_WARP_BILINEAR); 17671+ 17672+DB_API void db_PrintDoubleVector(double *a,long size); 17673+DB_API void db_PrintDoubleMatrix(double *a,long rows,long cols); 17674+ 17675+#include "db_utilities_constants.h" 17676+#include "db_utilities_algebra.h" 17677+#include "db_utilities_indexing.h" 17678+#include "db_utilities_linalg.h" 17679+#include "db_utilities_poly.h" 17680+#include "db_utilities_geometry.h" 17681+#include "db_utilities_random.h" 17682+#include "db_utilities_rotation.h" 17683+#include "db_utilities_camera.h" 17684+ 17685+#define DB_INVALID (-1) 17686+ 17687+ 17688+#endif /* DB_UTILITIES_H */ 17689diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_algebra.h b/benchmark/feature_stab/db_vlvm/db_utilities_algebra.h 17690new file mode 100644 17691index 00000000..2aedd74d 17692--- /dev/null 17693+++ b/benchmark/feature_stab/db_vlvm/db_utilities_algebra.h 17694@@ -0,0 +1,41 @@ 17695+/* 17696+ * Copyright (C) 2011 The Android Open Source Project 17697+ * 17698+ * Licensed under the Apache License, Version 2.0 (the "License"); 17699+ * you may not use this file except in compliance with the License. 17700+ * You may obtain a copy of the License at 17701+ * 17702+ * http://www.apache.org/licenses/LICENSE-2.0 17703+ * 17704+ * Unless required by applicable law or agreed to in writing, software 17705+ * distributed under the License is distributed on an "AS IS" BASIS, 17706+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17707+ * See the License for the specific language governing permissions and 17708+ * limitations under the License. 17709+ */ 17710+ 17711+/* $Id: db_utilities_algebra.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */ 17712+ 17713+#ifndef DB_UTILITIES_ALGEBRA 17714+#define DB_UTILITIES_ALGEBRA 17715+ 17716+#include "db_utilities.h" 17717+ 17718+ 17719+ 17720+/***************************************************************** 17721+* Lean and mean begins here * 17722+*****************************************************************/ 17723+/*! 17724+ * \defgroup LMAlgebra (LM) Algebra utilities 17725+ */ 17726+/*\{*/ 17727+ 17728+inline void db_HomogenousNormalize3(double *x) 17729+{ 17730+ db_MultiplyScalar3(x,db_SafeSqrtReciprocal(db_SquareSum3(x))); 17731+} 17732+ 17733+/*\}*/ 17734+ 17735+#endif /* DB_UTILITIES_ALGEBRA */ 17736diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_camera.cpp b/benchmark/feature_stab/db_vlvm/db_utilities_camera.cpp 17737new file mode 100644 17738index 00000000..dceba9b6 17739--- /dev/null 17740+++ b/benchmark/feature_stab/db_vlvm/db_utilities_camera.cpp 17741@@ -0,0 +1,50 @@ 17742+/* 17743+ * Copyright (C) 2011 The Android Open Source Project 17744+ * 17745+ * Licensed under the Apache License, Version 2.0 (the "License"); 17746+ * you may not use this file except in compliance with the License. 17747+ * You may obtain a copy of the License at 17748+ * 17749+ * http://www.apache.org/licenses/LICENSE-2.0 17750+ * 17751+ * Unless required by applicable law or agreed to in writing, software 17752+ * distributed under the License is distributed on an "AS IS" BASIS, 17753+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17754+ * See the License for the specific language governing permissions and 17755+ * limitations under the License. 17756+ */ 17757+ 17758+/* $Id: db_utilities_camera.cpp,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */ 17759+ 17760+#include "db_utilities_camera.h" 17761+#include "db_utilities.h" 17762+#include <assert.h> 17763+ 17764+ 17765+ 17766+/***************************************************************** 17767+* Lean and mean begins here * 17768+*****************************************************************/ 17769+ 17770+void db_Approx3DCalMat(double K[9],double Kinv[9],int im_width,int im_height,double f_correction,int field) 17771+{ 17772+ double iw,ih,av_size,field_fact; 17773+ 17774+ if(field) field_fact=2.0; 17775+ else field_fact=1.0; 17776+ 17777+ iw=(double)im_width; 17778+ ih=(double)(im_height*field_fact); 17779+ av_size=(iw+ih)/2.0; 17780+ K[0]=f_correction*av_size; 17781+ K[1]=0; 17782+ K[2]=iw/2.0; 17783+ K[3]=0; 17784+ K[4]=f_correction*av_size/field_fact; 17785+ K[5]=ih/2.0/field_fact; 17786+ K[6]=0; 17787+ K[7]=0; 17788+ K[8]=1; 17789+ 17790+ db_InvertCalibrationMatrix(Kinv,K); 17791+} 17792diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_camera.h b/benchmark/feature_stab/db_vlvm/db_utilities_camera.h 17793new file mode 100644 17794index 00000000..26ba4420 17795--- /dev/null 17796+++ b/benchmark/feature_stab/db_vlvm/db_utilities_camera.h 17797@@ -0,0 +1,332 @@ 17798+/* 17799+ * Copyright (C) 2011 The Android Open Source Project 17800+ * 17801+ * Licensed under the Apache License, Version 2.0 (the "License"); 17802+ * you may not use this file except in compliance with the License. 17803+ * You may obtain a copy of the License at 17804+ * 17805+ * http://www.apache.org/licenses/LICENSE-2.0 17806+ * 17807+ * Unless required by applicable law or agreed to in writing, software 17808+ * distributed under the License is distributed on an "AS IS" BASIS, 17809+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17810+ * See the License for the specific language governing permissions and 17811+ * limitations under the License. 17812+ */ 17813+ 17814+/* $Id: db_utilities_camera.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */ 17815+ 17816+#ifndef DB_UTILITIES_CAMERA 17817+#define DB_UTILITIES_CAMERA 17818+ 17819+#include "db_utilities.h" 17820+ 17821+ 17822+ 17823+/***************************************************************** 17824+* Lean and mean begins here * 17825+*****************************************************************/ 17826+/*! 17827+ * \defgroup LMCamera (LM) Camera Utilities 17828+ */ 17829+/*\{*/ 17830+ 17831+#include "db_utilities.h" 17832+ 17833+#define DB_RADDISTMODE_BOUGEUT 4 17834+#define DB_RADDISTMODE_2NDORDER 5 17835+#define DB_RADDISTMODE_IDENTITY 6 17836+ 17837+/*! 17838+Give reasonable guess of the calibration matrix for normalization purposes. 17839+Use real K matrix when doing real geometry. 17840+focal length = (w+h)/2.0*f_correction. 17841+\param K calibration matrix (out) 17842+\param Kinv inverse of K (out) 17843+\param im_width image width 17844+\param im_height image height 17845+\param f_correction focal length correction factor 17846+\param field set to 1 if this is a field image (fy = fx/2) 17847+\return K(3x3) intrinsic calibration matrix 17848+*/ 17849+DB_API void db_Approx3DCalMat(double K[9],double Kinv[9],int im_width,int im_height,double f_correction=1.0,int field=0); 17850+ 17851+/*! 17852+ Make a 2x2 identity matrix 17853+ */ 17854+void inline db_Identity2x2(double A[4]) 17855+{ 17856+ A[0]=1;A[1]=0; 17857+ A[2]=0;A[3]=1; 17858+} 17859+/*! 17860+ Make a 3x3 identity matrix 17861+ */ 17862+void inline db_Identity3x3(double A[9]) 17863+{ 17864+ A[0]=1;A[1]=0;A[2]=0; 17865+ A[3]=0;A[4]=1;A[5]=0; 17866+ A[6]=0;A[7]=0;A[8]=1; 17867+} 17868+/*! 17869+ Invert intrinsic calibration matrix K(3x3) 17870+ If fx or fy is 0, I is returned. 17871+ */ 17872+void inline db_InvertCalibrationMatrix(double Kinv[9],const double K[9]) 17873+{ 17874+ double a,b,c,d,e,f,ainv,dinv,adinv; 17875+ 17876+ a=K[0];b=K[1];c=K[2];d=K[4];e=K[5];f=K[8]; 17877+ if((a==0.0)||(d==0.0)) db_Identity3x3(Kinv); 17878+ else 17879+ { 17880+ Kinv[3]=0.0; 17881+ Kinv[6]=0.0; 17882+ Kinv[7]=0.0; 17883+ Kinv[8]=1.0; 17884+ 17885+ ainv=1.0/a; 17886+ dinv=1.0/d; 17887+ adinv=ainv*dinv; 17888+ Kinv[0]=f*ainv; 17889+ Kinv[1]= -b*f*adinv; 17890+ Kinv[2]=(b*e-c*d)*adinv; 17891+ Kinv[4]=f*dinv; 17892+ Kinv[5]= -e*dinv; 17893+ } 17894+} 17895+/*! 17896+ De-homogenize image point: xd(1:2) = xs(1:2)/xs(3). 17897+ If xs(3) is 0, xd will become 0 17898+ \param xd destination point 17899+ \param xs source point 17900+ */ 17901+void inline db_DeHomogenizeImagePoint(double xd[2],const double xs[3]) 17902+{ 17903+ double temp,div; 17904+ 17905+ temp=xs[2]; 17906+ if(temp!=0) 17907+ { 17908+ div=1.0/temp; 17909+ xd[0]=xs[0]*div;xd[1]=xs[1]*div; 17910+ } 17911+ else 17912+ { 17913+ xd[0]=0.0;xd[1]=0.0; 17914+ } 17915+} 17916+ 17917+ 17918+/*! 17919+ Orthonormalize 3D rotation R 17920+ */ 17921+inline void db_OrthonormalizeRotation(double R[9]) 17922+{ 17923+ double s,mult; 17924+ /*Normalize first vector*/ 17925+ s=db_sqr(R[0])+db_sqr(R[1])+db_sqr(R[2]); 17926+ mult=sqrt(1.0/(s?s:1)); 17927+ R[0]*=mult; R[1]*=mult; R[2]*=mult; 17928+ /*Subtract scalar product from second vector*/ 17929+ s=R[0]*R[3]+R[1]*R[4]+R[2]*R[5]; 17930+ R[3]-=s*R[0]; R[4]-=s*R[1]; R[5]-=s*R[2]; 17931+ /*Normalize second vector*/ 17932+ s=db_sqr(R[3])+db_sqr(R[4])+db_sqr(R[5]); 17933+ mult=sqrt(1.0/(s?s:1)); 17934+ R[3]*=mult; R[4]*=mult; R[5]*=mult; 17935+ /*Get third vector by vector product*/ 17936+ R[6]=R[1]*R[5]-R[4]*R[2]; 17937+ R[7]=R[2]*R[3]-R[5]*R[0]; 17938+ R[8]=R[0]*R[4]-R[3]*R[1]; 17939+} 17940+/*! 17941+Update a rotation with the update dx=[sin(phi) sin(ohm) sin(kap)] 17942+*/ 17943+inline void db_UpdateRotation(double R_p_dx[9],double R[9],const double dx[3]) 17944+{ 17945+ double R_temp[9]; 17946+ /*Update rotation*/ 17947+ db_IncrementalRotationMatrix(R_temp,dx); 17948+ db_Multiply3x3_3x3(R_p_dx,R_temp,R); 17949+} 17950+/*! 17951+ Compute xp = Hx for inhomogenous image points. 17952+ */ 17953+inline void db_ImageHomographyInhomogenous(double xp[2],const double H[9],const double x[2]) 17954+{ 17955+ double x3,m; 17956+ 17957+ x3=H[6]*x[0]+H[7]*x[1]+H[8]; 17958+ if(x3!=0.0) 17959+ { 17960+ m=1.0/x3; 17961+ xp[0]=m*(H[0]*x[0]+H[1]*x[1]+H[2]); 17962+ xp[1]=m*(H[3]*x[0]+H[4]*x[1]+H[5]); 17963+ } 17964+ else 17965+ { 17966+ xp[0]=xp[1]=0.0; 17967+ } 17968+} 17969+inline double db_FocalFromCamRotFocalHomography(const double H[9]) 17970+{ 17971+ double k1,k2; 17972+ 17973+ k1=db_sqr(H[2])+db_sqr(H[5]); 17974+ k2=db_sqr(H[6])+db_sqr(H[7]); 17975+ if(k1>=k2) 17976+ { 17977+ return(db_SafeSqrt(db_SafeDivision(k1,1.0-db_sqr(H[8])))); 17978+ } 17979+ else 17980+ { 17981+ return(db_SafeSqrt(db_SafeDivision(1.0-db_sqr(H[8]),k2))); 17982+ } 17983+} 17984+ 17985+inline double db_FocalAndRotFromCamRotFocalHomography(double R[9],const double H[9]) 17986+{ 17987+ double back,fi; 17988+ 17989+ back=db_FocalFromCamRotFocalHomography(H); 17990+ fi=db_SafeReciprocal(back); 17991+ R[0]=H[0]; R[1]=H[1]; R[2]=fi*H[2]; 17992+ R[3]=H[3]; R[4]=H[4]; R[5]=fi*H[5]; 17993+ R[6]=back*H[6]; R[7]=back*H[7]; R[8]=H[8]; 17994+ return(back); 17995+} 17996+/*! 17997+Compute Jacobian at zero of three coordinates dR*x with 17998+respect to the update dR([sin(phi) sin(ohm) sin(kap)]) given x. 17999+ 18000+The Jacobian at zero of the homogenous coordinates with respect to 18001+ [sin(phi) sin(ohm) sin(kap)] is 18002+\code 18003+ [-rx2 0 rx1 ] 18004+ [ 0 rx2 -rx0 ] 18005+ [ rx0 -rx1 0 ]. 18006+\endcode 18007+ 18008+*/ 18009+inline void db_JacobianOfRotatedPointStride(double J[9],const double x[3],int stride) 18010+{ 18011+ /*The Jacobian at zero of the homogenous coordinates with respect to 18012+ [sin(phi) sin(ohm) sin(kap)] is 18013+ [-rx2 0 rx1 ] 18014+ [ 0 rx2 -rx0 ] 18015+ [ rx0 -rx1 0 ]*/ 18016+ 18017+ J[0]= -x[stride<<1]; 18018+ J[1]=0; 18019+ J[2]= x[stride]; 18020+ J[3]=0; 18021+ J[4]= x[stride<<1]; 18022+ J[5]= -x[0]; 18023+ J[6]= x[0]; 18024+ J[7]= -x[stride]; 18025+ J[8]=0; 18026+} 18027+/*! 18028+ Invert an affine (if possible) 18029+ \param Hinv inverted matrix 18030+ \param H input matrix 18031+ \return true if success and false if matrix is ill-conditioned (det < 1e-7) 18032+ */ 18033+inline bool db_InvertAffineTransform(double Hinv[9],const double H[9]) 18034+{ 18035+ double det=H[0]*H[4]-H[3]*H[1]; 18036+ if (det<1e-7) 18037+ { 18038+ db_Copy9(Hinv,H); 18039+ return false; 18040+ } 18041+ else 18042+ { 18043+ Hinv[0]=H[4]/det; 18044+ Hinv[1]=-H[1]/det; 18045+ Hinv[3]=-H[3]/det; 18046+ Hinv[4]=H[0]/det; 18047+ Hinv[2]= -Hinv[0]*H[2]-Hinv[1]*H[5]; 18048+ Hinv[5]= -Hinv[3]*H[2]-Hinv[4]*H[5]; 18049+ } 18050+ return true; 18051+} 18052+ 18053+/*! 18054+Update of upper 2x2 is multiplication by 18055+\code 18056+[s 0][ cos(theta) sin(theta)] 18057+[0 s][-sin(theta) cos(theta)] 18058+\endcode 18059+*/ 18060+inline void db_MultiplyScaleOntoImageHomography(double H[9],double s) 18061+{ 18062+ 18063+ H[0]*=s; 18064+ H[1]*=s; 18065+ H[3]*=s; 18066+ H[4]*=s; 18067+} 18068+/*! 18069+Update of upper 2x2 is multiplication by 18070+\code 18071+[s 0][ cos(theta) sin(theta)] 18072+[0 s][-sin(theta) cos(theta)] 18073+\endcode 18074+*/ 18075+inline void db_MultiplyRotationOntoImageHomography(double H[9],double theta) 18076+{ 18077+ double c,s,H0,H1; 18078+ 18079+ 18080+ c=cos(theta); 18081+ s=db_SafeSqrt(1.0-db_sqr(c)); 18082+ H0= c*H[0]+s*H[3]; 18083+ H[3]= -s*H[0]+c*H[3]; 18084+ H[0]=H0; 18085+ H1=c*H[1]+s*H[4]; 18086+ H[4]= -s*H[1]+c*H[4]; 18087+ H[1]=H1; 18088+} 18089+ 18090+inline void db_UpdateImageHomographyAffine(double H_p_dx[9],const double H[9],const double dx[6]) 18091+{ 18092+ db_AddVectors6(H_p_dx,H,dx); 18093+ db_Copy3(H_p_dx+6,H+6); 18094+} 18095+ 18096+inline void db_UpdateImageHomographyProjective(double H_p_dx[9],const double H[9],const double dx[8],int frozen_coord) 18097+{ 18098+ int i,j; 18099+ 18100+ for(j=0,i=0;i<9;i++) 18101+ { 18102+ if(i!=frozen_coord) 18103+ { 18104+ H_p_dx[i]=H[i]+dx[j]; 18105+ j++; 18106+ } 18107+ else H_p_dx[i]=H[i]; 18108+ } 18109+} 18110+ 18111+inline void db_UpdateRotFocalHomography(double H_p_dx[9],const double H[9],const double dx[4]) 18112+{ 18113+ double f,fp,fpi; 18114+ double R[9],dR[9]; 18115+ 18116+ /*Updated matrix is diag(f+df,f+df)*dR*R*diag(1/(f+df),1/(f+df),1)*/ 18117+ f=db_FocalAndRotFromCamRotFocalHomography(R,H); 18118+ db_IncrementalRotationMatrix(dR,dx); 18119+ db_Multiply3x3_3x3(H_p_dx,dR,R); 18120+ fp=f+dx[3]; 18121+ fpi=db_SafeReciprocal(fp); 18122+ H_p_dx[2]*=fp; 18123+ H_p_dx[5]*=fp; 18124+ H_p_dx[6]*=fpi; 18125+ H_p_dx[7]*=fpi; 18126+} 18127+ 18128+/*\}*/ 18129+#endif /* DB_UTILITIES_CAMERA */ 18130diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_constants.h b/benchmark/feature_stab/db_vlvm/db_utilities_constants.h 18131new file mode 100644 18132index 00000000..07565efd 18133--- /dev/null 18134+++ b/benchmark/feature_stab/db_vlvm/db_utilities_constants.h 18135@@ -0,0 +1,208 @@ 18136+/* 18137+ * Copyright (C) 2011 The Android Open Source Project 18138+ * 18139+ * Licensed under the Apache License, Version 2.0 (the "License"); 18140+ * you may not use this file except in compliance with the License. 18141+ * You may obtain a copy of the License at 18142+ * 18143+ * http://www.apache.org/licenses/LICENSE-2.0 18144+ * 18145+ * Unless required by applicable law or agreed to in writing, software 18146+ * distributed under the License is distributed on an "AS IS" BASIS, 18147+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18148+ * See the License for the specific language governing permissions and 18149+ * limitations under the License. 18150+ */ 18151+ 18152+/* $Id: db_utilities_constants.h,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */ 18153+ 18154+#ifndef DB_UTILITIES_CONSTANTS 18155+#define DB_UTILITIES_CONSTANTS 18156+ 18157+/***************************************************************** 18158+* Lean and mean begins here * 18159+*****************************************************************/ 18160+ 18161+/****************Constants********************/ 18162+#define DB_E 2.7182818284590452354 18163+#define DB_LOG2E 1.4426950408889634074 18164+#define DB_LOG10E 0.43429448190325182765 18165+#define DB_LN2 0.69314718055994530942 18166+#define DB_LN10 2.30258509299404568402 18167+#define DB_PI 3.1415926535897932384626433832795 18168+#define DB_PI_2 1.57079632679489661923 18169+#define DB_PI_4 0.78539816339744830962 18170+#define DB_1_PI 0.31830988618379067154 18171+#define DB_2_PI 0.63661977236758134308 18172+#define DB_SQRTPI 1.7724538509055160272981674833411 18173+#define DB_SQRT_2PI 2.506628274631000502415765284811 18174+#define DB_2_SQRTPI 1.12837916709551257390 18175+#define DB_SQRT2 1.41421356237309504880 18176+#define DB_SQRT3 1.7320508075688772935274463415059 18177+#define DB_SQRT1_2 0.70710678118654752440 18178+#define DB_EPS 2.220446049250313e-016 /* for 32 bit double */ 18179+ 18180+/****************Default Parameters********************/ 18181+/*Preemptive ransac parameters*/ 18182+#define DB_DEFAULT_NR_SAMPLES 500 18183+#define DB_DEFAULT_CHUNK_SIZE 100 18184+#define DB_DEFAULT_GROUP_SIZE 10 18185+ 18186+/*Optimisation parameters*/ 18187+#define DB_DEFAULT_MAX_POINTS 1000 18188+#define DB_DEFAULT_MAX_ITERATIONS 25 18189+#define DB_DEFAULT_IMP_REQ 0.001 18190+ 18191+/*Feature standard deviation parameters*/ 18192+#define DB_POINT_STANDARDDEV (1.0/(826.0)) /*1 pixel for CIF (fraction of (image width+image height)/2)*/ 18193+#define DB_OUTLIER_THRESHOLD 3.0 /*In number of DB_POINT_STANDARDDEV's*/ 18194+#define DB_WORST_CASE 50.0 /*In number of DB_POINT_STANDARDDEV's*/ 18195+ 18196+/*Front-end parameters*/ 18197+#define DB_DEFAULT_TARGET_NR_CORNERS 5000 18198+#define DB_DEFAULT_NR_FEATURE_BLOCKS 10 18199+#define DB_DEFAULT_ABS_CORNER_THRESHOLD 50000000.0 18200+#define DB_DEFAULT_REL_CORNER_THRESHOLD 0.00005 18201+#define DB_DEFAULT_MAX_DISPARITY 0.1 18202+#define DB_DEFAULT_NO_DISPARITY -1.0 18203+#define DB_DEFAULT_MAX_TRACK_LENGTH 300 18204+ 18205+#define DB_DEFAULT_MAX_NR_CAMERAS 1000 18206+ 18207+#define DB_DEFAULT_TRIPLE_STEP 2 18208+#define DB_DEFAULT_DOUBLE_STEP 2 18209+#define DB_DEFAULT_SINGLE_STEP 1 18210+#define DB_DEFAULT_NR_SINGLES 10 18211+#define DB_DEFAULT_NR_DOUBLES 1 18212+#define DB_DEFAULT_NR_TRIPLES 1 18213+ 18214+#define DB_DEFAULT_TRIFOCAL_FOUR_STEPS 40 18215+ 18216+#define DB_DEFAULT_EPIPOLAR_ERROR 1 /*in pixels*/ 18217+ 18218+////////////////////////// DOXYGEN ///////////////////// 18219+ 18220+/*! 18221+ * \def DB_DEFAULT_GROUP_SIZE 18222+ * \ingroup LMRobust 18223+ * \brief Default group size for db_PreemptiveRansac class. 18224+ * Group size is the number of observation costs multiplied together 18225+ * before a log of the product is added to the total cost. 18226+*/ 18227+ 18228+/*! 18229+ * \def DB_DEFAULT_TARGET_NR_CORNERS 18230+ * \ingroup FeatureDetection 18231+ * \brief Default target number of corners 18232+*/ 18233+/*! 18234+ * \def DB_DEFAULT_NR_FEATURE_BLOCKS 18235+ * \ingroup FeatureDetection 18236+ * \brief Default number of regions (horizontal or vertical) that are considered separately 18237+ * for feature detection. The greater the number, the more uniform the distribution of 18238+ * detected features. 18239+*/ 18240+/*! 18241+ * \def DB_DEFAULT_ABS_CORNER_THRESHOLD 18242+ * \ingroup FeatureDetection 18243+ * \brief Absolute feature strength threshold. 18244+*/ 18245+/*! 18246+ * \def DB_DEFAULT_REL_CORNER_THRESHOLD 18247+ * \ingroup FeatureDetection 18248+ * \brief Relative feature strength threshold. 18249+*/ 18250+/*! 18251+ * \def DB_DEFAULT_MAX_DISPARITY 18252+ * \ingroup FeatureMatching 18253+ * \brief Maximum disparity (as fraction of image size) allowed in feature matching 18254+*/ 18255+ /*! 18256+ * \def DB_DEFAULT_NO_DISPARITY 18257+ * \ingroup FeatureMatching 18258+ * \brief Indicates that vertical disparity is the same as horizontal disparity. 18259+*/ 18260+/////////////////////////////////////////////////////////////////////////////////// 18261+ /*! 18262+ * \def DB_E 18263+ * \ingroup LMBasicUtilities 18264+ * \brief e 18265+*/ 18266+ /*! 18267+ * \def DB_LOG2E 18268+ * \ingroup LMBasicUtilities 18269+ * \brief log2(e) 18270+*/ 18271+ /*! 18272+ * \def DB_LOG10E 18273+ * \ingroup LMBasicUtilities 18274+ * \brief log10(e) 18275+*/ 18276+ /*! 18277+ * \def DB_LOG10E 18278+ * \ingroup LMBasicUtilities 18279+ * \brief log10(e) 18280+*/ 18281+/*! 18282+ * \def DB_LN2 18283+ * \ingroup LMBasicUtilities 18284+ * \brief ln(2) 18285+*/ 18286+/*! 18287+ * \def DB_LN10 18288+ * \ingroup LMBasicUtilities 18289+ * \brief ln(10) 18290+*/ 18291+/*! 18292+ * \def DB_PI 18293+ * \ingroup LMBasicUtilities 18294+ * \brief Pi 18295+*/ 18296+/*! 18297+ * \def DB_PI_2 18298+ * \ingroup LMBasicUtilities 18299+ * \brief Pi/2 18300+*/ 18301+/*! 18302+ * \def DB_PI_4 18303+ * \ingroup LMBasicUtilities 18304+ * \brief Pi/4 18305+*/ 18306+/*! 18307+ * \def DB_1_PI 18308+ * \ingroup LMBasicUtilities 18309+ * \brief 1/Pi 18310+*/ 18311+/*! 18312+ * \def DB_2_PI 18313+ * \ingroup LMBasicUtilities 18314+ * \brief 2/Pi 18315+*/ 18316+/*! 18317+ * \def DB_SQRTPI 18318+ * \ingroup LMBasicUtilities 18319+ * \brief sqrt(Pi) 18320+*/ 18321+/*! 18322+ * \def DB_SQRT_2PI 18323+ * \ingroup LMBasicUtilities 18324+ * \brief sqrt(2*Pi) 18325+*/ 18326+/*! 18327+ * \def DB_SQRT2 18328+ * \ingroup LMBasicUtilities 18329+ * \brief sqrt(2) 18330+*/ 18331+/*! 18332+ * \def DB_SQRT3 18333+ * \ingroup LMBasicUtilities 18334+ * \brief sqrt(3) 18335+*/ 18336+/*! 18337+ * \def DB_SQRT1_2 18338+ * \ingroup LMBasicUtilities 18339+ * \brief sqrt(1/2) 18340+*/ 18341+#endif /* DB_UTILITIES_CONSTANTS */ 18342+ 18343+ 18344diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_geometry.h b/benchmark/feature_stab/db_vlvm/db_utilities_geometry.h 18345new file mode 100644 18346index 00000000..f2155846 18347--- /dev/null 18348+++ b/benchmark/feature_stab/db_vlvm/db_utilities_geometry.h 18349@@ -0,0 +1,121 @@ 18350+/* 18351+ * Copyright (C) 2011 The Android Open Source Project 18352+ * 18353+ * Licensed under the Apache License, Version 2.0 (the "License"); 18354+ * you may not use this file except in compliance with the License. 18355+ * You may obtain a copy of the License at 18356+ * 18357+ * http://www.apache.org/licenses/LICENSE-2.0 18358+ * 18359+ * Unless required by applicable law or agreed to in writing, software 18360+ * distributed under the License is distributed on an "AS IS" BASIS, 18361+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18362+ * See the License for the specific language governing permissions and 18363+ * limitations under the License. 18364+ */ 18365+ 18366+/* $Id: db_utilities_geometry.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */ 18367+ 18368+#ifndef DB_UTILITIES_GEOMETRY_H 18369+#define DB_UTILITIES_GEOMETRY_H 18370+ 18371+#include "db_utilities.h" 18372+ 18373+ 18374+ 18375+/***************************************************************** 18376+* Lean and mean begins here * 18377+*****************************************************************/ 18378+/*! Get the inhomogenous 2D-point centroid of nr_point inhomogenous 18379+points in X*/ 18380+inline void db_PointCentroid2D(double c[2],const double *X,int nr_points) 18381+{ 18382+ int i; 18383+ double cx,cy,m; 18384+ 18385+ cx=0;cy=0; 18386+ for(i=0;i<nr_points;i++) 18387+ { 18388+ cx+= *X++; 18389+ cy+= *X++; 18390+ } 18391+ if(nr_points) 18392+ { 18393+ m=1.0/((double)nr_points); 18394+ c[0]=cx*m; 18395+ c[1]=cy*m; 18396+ } 18397+ else c[0]=c[1]=0; 18398+} 18399+ 18400+inline void db_PointCentroid2D(double c[2],const double * const *X,int nr_points) 18401+{ 18402+ int i; 18403+ double cx,cy,m; 18404+ const double *temp; 18405+ 18406+ cx=0;cy=0; 18407+ for(i=0;i<nr_points;i++) 18408+ { 18409+ temp= *X++; 18410+ cx+=temp[0]; 18411+ cy+=temp[1]; 18412+ } 18413+ if(nr_points) 18414+ { 18415+ m=1.0/((double)nr_points); 18416+ c[0]=cx*m; 18417+ c[1]=cy*m; 18418+ } 18419+ else c[0]=c[1]=0; 18420+} 18421+ 18422+/*! Get the inhomogenous 3D-point centroid of nr_point inhomogenous 18423+points in X*/ 18424+inline void db_PointCentroid3D(double c[3],const double *X,int nr_points) 18425+{ 18426+ int i; 18427+ double cx,cy,cz,m; 18428+ 18429+ cx=0;cy=0;cz=0; 18430+ for(i=0;i<nr_points;i++) 18431+ { 18432+ cx+= *X++; 18433+ cy+= *X++; 18434+ cz+= *X++; 18435+ } 18436+ if(nr_points) 18437+ { 18438+ m=1.0/((double)nr_points); 18439+ c[0]=cx*m; 18440+ c[1]=cy*m; 18441+ c[2]=cz*m; 18442+ } 18443+ else c[0]=c[1]=c[2]=0; 18444+} 18445+ 18446+inline void db_PointCentroid3D(double c[3],const double * const *X,int nr_points) 18447+{ 18448+ int i; 18449+ double cx,cy,cz,m; 18450+ const double *temp; 18451+ 18452+ cx=0;cy=0;cz=0; 18453+ for(i=0;i<nr_points;i++) 18454+ { 18455+ temp= *X++; 18456+ cx+=temp[0]; 18457+ cy+=temp[1]; 18458+ cz+=temp[2]; 18459+ } 18460+ if(nr_points) 18461+ { 18462+ m=1.0/((double)nr_points); 18463+ c[0]=cx*m; 18464+ c[1]=cy*m; 18465+ c[2]=cz*m; 18466+ } 18467+ else c[0]=c[1]=c[2]=0; 18468+} 18469+ 18470+#endif /* DB_UTILITIES_GEOMETRY_H */ 18471diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_indexing.cpp b/benchmark/feature_stab/db_vlvm/db_utilities_indexing.cpp 18472new file mode 100644 18473index 00000000..30ce03aa 18474--- /dev/null 18475+++ b/benchmark/feature_stab/db_vlvm/db_utilities_indexing.cpp 18476@@ -0,0 +1,120 @@ 18477+/* 18478+ * Copyright (C) 2011 The Android Open Source Project 18479+ * 18480+ * Licensed under the Apache License, Version 2.0 (the "License"); 18481+ * you may not use this file except in compliance with the License. 18482+ * You may obtain a copy of the License at 18483+ * 18484+ * http://www.apache.org/licenses/LICENSE-2.0 18485+ * 18486+ * Unless required by applicable law or agreed to in writing, software 18487+ * distributed under the License is distributed on an "AS IS" BASIS, 18488+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18489+ * See the License for the specific language governing permissions and 18490+ * limitations under the License. 18491+ */ 18492+ 18493+/* $Id: db_utilities_indexing.cpp,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */ 18494+ 18495+#include "db_utilities_indexing.h" 18496+#include "db_utilities.h" 18497+ 18498+ 18499+ 18500+/***************************************************************** 18501+* Lean and mean begins here * 18502+*****************************************************************/ 18503+ 18504+void db_Zero(double *d,long nr) 18505+{ 18506+ long i; 18507+ for(i=0;i<nr;i++) d[i]=0.0; 18508+} 18509+ 18510+/*This routine breaks number in source into values smaller and larger than 18511+a pivot element. Values equal to the pivot are ignored*/ 18512+void db_LeanPartitionOnPivot(double pivot,double *dest,const double *source,long first,long last,long *first_equal,long *last_equal) 18513+{ 18514+ double temp; 18515+ const double *s_point; 18516+ const double *s_top; 18517+ double *d_bottom; 18518+ double *d_top; 18519+ 18520+ s_point=source+first; 18521+ s_top=source+last; 18522+ d_bottom=dest+first; 18523+ d_top=dest+last; 18524+ 18525+ for(;s_point<=s_top;) 18526+ { 18527+ temp= *(s_point++); 18528+ if(temp<pivot) *(d_bottom++)=temp; 18529+ else if(temp>pivot) *(d_top--)=temp; 18530+ } 18531+ *first_equal=d_bottom-dest; 18532+ *last_equal=d_top-dest; 18533+} 18534+ 18535+double db_LeanQuickSelect(const double *s,long nr_elements,long pos,double *temp) 18536+{ 18537+ long first=0; 18538+ long last=nr_elements-1; 18539+ double pivot; 18540+ long first_equal,last_equal; 18541+ double *tempA; 18542+ double *tempB; 18543+ double *tempC; 18544+ const double *source; 18545+ double *dest; 18546+ 18547+ tempA=temp; 18548+ tempB=temp+nr_elements; 18549+ source=s; 18550+ dest=tempA; 18551+ 18552+ for(;last-first>2;) 18553+ { 18554+ pivot=db_TripleMedian(source[first],source[last],source[(first+last)/2]); 18555+ db_LeanPartitionOnPivot(pivot,dest,source,first,last,&first_equal,&last_equal); 18556+ 18557+ if(first_equal>pos) last=first_equal-1; 18558+ else if(last_equal<pos) first=last_equal+1; 18559+ else 18560+ { 18561+ return(pivot); 18562+ } 18563+ 18564+ /*Swap pointers*/ 18565+ tempC=tempA; 18566+ tempA=tempB; 18567+ tempB=tempC; 18568+ source=tempB; 18569+ dest=tempA; 18570+ } 18571+ pivot=db_TripleMedian(source[first],source[last],source[(first+last)/2]); 18572+ 18573+ return(pivot); 18574+} 18575+ 18576+float* db_AlignPointer_f(float *p,unsigned long nr_bytes) 18577+{ 18578+ float *ap; 18579+ unsigned long m; 18580+ 18581+ m=((unsigned long)p)%nr_bytes; 18582+ if(m) ap=(float*) (((unsigned long)p)-m+nr_bytes); 18583+ else ap=p; 18584+ return(ap); 18585+} 18586+ 18587+short* db_AlignPointer_s(short *p,unsigned long nr_bytes) 18588+{ 18589+ short *ap; 18590+ unsigned long m; 18591+ 18592+ m=((unsigned long)p)%nr_bytes; 18593+ if(m) ap=(short*) (((unsigned long)p)-m+nr_bytes); 18594+ else ap=p; 18595+ return(ap); 18596+} 18597diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_indexing.h b/benchmark/feature_stab/db_vlvm/db_utilities_indexing.h 18598new file mode 100644 18599index 00000000..01eeb9ea 18600--- /dev/null 18601+++ b/benchmark/feature_stab/db_vlvm/db_utilities_indexing.h 18602@@ -0,0 +1,270 @@ 18603+/* 18604+ * Copyright (C) 2011 The Android Open Source Project 18605+ * 18606+ * Licensed under the Apache License, Version 2.0 (the "License"); 18607+ * you may not use this file except in compliance with the License. 18608+ * You may obtain a copy of the License at 18609+ * 18610+ * http://www.apache.org/licenses/LICENSE-2.0 18611+ * 18612+ * Unless required by applicable law or agreed to in writing, software 18613+ * distributed under the License is distributed on an "AS IS" BASIS, 18614+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18615+ * See the License for the specific language governing permissions and 18616+ * limitations under the License. 18617+ */ 18618+ 18619+/* $Id: db_utilities_indexing.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */ 18620+ 18621+#ifndef DB_UTILITIES_INDEXING 18622+#define DB_UTILITIES_INDEXING 18623+ 18624+ 18625+ 18626+/***************************************************************** 18627+* Lean and mean begins here * 18628+*****************************************************************/ 18629+ 18630+#include "db_utilities.h" 18631+ 18632+/*! 18633+ * \defgroup LMIndexing (LM) Indexing Utilities (Order Statistics, Matrix Operations) 18634+ */ 18635+/*\{*/ 18636+ 18637+inline void db_SetupMatrixRefs(double **ar,long rows,long cols,double *a) 18638+{ 18639+ long i; 18640+ for(i=0;i<rows;i++) ar[i]=&a[i*cols]; 18641+} 18642+ 18643+inline void db_SymmetricExtendUpperToLower(double **A,int rows,int cols) 18644+{ 18645+ int i,j; 18646+ for(i=1;i<rows;i++) for(j=0;j<i;j++) A[i][j]=A[j][i]; 18647+} 18648+ 18649+void inline db_MultiplyMatrixVectorAtb(double *c,const double * const *At,const double *b,int arows,int acols) 18650+{ 18651+ int i,j; 18652+ double acc; 18653+ 18654+ for(i=0;i<arows;i++) 18655+ { 18656+ acc=0; 18657+ for(j=0;j<acols;j++) acc+=At[j][i]*b[j]; 18658+ c[i]=acc; 18659+ } 18660+} 18661+ 18662+inline void db_MultiplyMatricesAB(double **C,const double * const *A,const double * const *B,int arows,int acols,int bcols) 18663+{ 18664+ int i,j,k; 18665+ double acc; 18666+ 18667+ for(i=0;i<arows;i++) for(j=0;j<bcols;j++) 18668+ { 18669+ acc=0; 18670+ for(k=0;k<acols;k++) acc+=A[i][k]*B[k][j]; 18671+ C[i][j]=acc; 18672+ } 18673+} 18674+ 18675+inline void db_UpperMultiplyMatricesAtB(double **Cu,const double * const *At,const double * const *B,int arows,int acols,int bcols) 18676+{ 18677+ int i,j,k; 18678+ double acc; 18679+ 18680+ for(i=0;i<arows;i++) for(j=i;j<bcols;j++) 18681+ { 18682+ acc=0; 18683+ for(k=0;k<acols;k++) acc+=At[k][i]*B[k][j]; 18684+ Cu[i][j]=acc; 18685+ } 18686+} 18687+ 18688+DB_API void db_Zero(double *d,long nr); 18689+ 18690+inline int db_MaxIndex2(double s[2]) 18691+{ 18692+ if(s[0]>=s[1]) return(0); 18693+ return(1); 18694+} 18695+ 18696+inline int db_MaxIndex3(const double s[3]) 18697+{ 18698+ double best; 18699+ int pos; 18700+ 18701+ best=s[0];pos=0; 18702+ if(s[1]>best){best=s[1];pos=1;} 18703+ if(s[2]>best){best=s[2];pos=2;} 18704+ return(pos); 18705+} 18706+ 18707+inline int db_MaxIndex4(const double s[4]) 18708+{ 18709+ double best; 18710+ int pos; 18711+ 18712+ best=s[0];pos=0; 18713+ if(s[1]>best){best=s[1];pos=1;} 18714+ if(s[2]>best){best=s[2];pos=2;} 18715+ if(s[3]>best){best=s[3];pos=3;} 18716+ return(pos); 18717+} 18718+ 18719+inline int db_MaxIndex5(const double s[5]) 18720+{ 18721+ double best; 18722+ int pos; 18723+ 18724+ best=s[0];pos=0; 18725+ if(s[1]>best){best=s[1];pos=1;} 18726+ if(s[2]>best){best=s[2];pos=2;} 18727+ if(s[3]>best){best=s[3];pos=3;} 18728+ if(s[4]>best){best=s[4];pos=4;} 18729+ return(pos); 18730+} 18731+ 18732+inline int db_MaxIndex6(const double s[6]) 18733+{ 18734+ double best; 18735+ int pos; 18736+ 18737+ best=s[0];pos=0; 18738+ if(s[1]>best){best=s[1];pos=1;} 18739+ if(s[2]>best){best=s[2];pos=2;} 18740+ if(s[3]>best){best=s[3];pos=3;} 18741+ if(s[4]>best){best=s[4];pos=4;} 18742+ if(s[5]>best){best=s[5];pos=5;} 18743+ return(pos); 18744+} 18745+ 18746+inline int db_MaxIndex7(const double s[7]) 18747+{ 18748+ double best; 18749+ int pos; 18750+ 18751+ best=s[0];pos=0; 18752+ if(s[1]>best){best=s[1];pos=1;} 18753+ if(s[2]>best){best=s[2];pos=2;} 18754+ if(s[3]>best){best=s[3];pos=3;} 18755+ if(s[4]>best){best=s[4];pos=4;} 18756+ if(s[5]>best){best=s[5];pos=5;} 18757+ if(s[6]>best){best=s[6];pos=6;} 18758+ return(pos); 18759+} 18760+ 18761+inline int db_MinIndex7(const double s[7]) 18762+{ 18763+ double best; 18764+ int pos; 18765+ 18766+ best=s[0];pos=0; 18767+ if(s[1]<best){best=s[1];pos=1;} 18768+ if(s[2]<best){best=s[2];pos=2;} 18769+ if(s[3]<best){best=s[3];pos=3;} 18770+ if(s[4]<best){best=s[4];pos=4;} 18771+ if(s[5]<best){best=s[5];pos=5;} 18772+ if(s[6]<best){best=s[6];pos=6;} 18773+ return(pos); 18774+} 18775+ 18776+inline int db_MinIndex9(const double s[9]) 18777+{ 18778+ double best; 18779+ int pos; 18780+ 18781+ best=s[0];pos=0; 18782+ if(s[1]<best){best=s[1];pos=1;} 18783+ if(s[2]<best){best=s[2];pos=2;} 18784+ if(s[3]<best){best=s[3];pos=3;} 18785+ if(s[4]<best){best=s[4];pos=4;} 18786+ if(s[5]<best){best=s[5];pos=5;} 18787+ if(s[6]<best){best=s[6];pos=6;} 18788+ if(s[7]<best){best=s[7];pos=7;} 18789+ if(s[8]<best){best=s[8];pos=8;} 18790+ return(pos); 18791+} 18792+ 18793+inline int db_MaxAbsIndex3(const double *s) 18794+{ 18795+ double t,best; 18796+ int pos; 18797+ 18798+ best=fabs(s[0]);pos=0; 18799+ t=fabs(s[1]);if(t>best){best=t;pos=1;} 18800+ t=fabs(s[2]);if(t>best){pos=2;} 18801+ return(pos); 18802+} 18803+ 18804+inline int db_MaxAbsIndex9(const double *s) 18805+{ 18806+ double t,best; 18807+ int pos; 18808+ 18809+ best=fabs(s[0]);pos=0; 18810+ t=fabs(s[1]);if(t>best){best=t;pos=1;} 18811+ t=fabs(s[2]);if(t>best){best=t;pos=2;} 18812+ t=fabs(s[3]);if(t>best){best=t;pos=3;} 18813+ t=fabs(s[4]);if(t>best){best=t;pos=4;} 18814+ t=fabs(s[5]);if(t>best){best=t;pos=5;} 18815+ t=fabs(s[6]);if(t>best){best=t;pos=6;} 18816+ t=fabs(s[7]);if(t>best){best=t;pos=7;} 18817+ t=fabs(s[8]);if(t>best){best=t;pos=8;} 18818+ return(pos); 18819+} 18820+ 18821+ 18822+/*! 18823+Select ordinal pos (zero based) out of nr_elements in s. 18824+temp should point to alloced memory of at least nr_elements*2 18825+Optimized runtimes on 450MHz: 18826+\code 18827+ 30 with 3 microsecs 18828+ 100 with 11 microsecs 18829+ 300 with 30 microsecs 18830+ 500 with 40 microsecs 18831+1000 with 100 microsecs 18832+5000 with 540 microsecs 18833+\endcode 18834+so the expected runtime is around 18835+(nr_elements/10) microseconds 18836+The total quickselect cost of splitting 500 hypotheses recursively 18837+is thus around 100 microseconds 18838+ 18839+Does the same operation as std::nth_element(). 18840+*/ 18841+DB_API double db_LeanQuickSelect(const double *s,long nr_elements,long pos,double *temp); 18842+ 18843+/*! 18844+ Median of 3 doubles 18845+ */ 18846+inline double db_TripleMedian(double a,double b,double c) 18847+{ 18848+ if(a>b) 18849+ { 18850+ if(c>a) return(a); 18851+ else if(c>b) return(c); 18852+ else return(b); 18853+ } 18854+ else 18855+ { 18856+ if(c>b) return(b); 18857+ else if(c>a) return(c); 18858+ else return(a); 18859+ } 18860+} 18861+ 18862+/*! 18863+Align float pointer to nr_bytes by moving forward 18864+*/ 18865+DB_API float* db_AlignPointer_f(float *p,unsigned long nr_bytes); 18866+ 18867+/*! 18868+Align short pointer to nr_bytes by moving forward 18869+*/ 18870+DB_API short* db_AlignPointer_s(short *p,unsigned long nr_bytes); 18871+ 18872+#endif /* DB_UTILITIES_INDEXING */ 18873diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_linalg.cpp b/benchmark/feature_stab/db_vlvm/db_utilities_linalg.cpp 18874new file mode 100644 18875index 00000000..8f68b303 18876--- /dev/null 18877+++ b/benchmark/feature_stab/db_vlvm/db_utilities_linalg.cpp 18878@@ -0,0 +1,376 @@ 18879+/* 18880+ * Copyright (C) 2011 The Android Open Source Project 18881+ * 18882+ * Licensed under the Apache License, Version 2.0 (the "License"); 18883+ * you may not use this file except in compliance with the License. 18884+ * You may obtain a copy of the License at 18885+ * 18886+ * http://www.apache.org/licenses/LICENSE-2.0 18887+ * 18888+ * Unless required by applicable law or agreed to in writing, software 18889+ * distributed under the License is distributed on an "AS IS" BASIS, 18890+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18891+ * See the License for the specific language governing permissions and 18892+ * limitations under the License. 18893+ */ 18894+ 18895+/* $Id: db_utilities_linalg.cpp,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */ 18896+ 18897+#include "db_utilities_linalg.h" 18898+#include "db_utilities.h" 18899+ 18900+ 18901+ 18902+/***************************************************************** 18903+* Lean and mean begins here * 18904+*****************************************************************/ 18905+ 18906+/*Cholesky-factorize symmetric positive definite 6 x 6 matrix A. Upper 18907+part of A is used from the input. The Cholesky factor is output as 18908+subdiagonal part in A and diagonal in d, which is 6-dimensional*/ 18909+void db_CholeskyDecomp6x6(double A[36],double d[6]) 18910+{ 18911+ double s,temp; 18912+ 18913+ /*[50 mult 35 add 6sqrt=85flops 6func]*/ 18914+ /*i=0*/ 18915+ s=A[0]; 18916+ d[0]=((s>0.0)?sqrt(s):1.0); 18917+ temp=db_SafeReciprocal(d[0]); 18918+ A[6]=A[1]*temp; 18919+ A[12]=A[2]*temp; 18920+ A[18]=A[3]*temp; 18921+ A[24]=A[4]*temp; 18922+ A[30]=A[5]*temp; 18923+ /*i=1*/ 18924+ s=A[7]-A[6]*A[6]; 18925+ d[1]=((s>0.0)?sqrt(s):1.0); 18926+ temp=db_SafeReciprocal(d[1]); 18927+ A[13]=(A[8]-A[6]*A[12])*temp; 18928+ A[19]=(A[9]-A[6]*A[18])*temp; 18929+ A[25]=(A[10]-A[6]*A[24])*temp; 18930+ A[31]=(A[11]-A[6]*A[30])*temp; 18931+ /*i=2*/ 18932+ s=A[14]-A[12]*A[12]-A[13]*A[13]; 18933+ d[2]=((s>0.0)?sqrt(s):1.0); 18934+ temp=db_SafeReciprocal(d[2]); 18935+ A[20]=(A[15]-A[12]*A[18]-A[13]*A[19])*temp; 18936+ A[26]=(A[16]-A[12]*A[24]-A[13]*A[25])*temp; 18937+ A[32]=(A[17]-A[12]*A[30]-A[13]*A[31])*temp; 18938+ /*i=3*/ 18939+ s=A[21]-A[18]*A[18]-A[19]*A[19]-A[20]*A[20]; 18940+ d[3]=((s>0.0)?sqrt(s):1.0); 18941+ temp=db_SafeReciprocal(d[3]); 18942+ A[27]=(A[22]-A[18]*A[24]-A[19]*A[25]-A[20]*A[26])*temp; 18943+ A[33]=(A[23]-A[18]*A[30]-A[19]*A[31]-A[20]*A[32])*temp; 18944+ /*i=4*/ 18945+ s=A[28]-A[24]*A[24]-A[25]*A[25]-A[26]*A[26]-A[27]*A[27]; 18946+ d[4]=((s>0.0)?sqrt(s):1.0); 18947+ temp=db_SafeReciprocal(d[4]); 18948+ A[34]=(A[29]-A[24]*A[30]-A[25]*A[31]-A[26]*A[32]-A[27]*A[33])*temp; 18949+ /*i=5*/ 18950+ s=A[35]-A[30]*A[30]-A[31]*A[31]-A[32]*A[32]-A[33]*A[33]-A[34]*A[34]; 18951+ d[5]=((s>0.0)?sqrt(s):1.0); 18952+} 18953+ 18954+/*Cholesky-factorize symmetric positive definite n x n matrix A.Part 18955+above diagonal of A is used from the input, diagonal of A is assumed to 18956+be stored in d. The Cholesky factor is output as 18957+subdiagonal part in A and diagonal in d, which is n-dimensional*/ 18958+void db_CholeskyDecompSeparateDiagonal(double **A,double *d,int n) 18959+{ 18960+ int i,j,k; 18961+ double s; 18962+ double temp = 0.0; 18963+ 18964+ for(i=0;i<n;i++) for(j=i;j<n;j++) 18965+ { 18966+ if(i==j) s=d[i]; 18967+ else s=A[i][j]; 18968+ for(k=i-1;k>=0;k--) s-=A[i][k]*A[j][k]; 18969+ if(i==j) 18970+ { 18971+ d[i]=((s>0.0)?sqrt(s):1.0); 18972+ temp=db_SafeReciprocal(d[i]); 18973+ } 18974+ else A[j][i]=s*temp; 18975+ } 18976+} 18977+ 18978+/*Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition 18979+of an n x n matrix and the right hand side b. The vector b is unchanged*/ 18980+void db_CholeskyBacksub(double *x,const double * const *A,const double *d,int n,const double *b) 18981+{ 18982+ int i,k; 18983+ double s; 18984+ 18985+ for(i=0;i<n;i++) 18986+ { 18987+ for(s=b[i],k=i-1;k>=0;k--) s-=A[i][k]*x[k]; 18988+ x[i]=db_SafeDivision(s,d[i]); 18989+ } 18990+ for(i=n-1;i>=0;i--) 18991+ { 18992+ for(s=x[i],k=i+1;k<n;k++) s-=A[k][i]*x[k]; 18993+ x[i]=db_SafeDivision(s,d[i]); 18994+ } 18995+} 18996+ 18997+/*Cholesky-factorize symmetric positive definite 3 x 3 matrix A. Part 18998+above diagonal of A is used from the input, diagonal of A is assumed to 18999+be stored in d. The Cholesky factor is output as subdiagonal part in A 19000+and diagonal in d, which is 3-dimensional*/ 19001+void db_CholeskyDecomp3x3SeparateDiagonal(double A[9],double d[3]) 19002+{ 19003+ double s,temp; 19004+ 19005+ /*i=0*/ 19006+ s=d[0]; 19007+ d[0]=((s>0.0)?sqrt(s):1.0); 19008+ temp=db_SafeReciprocal(d[0]); 19009+ A[3]=A[1]*temp; 19010+ A[6]=A[2]*temp; 19011+ /*i=1*/ 19012+ s=d[1]-A[3]*A[3]; 19013+ d[1]=((s>0.0)?sqrt(s):1.0); 19014+ temp=db_SafeReciprocal(d[1]); 19015+ A[7]=(A[5]-A[3]*A[6])*temp; 19016+ /*i=2*/ 19017+ s=d[2]-A[6]*A[6]-A[7]*A[7]; 19018+ d[2]=((s>0.0)?sqrt(s):1.0); 19019+} 19020+ 19021+/*Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition 19022+of a 3 x 3 matrix and the right hand side b. The vector b is unchanged*/ 19023+void db_CholeskyBacksub3x3(double x[3],const double A[9],const double d[3],const double b[3]) 19024+{ 19025+ /*[42 mult 30 add=72flops]*/ 19026+ x[0]=db_SafeDivision(b[0],d[0]); 19027+ x[1]=db_SafeDivision((b[1]-A[3]*x[0]),d[1]); 19028+ x[2]=db_SafeDivision((b[2]-A[6]*x[0]-A[7]*x[1]),d[2]); 19029+ x[2]=db_SafeDivision(x[2],d[2]); 19030+ x[1]=db_SafeDivision((x[1]-A[7]*x[2]),d[1]); 19031+ x[0]=db_SafeDivision((x[0]-A[6]*x[2]-A[3]*x[1]),d[0]); 19032+} 19033+ 19034+/*Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition 19035+of a 6 x 6 matrix and the right hand side b. The vector b is unchanged*/ 19036+void db_CholeskyBacksub6x6(double x[6],const double A[36],const double d[6],const double b[6]) 19037+{ 19038+ /*[42 mult 30 add=72flops]*/ 19039+ x[0]=db_SafeDivision(b[0],d[0]); 19040+ x[1]=db_SafeDivision((b[1]-A[6]*x[0]),d[1]); 19041+ x[2]=db_SafeDivision((b[2]-A[12]*x[0]-A[13]*x[1]),d[2]); 19042+ x[3]=db_SafeDivision((b[3]-A[18]*x[0]-A[19]*x[1]-A[20]*x[2]),d[3]); 19043+ x[4]=db_SafeDivision((b[4]-A[24]*x[0]-A[25]*x[1]-A[26]*x[2]-A[27]*x[3]),d[4]); 19044+ x[5]=db_SafeDivision((b[5]-A[30]*x[0]-A[31]*x[1]-A[32]*x[2]-A[33]*x[3]-A[34]*x[4]),d[5]); 19045+ x[5]=db_SafeDivision(x[5],d[5]); 19046+ x[4]=db_SafeDivision((x[4]-A[34]*x[5]),d[4]); 19047+ x[3]=db_SafeDivision((x[3]-A[33]*x[5]-A[27]*x[4]),d[3]); 19048+ x[2]=db_SafeDivision((x[2]-A[32]*x[5]-A[26]*x[4]-A[20]*x[3]),d[2]); 19049+ x[1]=db_SafeDivision((x[1]-A[31]*x[5]-A[25]*x[4]-A[19]*x[3]-A[13]*x[2]),d[1]); 19050+ x[0]=db_SafeDivision((x[0]-A[30]*x[5]-A[24]*x[4]-A[18]*x[3]-A[12]*x[2]-A[6]*x[1]),d[0]); 19051+} 19052+ 19053+ 19054+void db_Orthogonalize6x7(double A[42],int orthonormalize) 19055+{ 19056+ int i; 19057+ double ss[6]; 19058+ 19059+ /*Compute square sums of rows*/ 19060+ ss[0]=db_SquareSum7(A); 19061+ ss[1]=db_SquareSum7(A+7); 19062+ ss[2]=db_SquareSum7(A+14); 19063+ ss[3]=db_SquareSum7(A+21); 19064+ ss[4]=db_SquareSum7(A+28); 19065+ ss[5]=db_SquareSum7(A+35); 19066+ 19067+ ss[1]-=db_OrthogonalizePair7(A+7 ,A,ss[0]); 19068+ ss[2]-=db_OrthogonalizePair7(A+14,A,ss[0]); 19069+ ss[3]-=db_OrthogonalizePair7(A+21,A,ss[0]); 19070+ ss[4]-=db_OrthogonalizePair7(A+28,A,ss[0]); 19071+ ss[5]-=db_OrthogonalizePair7(A+35,A,ss[0]); 19072+ 19073+ /*Pivot on largest ss (could also be done on ss/(original_ss))*/ 19074+ i=db_MaxIndex5(ss+1); 19075+ db_OrthogonalizationSwap7(A+7,i,ss+1); 19076+ 19077+ ss[2]-=db_OrthogonalizePair7(A+14,A+7,ss[1]); 19078+ ss[3]-=db_OrthogonalizePair7(A+21,A+7,ss[1]); 19079+ ss[4]-=db_OrthogonalizePair7(A+28,A+7,ss[1]); 19080+ ss[5]-=db_OrthogonalizePair7(A+35,A+7,ss[1]); 19081+ 19082+ i=db_MaxIndex4(ss+2); 19083+ db_OrthogonalizationSwap7(A+14,i,ss+2); 19084+ 19085+ ss[3]-=db_OrthogonalizePair7(A+21,A+14,ss[2]); 19086+ ss[4]-=db_OrthogonalizePair7(A+28,A+14,ss[2]); 19087+ ss[5]-=db_OrthogonalizePair7(A+35,A+14,ss[2]); 19088+ 19089+ i=db_MaxIndex3(ss+3); 19090+ db_OrthogonalizationSwap7(A+21,i,ss+3); 19091+ 19092+ ss[4]-=db_OrthogonalizePair7(A+28,A+21,ss[3]); 19093+ ss[5]-=db_OrthogonalizePair7(A+35,A+21,ss[3]); 19094+ 19095+ i=db_MaxIndex2(ss+4); 19096+ db_OrthogonalizationSwap7(A+28,i,ss+4); 19097+ 19098+ ss[5]-=db_OrthogonalizePair7(A+35,A+28,ss[4]); 19099+ 19100+ if(orthonormalize) 19101+ { 19102+ db_MultiplyScalar7(A ,db_SafeSqrtReciprocal(ss[0])); 19103+ db_MultiplyScalar7(A+7 ,db_SafeSqrtReciprocal(ss[1])); 19104+ db_MultiplyScalar7(A+14,db_SafeSqrtReciprocal(ss[2])); 19105+ db_MultiplyScalar7(A+21,db_SafeSqrtReciprocal(ss[3])); 19106+ db_MultiplyScalar7(A+28,db_SafeSqrtReciprocal(ss[4])); 19107+ db_MultiplyScalar7(A+35,db_SafeSqrtReciprocal(ss[5])); 19108+ } 19109+} 19110+ 19111+void db_Orthogonalize8x9(double A[72],int orthonormalize) 19112+{ 19113+ int i; 19114+ double ss[8]; 19115+ 19116+ /*Compute square sums of rows*/ 19117+ ss[0]=db_SquareSum9(A); 19118+ ss[1]=db_SquareSum9(A+9); 19119+ ss[2]=db_SquareSum9(A+18); 19120+ ss[3]=db_SquareSum9(A+27); 19121+ ss[4]=db_SquareSum9(A+36); 19122+ ss[5]=db_SquareSum9(A+45); 19123+ ss[6]=db_SquareSum9(A+54); 19124+ ss[7]=db_SquareSum9(A+63); 19125+ 19126+ ss[1]-=db_OrthogonalizePair9(A+9 ,A,ss[0]); 19127+ ss[2]-=db_OrthogonalizePair9(A+18,A,ss[0]); 19128+ ss[3]-=db_OrthogonalizePair9(A+27,A,ss[0]); 19129+ ss[4]-=db_OrthogonalizePair9(A+36,A,ss[0]); 19130+ ss[5]-=db_OrthogonalizePair9(A+45,A,ss[0]); 19131+ ss[6]-=db_OrthogonalizePair9(A+54,A,ss[0]); 19132+ ss[7]-=db_OrthogonalizePair9(A+63,A,ss[0]); 19133+ 19134+ /*Pivot on largest ss (could also be done on ss/(original_ss))*/ 19135+ i=db_MaxIndex7(ss+1); 19136+ db_OrthogonalizationSwap9(A+9,i,ss+1); 19137+ 19138+ ss[2]-=db_OrthogonalizePair9(A+18,A+9,ss[1]); 19139+ ss[3]-=db_OrthogonalizePair9(A+27,A+9,ss[1]); 19140+ ss[4]-=db_OrthogonalizePair9(A+36,A+9,ss[1]); 19141+ ss[5]-=db_OrthogonalizePair9(A+45,A+9,ss[1]); 19142+ ss[6]-=db_OrthogonalizePair9(A+54,A+9,ss[1]); 19143+ ss[7]-=db_OrthogonalizePair9(A+63,A+9,ss[1]); 19144+ 19145+ i=db_MaxIndex6(ss+2); 19146+ db_OrthogonalizationSwap9(A+18,i,ss+2); 19147+ 19148+ ss[3]-=db_OrthogonalizePair9(A+27,A+18,ss[2]); 19149+ ss[4]-=db_OrthogonalizePair9(A+36,A+18,ss[2]); 19150+ ss[5]-=db_OrthogonalizePair9(A+45,A+18,ss[2]); 19151+ ss[6]-=db_OrthogonalizePair9(A+54,A+18,ss[2]); 19152+ ss[7]-=db_OrthogonalizePair9(A+63,A+18,ss[2]); 19153+ 19154+ i=db_MaxIndex5(ss+3); 19155+ db_OrthogonalizationSwap9(A+27,i,ss+3); 19156+ 19157+ ss[4]-=db_OrthogonalizePair9(A+36,A+27,ss[3]); 19158+ ss[5]-=db_OrthogonalizePair9(A+45,A+27,ss[3]); 19159+ ss[6]-=db_OrthogonalizePair9(A+54,A+27,ss[3]); 19160+ ss[7]-=db_OrthogonalizePair9(A+63,A+27,ss[3]); 19161+ 19162+ i=db_MaxIndex4(ss+4); 19163+ db_OrthogonalizationSwap9(A+36,i,ss+4); 19164+ 19165+ ss[5]-=db_OrthogonalizePair9(A+45,A+36,ss[4]); 19166+ ss[6]-=db_OrthogonalizePair9(A+54,A+36,ss[4]); 19167+ ss[7]-=db_OrthogonalizePair9(A+63,A+36,ss[4]); 19168+ 19169+ i=db_MaxIndex3(ss+5); 19170+ db_OrthogonalizationSwap9(A+45,i,ss+5); 19171+ 19172+ ss[6]-=db_OrthogonalizePair9(A+54,A+45,ss[5]); 19173+ ss[7]-=db_OrthogonalizePair9(A+63,A+45,ss[5]); 19174+ 19175+ i=db_MaxIndex2(ss+6); 19176+ db_OrthogonalizationSwap9(A+54,i,ss+6); 19177+ 19178+ ss[7]-=db_OrthogonalizePair9(A+63,A+54,ss[6]); 19179+ 19180+ if(orthonormalize) 19181+ { 19182+ db_MultiplyScalar9(A ,db_SafeSqrtReciprocal(ss[0])); 19183+ db_MultiplyScalar9(A+9 ,db_SafeSqrtReciprocal(ss[1])); 19184+ db_MultiplyScalar9(A+18,db_SafeSqrtReciprocal(ss[2])); 19185+ db_MultiplyScalar9(A+27,db_SafeSqrtReciprocal(ss[3])); 19186+ db_MultiplyScalar9(A+36,db_SafeSqrtReciprocal(ss[4])); 19187+ db_MultiplyScalar9(A+45,db_SafeSqrtReciprocal(ss[5])); 19188+ db_MultiplyScalar9(A+54,db_SafeSqrtReciprocal(ss[6])); 19189+ db_MultiplyScalar9(A+63,db_SafeSqrtReciprocal(ss[7])); 19190+ } 19191+} 19192+ 19193+void db_NullVectorOrthonormal6x7(double x[7],const double A[42]) 19194+{ 19195+ int i; 19196+ double omss[7]; 19197+ const double *B; 19198+ 19199+ /*Pivot by choosing row of the identity matrix 19200+ (the one corresponding to column of A with smallest square sum)*/ 19201+ omss[0]=db_SquareSum6Stride7(A); 19202+ omss[1]=db_SquareSum6Stride7(A+1); 19203+ omss[2]=db_SquareSum6Stride7(A+2); 19204+ omss[3]=db_SquareSum6Stride7(A+3); 19205+ omss[4]=db_SquareSum6Stride7(A+4); 19206+ omss[5]=db_SquareSum6Stride7(A+5); 19207+ omss[6]=db_SquareSum6Stride7(A+6); 19208+ i=db_MinIndex7(omss); 19209+ /*orthogonalize that row against all previous rows 19210+ and normalize it*/ 19211+ B=A+i; 19212+ db_MultiplyScalarCopy7(x,A,-B[0]); 19213+ db_RowOperation7(x,A+7 ,B[7]); 19214+ db_RowOperation7(x,A+14,B[14]); 19215+ db_RowOperation7(x,A+21,B[21]); 19216+ db_RowOperation7(x,A+28,B[28]); 19217+ db_RowOperation7(x,A+35,B[35]); 19218+ x[i]+=1.0; 19219+ db_MultiplyScalar7(x,db_SafeSqrtReciprocal(1.0-omss[i])); 19220+} 19221+ 19222+void db_NullVectorOrthonormal8x9(double x[9],const double A[72]) 19223+{ 19224+ int i; 19225+ double omss[9]; 19226+ const double *B; 19227+ 19228+ /*Pivot by choosing row of the identity matrix 19229+ (the one corresponding to column of A with smallest square sum)*/ 19230+ omss[0]=db_SquareSum8Stride9(A); 19231+ omss[1]=db_SquareSum8Stride9(A+1); 19232+ omss[2]=db_SquareSum8Stride9(A+2); 19233+ omss[3]=db_SquareSum8Stride9(A+3); 19234+ omss[4]=db_SquareSum8Stride9(A+4); 19235+ omss[5]=db_SquareSum8Stride9(A+5); 19236+ omss[6]=db_SquareSum8Stride9(A+6); 19237+ omss[7]=db_SquareSum8Stride9(A+7); 19238+ omss[8]=db_SquareSum8Stride9(A+8); 19239+ i=db_MinIndex9(omss); 19240+ /*orthogonalize that row against all previous rows 19241+ and normalize it*/ 19242+ B=A+i; 19243+ db_MultiplyScalarCopy9(x,A,-B[0]); 19244+ db_RowOperation9(x,A+9 ,B[9]); 19245+ db_RowOperation9(x,A+18,B[18]); 19246+ db_RowOperation9(x,A+27,B[27]); 19247+ db_RowOperation9(x,A+36,B[36]); 19248+ db_RowOperation9(x,A+45,B[45]); 19249+ db_RowOperation9(x,A+54,B[54]); 19250+ db_RowOperation9(x,A+63,B[63]); 19251+ x[i]+=1.0; 19252+ db_MultiplyScalar9(x,db_SafeSqrtReciprocal(1.0-omss[i])); 19253+} 19254+ 19255diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_linalg.h b/benchmark/feature_stab/db_vlvm/db_utilities_linalg.h 19256new file mode 100644 19257index 00000000..1f63d4e5 19258--- /dev/null 19259+++ b/benchmark/feature_stab/db_vlvm/db_utilities_linalg.h 19260@@ -0,0 +1,802 @@ 19261+/* 19262+ * Copyright (C) 2011 The Android Open Source Project 19263+ * 19264+ * Licensed under the Apache License, Version 2.0 (the "License"); 19265+ * you may not use this file except in compliance with the License. 19266+ * You may obtain a copy of the License at 19267+ * 19268+ * http://www.apache.org/licenses/LICENSE-2.0 19269+ * 19270+ * Unless required by applicable law or agreed to in writing, software 19271+ * distributed under the License is distributed on an "AS IS" BASIS, 19272+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19273+ * See the License for the specific language governing permissions and 19274+ * limitations under the License. 19275+ */ 19276+ 19277+/* $Id: db_utilities_linalg.h,v 1.5 2011/06/17 14:03:31 mbansal Exp $ */ 19278+ 19279+#ifndef DB_UTILITIES_LINALG 19280+#define DB_UTILITIES_LINALG 19281+ 19282+#include "db_utilities.h" 19283+ 19284+ 19285+ 19286+/***************************************************************** 19287+* Lean and mean begins here * 19288+*****************************************************************/ 19289+/*! 19290+ * \defgroup LMLinAlg (LM) Linear Algebra Utilities (QR factorization, orthogonal basis, etc.) 19291+ */ 19292+ 19293+/*! 19294+ \ingroup LMBasicUtilities 19295+ */ 19296+inline void db_MultiplyScalar6(double A[6],double mult) 19297+{ 19298+ (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; 19299+ (*A++) *= mult; 19300+} 19301+/*! 19302+ \ingroup LMBasicUtilities 19303+ */ 19304+inline void db_MultiplyScalar7(double A[7],double mult) 19305+{ 19306+ (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; 19307+ (*A++) *= mult; (*A++) *= mult; 19308+} 19309+/*! 19310+ \ingroup LMBasicUtilities 19311+ */ 19312+inline void db_MultiplyScalar9(double A[9],double mult) 19313+{ 19314+ (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; 19315+ (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; 19316+} 19317+ 19318+/*! 19319+ \ingroup LMBasicUtilities 19320+ */ 19321+inline double db_SquareSum6Stride7(const double *x) 19322+{ 19323+ return(db_sqr(x[0])+db_sqr(x[7])+db_sqr(x[14])+ 19324+ db_sqr(x[21])+db_sqr(x[28])+db_sqr(x[35])); 19325+} 19326+ 19327+/*! 19328+ \ingroup LMBasicUtilities 19329+ */ 19330+inline double db_SquareSum8Stride9(const double *x) 19331+{ 19332+ return(db_sqr(x[0])+db_sqr(x[9])+db_sqr(x[18])+ 19333+ db_sqr(x[27])+db_sqr(x[36])+db_sqr(x[45])+ 19334+ db_sqr(x[54])+db_sqr(x[63])); 19335+} 19336+ 19337+/*! 19338+ \ingroup LMLinAlg 19339+ Cholesky-factorize symmetric positive definite 6 x 6 matrix A. Upper 19340+part of A is used from the input. The Cholesky factor is output as 19341+subdiagonal part in A and diagonal in d, which is 6-dimensional 19342+1.9 microseconds on 450MHz*/ 19343+DB_API void db_CholeskyDecomp6x6(double A[36],double d[6]); 19344+ 19345+/*! 19346+ \ingroup LMLinAlg 19347+ Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition 19348+of a 6 x 6 matrix and the right hand side b. The vector b is unchanged 19349+1.3 microseconds on 450MHz*/ 19350+DB_API void db_CholeskyBacksub6x6(double x[6],const double A[36],const double d[6],const double b[6]); 19351+ 19352+/*! 19353+ \ingroup LMLinAlg 19354+ Cholesky-factorize symmetric positive definite n x n matrix A.Part 19355+above diagonal of A is used from the input, diagonal of A is assumed to 19356+be stored in d. The Cholesky factor is output as 19357+subdiagonal part in A and diagonal in d, which is n-dimensional*/ 19358+DB_API void db_CholeskyDecompSeparateDiagonal(double **A,double *d,int n); 19359+ 19360+/*! 19361+ \ingroup LMLinAlg 19362+ Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition 19363+of an n x n matrix and the right hand side b. The vector b is unchanged*/ 19364+DB_API void db_CholeskyBacksub(double *x,const double * const *A,const double *d,int n,const double *b); 19365+ 19366+/*! 19367+ \ingroup LMLinAlg 19368+ Cholesky-factorize symmetric positive definite 3 x 3 matrix A. Part 19369+above diagonal of A is used from the input, diagonal of A is assumed to 19370+be stored in d. The Cholesky factor is output as subdiagonal part in A 19371+and diagonal in d, which is 3-dimensional*/ 19372+DB_API void db_CholeskyDecomp3x3SeparateDiagonal(double A[9],double d[3]); 19373+ 19374+/*! 19375+ \ingroup LMLinAlg 19376+ Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition 19377+of a 3 x 3 matrix and the right hand side b. The vector b is unchanged*/ 19378+DB_API void db_CholeskyBacksub3x3(double x[3],const double A[9],const double d[3],const double b[3]); 19379+ 19380+/*! 19381+ \ingroup LMLinAlg 19382+ perform A-=B*mult*/ 19383+inline void db_RowOperation3(double A[3],const double B[3],double mult) 19384+{ 19385+ *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); 19386+} 19387+ 19388+/*! 19389+ \ingroup LMLinAlg 19390+ */ 19391+inline void db_RowOperation7(double A[7],const double B[7],double mult) 19392+{ 19393+ *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); 19394+ *A++ -= mult*(*B++); *A++ -= mult*(*B++); 19395+} 19396+ 19397+/*! 19398+ \ingroup LMLinAlg 19399+ */ 19400+inline void db_RowOperation9(double A[9],const double B[9],double mult) 19401+{ 19402+ *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); 19403+ *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); 19404+} 19405+ 19406+/*! 19407+ \ingroup LMBasicUtilities 19408+ Swap values of A[7] and B[7] 19409+ */ 19410+inline void db_Swap7(double A[7],double B[7]) 19411+{ 19412+ double temp; 19413+ temp= *A; *A++ = *B; *B++ =temp; temp= *A; *A++ = *B; *B++ =temp; temp= *A; *A++ = *B; *B++ =temp; 19414+ temp= *A; *A++ = *B; *B++ =temp; temp= *A; *A++ = *B; *B++ =temp; temp= *A; *A++ = *B; *B++ =temp; 19415+ temp= *A; *A++ = *B; *B++ =temp; 19416+} 19417+ 19418+/*! 19419+ \ingroup LMBasicUtilities 19420+ Swap values of A[9] and B[9] 19421+ */ 19422+inline void db_Swap9(double A[9],double B[9]) 19423+{ 19424+ double temp; 19425+ temp= *A; *A++ = *B; *B++ =temp; temp= *A; *A++ = *B; *B++ =temp; temp= *A; *A++ = *B; *B++ =temp; 19426+ temp= *A; *A++ = *B; *B++ =temp; temp= *A; *A++ = *B; *B++ =temp; temp= *A; *A++ = *B; *B++ =temp; 19427+ temp= *A; *A++ = *B; *B++ =temp; temp= *A; *A++ = *B; *B++ =temp; temp= *A; *A++ = *B; *B++ =temp; 19428+} 19429+ 19430+ 19431+/*! 19432+ \ingroup LMLinAlg 19433+ */ 19434+DB_API void db_Orthogonalize6x7(double A[42],int orthonormalize=0); 19435+ 19436+/*! 19437+ \ingroup LMLinAlg 19438+ */ 19439+DB_API void db_Orthogonalize8x9(double A[72],int orthonormalize=0); 19440+ 19441+/*! 19442+ \ingroup LMLinAlg 19443+ */ 19444+inline double db_OrthogonalizePair7(double *x,const double *v,double ssv) 19445+{ 19446+ double m,sp,sp_m; 19447+ 19448+ m=db_SafeReciprocal(ssv); 19449+ sp=db_ScalarProduct7(x,v); 19450+ sp_m=sp*m; 19451+ db_RowOperation7(x,v,sp_m); 19452+ return(sp*sp_m); 19453+} 19454+ 19455+/*! 19456+ \ingroup LMLinAlg 19457+ */ 19458+inline double db_OrthogonalizePair9(double *x,const double *v,double ssv) 19459+{ 19460+ double m,sp,sp_m; 19461+ 19462+ m=db_SafeReciprocal(ssv); 19463+ sp=db_ScalarProduct9(x,v); 19464+ sp_m=sp*m; 19465+ db_RowOperation9(x,v,sp_m); 19466+ return(sp*sp_m); 19467+} 19468+ 19469+/*! 19470+ \ingroup LMLinAlg 19471+ */ 19472+inline void db_OrthogonalizationSwap7(double *A,int i,double *ss) 19473+{ 19474+ double temp; 19475+ 19476+ db_Swap7(A,A+7*i); 19477+ temp=ss[0]; ss[0]=ss[i]; ss[i]=temp; 19478+} 19479+/*! 19480+ \ingroup LMLinAlg 19481+ */ 19482+inline void db_OrthogonalizationSwap9(double *A,int i,double *ss) 19483+{ 19484+ double temp; 19485+ 19486+ db_Swap9(A,A+9*i); 19487+ temp=ss[0]; ss[0]=ss[i]; ss[i]=temp; 19488+} 19489+ 19490+/*! 19491+ \ingroup LMLinAlg 19492+ */ 19493+DB_API void db_NullVectorOrthonormal6x7(double x[7],const double A[42]); 19494+/*! 19495+ \ingroup LMLinAlg 19496+ */ 19497+DB_API void db_NullVectorOrthonormal8x9(double x[9],const double A[72]); 19498+ 19499+/*! 19500+ \ingroup LMLinAlg 19501+ */ 19502+inline void db_NullVector6x7Destructive(double x[7],double A[42]) 19503+{ 19504+ db_Orthogonalize6x7(A,1); 19505+ db_NullVectorOrthonormal6x7(x,A); 19506+} 19507+ 19508+/*! 19509+ \ingroup LMLinAlg 19510+ */ 19511+inline void db_NullVector8x9Destructive(double x[9],double A[72]) 19512+{ 19513+ db_Orthogonalize8x9(A,1); 19514+ db_NullVectorOrthonormal8x9(x,A); 19515+} 19516+ 19517+inline int db_ScalarProduct512_s(const short *f,const short *g) 19518+{ 19519+#ifndef DB_USE_MMX 19520+ int back; 19521+ back=0; 19522+ for(int i=1; i<=512; i++) 19523+ back+=(*f++)*(*g++); 19524+ 19525+ return(back); 19526+#endif 19527+} 19528+ 19529+ 19530+inline int db_ScalarProduct32_s(const short *f,const short *g) 19531+{ 19532+#ifndef DB_USE_MMX 19533+ int back; 19534+ back=0; 19535+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19536+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19537+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19538+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19539+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19540+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19541+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19542+ 19543+ return(back); 19544+#endif 19545+} 19546+ 19547+/*! 19548+ \ingroup LMLinAlg 19549+ Scalar product of 128-vectors (short) 19550+ Compile-time control: MMX, SSE2 or standard C 19551+ */ 19552+inline int db_ScalarProduct128_s(const short *f,const short *g) 19553+{ 19554+#ifndef DB_USE_MMX 19555+ int back; 19556+ back=0; 19557+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19558+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19559+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19560+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19561+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19562+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19563+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19564+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19565+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19566+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19567+ 19568+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19569+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19570+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19571+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19572+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19573+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19574+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19575+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19576+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19577+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19578+ 19579+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19580+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19581+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19582+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19583+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19584+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19585+ 19586+ return(back); 19587+#else 19588+#ifdef DB_USE_SSE2 19589+ int back; 19590+ 19591+ _asm 19592+ { 19593+ mov eax,f 19594+ mov ecx,g 19595+ /*First iteration************************************/ 19596+ movdqa xmm0,[eax] 19597+ pxor xmm7,xmm7 /*Set xmm7 to zero*/ 19598+ pmaddwd xmm0,[ecx] 19599+ /*Stall*/ 19600+ /*Standard iteration************************************/ 19601+ movdqa xmm2,[eax+16] 19602+ paddd xmm7,xmm0 19603+ pmaddwd xmm2,[ecx+16] 19604+ /*Stall*/ 19605+ movdqa xmm1,[eax+32] 19606+ paddd xmm7,xmm2 19607+ pmaddwd xmm1,[ecx+32] 19608+ /*Stall*/ 19609+ /*Standard iteration************************************/ 19610+ movdqa xmm0,[eax+48] 19611+ paddd xmm7,xmm1 19612+ pmaddwd xmm0,[ecx+48] 19613+ /*Stall*/ 19614+ /*Standard iteration************************************/ 19615+ movdqa xmm2,[eax+64] 19616+ paddd xmm7,xmm0 19617+ pmaddwd xmm2,[ecx+64] 19618+ /*Stall*/ 19619+ movdqa xmm1,[eax+80] 19620+ paddd xmm7,xmm2 19621+ pmaddwd xmm1,[ecx+80] 19622+ /*Stall*/ 19623+ /*Standard iteration************************************/ 19624+ movdqa xmm0,[eax+96] 19625+ paddd xmm7,xmm1 19626+ pmaddwd xmm0,[ecx+96] 19627+ /*Stall*/ 19628+ /*Standard iteration************************************/ 19629+ movdqa xmm2,[eax+112] 19630+ paddd xmm7,xmm0 19631+ pmaddwd xmm2,[ecx+112] 19632+ /*Stall*/ 19633+ movdqa xmm1,[eax+128] 19634+ paddd xmm7,xmm2 19635+ pmaddwd xmm1,[ecx+128] 19636+ /*Stall*/ 19637+ /*Standard iteration************************************/ 19638+ movdqa xmm0,[eax+144] 19639+ paddd xmm7,xmm1 19640+ pmaddwd xmm0,[ecx+144] 19641+ /*Stall*/ 19642+ /*Standard iteration************************************/ 19643+ movdqa xmm2,[eax+160] 19644+ paddd xmm7,xmm0 19645+ pmaddwd xmm2,[ecx+160] 19646+ /*Stall*/ 19647+ movdqa xmm1,[eax+176] 19648+ paddd xmm7,xmm2 19649+ pmaddwd xmm1,[ecx+176] 19650+ /*Stall*/ 19651+ /*Standard iteration************************************/ 19652+ movdqa xmm0,[eax+192] 19653+ paddd xmm7,xmm1 19654+ pmaddwd xmm0,[ecx+192] 19655+ /*Stall*/ 19656+ /*Standard iteration************************************/ 19657+ movdqa xmm2,[eax+208] 19658+ paddd xmm7,xmm0 19659+ pmaddwd xmm2,[ecx+208] 19660+ /*Stall*/ 19661+ movdqa xmm1,[eax+224] 19662+ paddd xmm7,xmm2 19663+ pmaddwd xmm1,[ecx+224] 19664+ /*Stall*/ 19665+ /*Standard iteration************************************/ 19666+ movdqa xmm0,[eax+240] 19667+ paddd xmm7,xmm1 19668+ pmaddwd xmm0,[ecx+240] 19669+ /*Stall*/ 19670+ /*Rest iteration************************************/ 19671+ paddd xmm7,xmm0 19672+ 19673+ /* add up the sum squares */ 19674+ movhlps xmm0,xmm7 /* high half to low half */ 19675+ paddd xmm7,xmm0 /* add high to low */ 19676+ pshuflw xmm0,xmm7, 0xE /* reshuffle */ 19677+ paddd xmm7,xmm0 /* add remaining */ 19678+ movd back,xmm7 19679+ 19680+ emms 19681+ } 19682+ 19683+ return(back); 19684+#else 19685+ int back; 19686+ 19687+ _asm 19688+ { 19689+ mov eax,f 19690+ mov ecx,g 19691+ /*First iteration************************************/ 19692+ movq mm0,[eax] 19693+ pxor mm7,mm7 /*Set mm7 to zero*/ 19694+ pmaddwd mm0,[ecx] 19695+ /*Stall*/ 19696+ movq mm1,[eax+8] 19697+ /*Stall*/ 19698+ pmaddwd mm1,[ecx+8] 19699+ /*Stall*/ 19700+ /*Standard iteration************************************/ 19701+ movq mm2,[eax+16] 19702+ paddd mm7,mm0 19703+ pmaddwd mm2,[ecx+16] 19704+ /*Stall*/ 19705+ movq mm0,[eax+24] 19706+ paddd mm7,mm1 19707+ pmaddwd mm0,[ecx+24] 19708+ /*Stall*/ 19709+ movq mm1,[eax+32] 19710+ paddd mm7,mm2 19711+ pmaddwd mm1,[ecx+32] 19712+ /*Stall*/ 19713+ /*Standard iteration************************************/ 19714+ movq mm2,[eax+40] 19715+ paddd mm7,mm0 19716+ pmaddwd mm2,[ecx+40] 19717+ /*Stall*/ 19718+ movq mm0,[eax+48] 19719+ paddd mm7,mm1 19720+ pmaddwd mm0,[ecx+48] 19721+ /*Stall*/ 19722+ movq mm1,[eax+56] 19723+ paddd mm7,mm2 19724+ pmaddwd mm1,[ecx+56] 19725+ /*Stall*/ 19726+ /*Standard iteration************************************/ 19727+ movq mm2,[eax+64] 19728+ paddd mm7,mm0 19729+ pmaddwd mm2,[ecx+64] 19730+ /*Stall*/ 19731+ movq mm0,[eax+72] 19732+ paddd mm7,mm1 19733+ pmaddwd mm0,[ecx+72] 19734+ /*Stall*/ 19735+ movq mm1,[eax+80] 19736+ paddd mm7,mm2 19737+ pmaddwd mm1,[ecx+80] 19738+ /*Stall*/ 19739+ /*Standard iteration************************************/ 19740+ movq mm2,[eax+88] 19741+ paddd mm7,mm0 19742+ pmaddwd mm2,[ecx+88] 19743+ /*Stall*/ 19744+ movq mm0,[eax+96] 19745+ paddd mm7,mm1 19746+ pmaddwd mm0,[ecx+96] 19747+ /*Stall*/ 19748+ movq mm1,[eax+104] 19749+ paddd mm7,mm2 19750+ pmaddwd mm1,[ecx+104] 19751+ /*Stall*/ 19752+ /*Standard iteration************************************/ 19753+ movq mm2,[eax+112] 19754+ paddd mm7,mm0 19755+ pmaddwd mm2,[ecx+112] 19756+ /*Stall*/ 19757+ movq mm0,[eax+120] 19758+ paddd mm7,mm1 19759+ pmaddwd mm0,[ecx+120] 19760+ /*Stall*/ 19761+ movq mm1,[eax+128] 19762+ paddd mm7,mm2 19763+ pmaddwd mm1,[ecx+128] 19764+ /*Stall*/ 19765+ /*Standard iteration************************************/ 19766+ movq mm2,[eax+136] 19767+ paddd mm7,mm0 19768+ pmaddwd mm2,[ecx+136] 19769+ /*Stall*/ 19770+ movq mm0,[eax+144] 19771+ paddd mm7,mm1 19772+ pmaddwd mm0,[ecx+144] 19773+ /*Stall*/ 19774+ movq mm1,[eax+152] 19775+ paddd mm7,mm2 19776+ pmaddwd mm1,[ecx+152] 19777+ /*Stall*/ 19778+ /*Standard iteration************************************/ 19779+ movq mm2,[eax+160] 19780+ paddd mm7,mm0 19781+ pmaddwd mm2,[ecx+160] 19782+ /*Stall*/ 19783+ movq mm0,[eax+168] 19784+ paddd mm7,mm1 19785+ pmaddwd mm0,[ecx+168] 19786+ /*Stall*/ 19787+ movq mm1,[eax+176] 19788+ paddd mm7,mm2 19789+ pmaddwd mm1,[ecx+176] 19790+ /*Stall*/ 19791+ /*Standard iteration************************************/ 19792+ movq mm2,[eax+184] 19793+ paddd mm7,mm0 19794+ pmaddwd mm2,[ecx+184] 19795+ /*Stall*/ 19796+ movq mm0,[eax+192] 19797+ paddd mm7,mm1 19798+ pmaddwd mm0,[ecx+192] 19799+ /*Stall*/ 19800+ movq mm1,[eax+200] 19801+ paddd mm7,mm2 19802+ pmaddwd mm1,[ecx+200] 19803+ /*Stall*/ 19804+ /*Standard iteration************************************/ 19805+ movq mm2,[eax+208] 19806+ paddd mm7,mm0 19807+ pmaddwd mm2,[ecx+208] 19808+ /*Stall*/ 19809+ movq mm0,[eax+216] 19810+ paddd mm7,mm1 19811+ pmaddwd mm0,[ecx+216] 19812+ /*Stall*/ 19813+ movq mm1,[eax+224] 19814+ paddd mm7,mm2 19815+ pmaddwd mm1,[ecx+224] 19816+ /*Stall*/ 19817+ /*Standard iteration************************************/ 19818+ movq mm2,[eax+232] 19819+ paddd mm7,mm0 19820+ pmaddwd mm2,[ecx+232] 19821+ /*Stall*/ 19822+ movq mm0,[eax+240] 19823+ paddd mm7,mm1 19824+ pmaddwd mm0,[ecx+240] 19825+ /*Stall*/ 19826+ movq mm1,[eax+248] 19827+ paddd mm7,mm2 19828+ pmaddwd mm1,[ecx+248] 19829+ /*Stall*/ 19830+ /*Rest iteration************************************/ 19831+ paddd mm7,mm0 19832+ /*Stall*/ 19833+ /*Stall*/ 19834+ /*Stall*/ 19835+ paddd mm7,mm1 19836+ /*Stall*/ 19837+ movq mm0,mm7 19838+ psrlq mm7,32 19839+ paddd mm0,mm7 19840+ /*Stall*/ 19841+ /*Stall*/ 19842+ /*Stall*/ 19843+ movd back,mm0 19844+ emms 19845+ } 19846+ 19847+ return(back); 19848+#endif 19849+#endif /*DB_USE_MMX*/ 19850+} 19851+ 19852+/*! 19853+ \ingroup LMLinAlg 19854+ Scalar product of 16 byte aligned 128-vectors (float). 19855+ Compile-time control: SIMD (SSE) or standard C. 19856+ */ 19857+inline float db_ScalarProduct128Aligned16_f(const float *f,const float *g) 19858+{ 19859+#ifndef DB_USE_SIMD 19860+ float back; 19861+ back=0.0; 19862+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19863+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19864+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19865+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19866+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19867+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19868+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19869+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19870+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19871+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19872+ 19873+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19874+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19875+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19876+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19877+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19878+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19879+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19880+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19881+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19882+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19883+ 19884+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19885+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19886+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19887+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19888+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19889+ back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); 19890+ 19891+ return(back); 19892+#else 19893+ float back; 19894+ 19895+ _asm 19896+ { 19897+ mov eax,f 19898+ mov ecx,g 19899+ /*First iteration************************************/ 19900+ movaps xmm0,[eax] 19901+ xorps xmm7,xmm7 /*Set mm7 to zero*/ 19902+ mulps xmm0,[ecx] 19903+ /*Stall*/ 19904+ movaps xmm1,[eax+16] 19905+ /*Stall*/ 19906+ mulps xmm1,[ecx+16] 19907+ /*Stall*/ 19908+ /*Standard iteration************************************/ 19909+ movaps xmm2,[eax+32] 19910+ addps xmm7,xmm0 19911+ mulps xmm2,[ecx+32] 19912+ /*Stall*/ 19913+ movaps xmm0,[eax+48] 19914+ addps xmm7,xmm1 19915+ mulps xmm0,[ecx+48] 19916+ /*Stall*/ 19917+ movaps xmm1,[eax+64] 19918+ addps xmm7,xmm2 19919+ mulps xmm1,[ecx+64] 19920+ /*Stall*/ 19921+ /*Standard iteration************************************/ 19922+ movaps xmm2,[eax+80] 19923+ addps xmm7,xmm0 19924+ mulps xmm2,[ecx+80] 19925+ /*Stall*/ 19926+ movaps xmm0,[eax+96] 19927+ addps xmm7,xmm1 19928+ mulps xmm0,[ecx+96] 19929+ /*Stall*/ 19930+ movaps xmm1,[eax+112] 19931+ addps xmm7,xmm2 19932+ mulps xmm1,[ecx+112] 19933+ /*Stall*/ 19934+ /*Standard iteration************************************/ 19935+ movaps xmm2,[eax+128] 19936+ addps xmm7,xmm0 19937+ mulps xmm2,[ecx+128] 19938+ /*Stall*/ 19939+ movaps xmm0,[eax+144] 19940+ addps xmm7,xmm1 19941+ mulps xmm0,[ecx+144] 19942+ /*Stall*/ 19943+ movaps xmm1,[eax+160] 19944+ addps xmm7,xmm2 19945+ mulps xmm1,[ecx+160] 19946+ /*Stall*/ 19947+ /*Standard iteration************************************/ 19948+ movaps xmm2,[eax+176] 19949+ addps xmm7,xmm0 19950+ mulps xmm2,[ecx+176] 19951+ /*Stall*/ 19952+ movaps xmm0,[eax+192] 19953+ addps xmm7,xmm1 19954+ mulps xmm0,[ecx+192] 19955+ /*Stall*/ 19956+ movaps xmm1,[eax+208] 19957+ addps xmm7,xmm2 19958+ mulps xmm1,[ecx+208] 19959+ /*Stall*/ 19960+ /*Standard iteration************************************/ 19961+ movaps xmm2,[eax+224] 19962+ addps xmm7,xmm0 19963+ mulps xmm2,[ecx+224] 19964+ /*Stall*/ 19965+ movaps xmm0,[eax+240] 19966+ addps xmm7,xmm1 19967+ mulps xmm0,[ecx+240] 19968+ /*Stall*/ 19969+ movaps xmm1,[eax+256] 19970+ addps xmm7,xmm2 19971+ mulps xmm1,[ecx+256] 19972+ /*Stall*/ 19973+ /*Standard iteration************************************/ 19974+ movaps xmm2,[eax+272] 19975+ addps xmm7,xmm0 19976+ mulps xmm2,[ecx+272] 19977+ /*Stall*/ 19978+ movaps xmm0,[eax+288] 19979+ addps xmm7,xmm1 19980+ mulps xmm0,[ecx+288] 19981+ /*Stall*/ 19982+ movaps xmm1,[eax+304] 19983+ addps xmm7,xmm2 19984+ mulps xmm1,[ecx+304] 19985+ /*Stall*/ 19986+ /*Standard iteration************************************/ 19987+ movaps xmm2,[eax+320] 19988+ addps xmm7,xmm0 19989+ mulps xmm2,[ecx+320] 19990+ /*Stall*/ 19991+ movaps xmm0,[eax+336] 19992+ addps xmm7,xmm1 19993+ mulps xmm0,[ecx+336] 19994+ /*Stall*/ 19995+ movaps xmm1,[eax+352] 19996+ addps xmm7,xmm2 19997+ mulps xmm1,[ecx+352] 19998+ /*Stall*/ 19999+ /*Standard iteration************************************/ 20000+ movaps xmm2,[eax+368] 20001+ addps xmm7,xmm0 20002+ mulps xmm2,[ecx+368] 20003+ /*Stall*/ 20004+ movaps xmm0,[eax+384] 20005+ addps xmm7,xmm1 20006+ mulps xmm0,[ecx+384] 20007+ /*Stall*/ 20008+ movaps xmm1,[eax+400] 20009+ addps xmm7,xmm2 20010+ mulps xmm1,[ecx+400] 20011+ /*Stall*/ 20012+ /*Standard iteration************************************/ 20013+ movaps xmm2,[eax+416] 20014+ addps xmm7,xmm0 20015+ mulps xmm2,[ecx+416] 20016+ /*Stall*/ 20017+ movaps xmm0,[eax+432] 20018+ addps xmm7,xmm1 20019+ mulps xmm0,[ecx+432] 20020+ /*Stall*/ 20021+ movaps xmm1,[eax+448] 20022+ addps xmm7,xmm2 20023+ mulps xmm1,[ecx+448] 20024+ /*Stall*/ 20025+ /*Standard iteration************************************/ 20026+ movaps xmm2,[eax+464] 20027+ addps xmm7,xmm0 20028+ mulps xmm2,[ecx+464] 20029+ /*Stall*/ 20030+ movaps xmm0,[eax+480] 20031+ addps xmm7,xmm1 20032+ mulps xmm0,[ecx+480] 20033+ /*Stall*/ 20034+ movaps xmm1,[eax+496] 20035+ addps xmm7,xmm2 20036+ mulps xmm1,[ecx+496] 20037+ /*Stall*/ 20038+ /*Rest iteration************************************/ 20039+ addps xmm7,xmm0 20040+ /*Stall*/ 20041+ addps xmm7,xmm1 20042+ /*Stall*/ 20043+ movaps xmm6,xmm7 20044+ /*Stall*/ 20045+ shufps xmm6,xmm6,4Eh 20046+ /*Stall*/ 20047+ addps xmm7,xmm6 20048+ /*Stall*/ 20049+ movaps xmm6,xmm7 20050+ /*Stall*/ 20051+ shufps xmm6,xmm6,11h 20052+ /*Stall*/ 20053+ addps xmm7,xmm6 20054+ /*Stall*/ 20055+ movss back,xmm7 20056+ } 20057+ 20058+ return(back); 20059+#endif /*DB_USE_SIMD*/ 20060+} 20061+ 20062+#endif /* DB_UTILITIES_LINALG */ 20063diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_poly.cpp b/benchmark/feature_stab/db_vlvm/db_utilities_poly.cpp 20064new file mode 100644 20065index 00000000..013ac726 20066--- /dev/null 20067+++ b/benchmark/feature_stab/db_vlvm/db_utilities_poly.cpp 20068@@ -0,0 +1,235 @@ 20069+/* 20070+ * Copyright (C) 2011 The Android Open Source Project 20071+ * 20072+ * Licensed under the Apache License, Version 2.0 (the "License"); 20073+ * you may not use this file except in compliance with the License. 20074+ * You may obtain a copy of the License at 20075+ * 20076+ * http://www.apache.org/licenses/LICENSE-2.0 20077+ * 20078+ * Unless required by applicable law or agreed to in writing, software 20079+ * distributed under the License is distributed on an "AS IS" BASIS, 20080+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20081+ * See the License for the specific language governing permissions and 20082+ * limitations under the License. 20083+ */ 20084+ 20085+/* $Id: db_utilities_poly.cpp,v 1.2 2010/09/03 12:00:10 bsouthall Exp $ */ 20086+ 20087+#include "db_utilities_poly.h" 20088+#include "db_utilities.h" 20089+ 20090+ 20091+ 20092+/***************************************************************** 20093+* Lean and mean begins here * 20094+*****************************************************************/ 20095+ 20096+void db_SolveCubic(double *roots,int *nr_roots,double a,double b,double c,double d) 20097+{ 20098+ double bp,bp2,cp,dp,q,r,srq; 20099+ double r2_min_q3,theta,bp_through3,theta_through3; 20100+ double cos_theta_through3,sin_theta_through3,min2_cos_theta_plu,min2_cos_theta_min; 20101+ double si_r_srq,A; 20102+ 20103+ /*For nondegenerate cubics with three roots 20104+ [24 mult 9 add 2sqrt 1acos 1cos=33flops 4func] 20105+ For nondegenerate cubics with one root 20106+ [16 mult 6 add 1sqrt 1qbrt=24flops 3func]*/ 20107+ 20108+ if(a==0.0) db_SolveQuadratic(roots,nr_roots,b,c,d); 20109+ else 20110+ { 20111+ bp=b/a; 20112+ bp2=bp*bp; 20113+ cp=c/a; 20114+ dp=d/a; 20115+ 20116+ q=(bp2-3.0*cp)/9.0; 20117+ r=(2.0*bp2*bp-9.0*bp*cp+27.0*dp)/54.0; 20118+ r2_min_q3=r*r-q*q*q; 20119+ if(r2_min_q3<0.0) 20120+ { 20121+ *nr_roots=3; 20122+ /*q has to be > 0*/ 20123+ srq=sqrt(q); 20124+ theta=acos(db_maxd(-1.0,db_mind(1.0,r/(q*srq)))); 20125+ bp_through3=bp/3.0; 20126+ theta_through3=theta/3.0; 20127+ cos_theta_through3=cos(theta_through3); 20128+ sin_theta_through3=sqrt(db_maxd(0.0,1.0-cos_theta_through3*cos_theta_through3)); 20129+ 20130+ /*cos(theta_through3+2*pi/3)=cos_theta_through3*cos(2*pi/3)-sin_theta_through3*sin(2*pi/3) 20131+ = -0.5*cos_theta_through3-sqrt(3)/2.0*sin_theta_through3 20132+ = -0.5*(cos_theta_through3+sqrt(3)*sin_theta_through3)*/ 20133+ min2_cos_theta_plu=cos_theta_through3+DB_SQRT3*sin_theta_through3; 20134+ min2_cos_theta_min=cos_theta_through3-DB_SQRT3*sin_theta_through3; 20135+ 20136+ roots[0]= -2.0*srq*cos_theta_through3-bp_through3; 20137+ roots[1]=srq*min2_cos_theta_plu-bp_through3; 20138+ roots[2]=srq*min2_cos_theta_min-bp_through3; 20139+ } 20140+ else if(r2_min_q3>0.0) 20141+ { 20142+ *nr_roots=1; 20143+ A= -db_sign(r)*db_CubRoot(db_absd(r)+sqrt(r2_min_q3)); 20144+ bp_through3=bp/3.0; 20145+ if(A!=0.0) roots[0]=A+q/A-bp_through3; 20146+ else roots[0]= -bp_through3; 20147+ } 20148+ else 20149+ { 20150+ *nr_roots=2; 20151+ bp_through3=bp/3.0; 20152+ /*q has to be >= 0*/ 20153+ si_r_srq=db_sign(r)*sqrt(q); 20154+ /*Single root*/ 20155+ roots[0]= -2.0*si_r_srq-bp_through3; 20156+ /*Double root*/ 20157+ roots[1]=si_r_srq-bp_through3; 20158+ } 20159+ } 20160+} 20161+ 20162+void db_SolveQuartic(double *roots,int *nr_roots,double a,double b,double c,double d,double e) 20163+{ 20164+ /*Normalized coefficients*/ 20165+ double c0,c1,c2,c3; 20166+ /*Temporary coefficients*/ 20167+ double c3through2,c3through4,c3c3through4_min_c2,min4_c0; 20168+ double lz,ms,ns,mn,m,n,lz_through2; 20169+ /*Cubic polynomial roots, nr of roots and coefficients*/ 20170+ double c_roots[3]; 20171+ int nr_c_roots; 20172+ double k0,k1; 20173+ /*nr additional roots from second quadratic*/ 20174+ int addroots; 20175+ 20176+ /*For nondegenerate quartics 20177+ [16mult 11add 2sqrt 1cubic 2quadratic=74flops 8funcs]*/ 20178+ 20179+ if(a==0.0) db_SolveCubic(roots,nr_roots,b,c,d,e); 20180+ else if(e==0.0) 20181+ { 20182+ db_SolveCubic(roots,nr_roots,a,b,c,d); 20183+ roots[*nr_roots]=0.0; 20184+ *nr_roots+=1; 20185+ } 20186+ else 20187+ { 20188+ /*Compute normalized coefficients*/ 20189+ c3=b/a; 20190+ c2=c/a; 20191+ c1=d/a; 20192+ c0=e/a; 20193+ /*Compute temporary coefficients*/ 20194+ c3through2=c3/2.0; 20195+ c3through4=c3/4.0; 20196+ c3c3through4_min_c2=c3*c3through4-c2; 20197+ min4_c0= -4.0*c0; 20198+ /*Compute coefficients of cubic*/ 20199+ k0=min4_c0*c3c3through4_min_c2-c1*c1; 20200+ k1=c1*c3+min4_c0; 20201+ /*k2= -c2*/ 20202+ /*k3=1.0*/ 20203+ 20204+ /*Solve it for roots*/ 20205+ db_SolveCubic(c_roots,&nr_c_roots,1.0,-c2,k1,k0); 20206+ 20207+ if(nr_c_roots>0) 20208+ { 20209+ lz=c_roots[0]; 20210+ lz_through2=lz/2.0; 20211+ ms=lz+c3c3through4_min_c2; 20212+ ns=lz_through2*lz_through2-c0; 20213+ mn=lz*c3through4-c1/2.0; 20214+ 20215+ if((ms>=0.0)&&(ns>=0.0)) 20216+ { 20217+ m=sqrt(ms); 20218+ n=sqrt(ns)*db_sign(mn); 20219+ 20220+ db_SolveQuadratic(roots,nr_roots, 20221+ 1.0,c3through2+m,lz_through2+n); 20222+ 20223+ db_SolveQuadratic(&roots[*nr_roots],&addroots, 20224+ 1.0,c3through2-m,lz_through2-n); 20225+ 20226+ *nr_roots+=addroots; 20227+ } 20228+ else *nr_roots=0; 20229+ } 20230+ else *nr_roots=0; 20231+ } 20232+} 20233+ 20234+void db_SolveQuarticForced(double *roots,int *nr_roots,double a,double b,double c,double d,double e) 20235+{ 20236+ /*Normalized coefficients*/ 20237+ double c0,c1,c2,c3; 20238+ /*Temporary coefficients*/ 20239+ double c3through2,c3through4,c3c3through4_min_c2,min4_c0; 20240+ double lz,ms,ns,mn,m,n,lz_through2; 20241+ /*Cubic polynomial roots, nr of roots and coefficients*/ 20242+ double c_roots[3]; 20243+ int nr_c_roots; 20244+ double k0,k1; 20245+ /*nr additional roots from second quadratic*/ 20246+ int addroots; 20247+ 20248+ /*For nondegenerate quartics 20249+ [16mult 11add 2sqrt 1cubic 2quadratic=74flops 8funcs]*/ 20250+ 20251+ if(a==0.0) db_SolveCubic(roots,nr_roots,b,c,d,e); 20252+ else if(e==0.0) 20253+ { 20254+ db_SolveCubic(roots,nr_roots,a,b,c,d); 20255+ roots[*nr_roots]=0.0; 20256+ *nr_roots+=1; 20257+ } 20258+ else 20259+ { 20260+ /*Compute normalized coefficients*/ 20261+ c3=b/a; 20262+ c2=c/a; 20263+ c1=d/a; 20264+ c0=e/a; 20265+ /*Compute temporary coefficients*/ 20266+ c3through2=c3/2.0; 20267+ c3through4=c3/4.0; 20268+ c3c3through4_min_c2=c3*c3through4-c2; 20269+ min4_c0= -4.0*c0; 20270+ /*Compute coefficients of cubic*/ 20271+ k0=min4_c0*c3c3through4_min_c2-c1*c1; 20272+ k1=c1*c3+min4_c0; 20273+ /*k2= -c2*/ 20274+ /*k3=1.0*/ 20275+ 20276+ /*Solve it for roots*/ 20277+ db_SolveCubic(c_roots,&nr_c_roots,1.0,-c2,k1,k0); 20278+ 20279+ if(nr_c_roots>0) 20280+ { 20281+ lz=c_roots[0]; 20282+ lz_through2=lz/2.0; 20283+ ms=lz+c3c3through4_min_c2; 20284+ ns=lz_through2*lz_through2-c0; 20285+ mn=lz*c3through4-c1/2.0; 20286+ 20287+ if(ms<0.0) ms=0.0; 20288+ if(ns<0.0) ns=0.0; 20289+ 20290+ m=sqrt(ms); 20291+ n=sqrt(ns)*db_sign(mn); 20292+ 20293+ db_SolveQuadratic(roots,nr_roots, 20294+ 1.0,c3through2+m,lz_through2+n); 20295+ 20296+ db_SolveQuadratic(&roots[*nr_roots],&addroots, 20297+ 1.0,c3through2-m,lz_through2-n); 20298+ 20299+ *nr_roots+=addroots; 20300+ } 20301+ else *nr_roots=0; 20302+ } 20303+} 20304diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_poly.h b/benchmark/feature_stab/db_vlvm/db_utilities_poly.h 20305new file mode 100644 20306index 00000000..1f878907 20307--- /dev/null 20308+++ b/benchmark/feature_stab/db_vlvm/db_utilities_poly.h 20309@@ -0,0 +1,383 @@ 20310+/* 20311+ * Copyright (C) 2011 The Android Open Source Project 20312+ * 20313+ * Licensed under the Apache License, Version 2.0 (the "License"); 20314+ * you may not use this file except in compliance with the License. 20315+ * You may obtain a copy of the License at 20316+ * 20317+ * http://www.apache.org/licenses/LICENSE-2.0 20318+ * 20319+ * Unless required by applicable law or agreed to in writing, software 20320+ * distributed under the License is distributed on an "AS IS" BASIS, 20321+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20322+ * See the License for the specific language governing permissions and 20323+ * limitations under the License. 20324+ */ 20325+ 20326+/* $Id: db_utilities_poly.h,v 1.2 2010/09/03 12:00:11 bsouthall Exp $ */ 20327+ 20328+#ifndef DB_UTILITIES_POLY 20329+#define DB_UTILITIES_POLY 20330+ 20331+#include "db_utilities.h" 20332+ 20333+ 20334+ 20335+/***************************************************************** 20336+* Lean and mean begins here * 20337+*****************************************************************/ 20338+/*! 20339+ * \defgroup LMPolynomial (LM) Polynomial utilities (solvers, arithmetic, evaluation, etc.) 20340+ */ 20341+/*\{*/ 20342+ 20343+/*! 20344+In debug mode closed form quadratic solving takes on the order of 15 microseconds 20345+while eig of the companion matrix takes about 1.1 milliseconds 20346+Speed-optimized code in release mode solves a quadratic in 0.3 microseconds on 450MHz 20347+*/ 20348+inline void db_SolveQuadratic(double *roots,int *nr_roots,double a,double b,double c) 20349+{ 20350+ double rs,srs,q; 20351+ 20352+ /*For non-degenerate quadratics 20353+ [5 mult 2 add 1 sqrt=7flops 1func]*/ 20354+ if(a==0.0) 20355+ { 20356+ if(b==0.0) *nr_roots=0; 20357+ else 20358+ { 20359+ roots[0]= -c/b; 20360+ *nr_roots=1; 20361+ } 20362+ } 20363+ else 20364+ { 20365+ rs=b*b-4.0*a*c; 20366+ if(rs>=0.0) 20367+ { 20368+ *nr_roots=2; 20369+ srs=sqrt(rs); 20370+ q= -0.5*(b+db_sign(b)*srs); 20371+ roots[0]=q/a; 20372+ /*If b is zero db_sign(b) returns 1, 20373+ so q is only zero when b=0 and c=0*/ 20374+ if(q==0.0) *nr_roots=1; 20375+ else roots[1]=c/q; 20376+ } 20377+ else *nr_roots=0; 20378+ } 20379+} 20380+ 20381+/*! 20382+In debug mode closed form cubic solving takes on the order of 45 microseconds 20383+while eig of the companion matrix takes about 1.3 milliseconds 20384+Speed-optimized code in release mode solves a cubic in 1.5 microseconds on 450MHz 20385+For a non-degenerate cubic with two roots, the first root is the single root and 20386+the second root is the double root 20387+*/ 20388+DB_API void db_SolveCubic(double *roots,int *nr_roots,double a,double b,double c,double d); 20389+/*! 20390+In debug mode closed form quartic solving takes on the order of 0.1 milliseconds 20391+while eig of the companion matrix takes about 1.5 milliseconds 20392+Speed-optimized code in release mode solves a quartic in 2.6 microseconds on 450MHz*/ 20393+DB_API void db_SolveQuartic(double *roots,int *nr_roots,double a,double b,double c,double d,double e); 20394+/*! 20395+Quartic solving where a solution is forced when splitting into quadratics, which 20396+can be good if the quartic is sometimes in fact a quadratic, such as in absolute orientation 20397+when the data is planar*/ 20398+DB_API void db_SolveQuarticForced(double *roots,int *nr_roots,double a,double b,double c,double d,double e); 20399+ 20400+inline double db_PolyEval1(const double p[2],double x) 20401+{ 20402+ return(p[0]+x*p[1]); 20403+} 20404+ 20405+inline void db_MultiplyPoly1_1(double *d,const double *a,const double *b) 20406+{ 20407+ double a0,a1; 20408+ double b0,b1; 20409+ a0=a[0];a1=a[1]; 20410+ b0=b[0];b1=b[1]; 20411+ 20412+ d[0]=a0*b0; 20413+ d[1]=a0*b1+a1*b0; 20414+ d[2]= a1*b1; 20415+} 20416+ 20417+inline void db_MultiplyPoly0_2(double *d,const double *a,const double *b) 20418+{ 20419+ double a0; 20420+ double b0,b1,b2; 20421+ a0=a[0]; 20422+ b0=b[0];b1=b[1];b2=b[2]; 20423+ 20424+ d[0]=a0*b0; 20425+ d[1]=a0*b1; 20426+ d[2]=a0*b2; 20427+} 20428+ 20429+inline void db_MultiplyPoly1_2(double *d,const double *a,const double *b) 20430+{ 20431+ double a0,a1; 20432+ double b0,b1,b2; 20433+ a0=a[0];a1=a[1]; 20434+ b0=b[0];b1=b[1];b2=b[2]; 20435+ 20436+ d[0]=a0*b0; 20437+ d[1]=a0*b1+a1*b0; 20438+ d[2]=a0*b2+a1*b1; 20439+ d[3]= a1*b2; 20440+} 20441+ 20442+ 20443+inline void db_MultiplyPoly1_3(double *d,const double *a,const double *b) 20444+{ 20445+ double a0,a1; 20446+ double b0,b1,b2,b3; 20447+ a0=a[0];a1=a[1]; 20448+ b0=b[0];b1=b[1];b2=b[2];b3=b[3]; 20449+ 20450+ d[0]=a0*b0; 20451+ d[1]=a0*b1+a1*b0; 20452+ d[2]=a0*b2+a1*b1; 20453+ d[3]=a0*b3+a1*b2; 20454+ d[4]= a1*b3; 20455+} 20456+/*! 20457+Multiply d=a*b where a is one degree and b is two degree*/ 20458+inline void db_AddPolyProduct0_1(double *d,const double *a,const double *b) 20459+{ 20460+ double a0; 20461+ double b0,b1; 20462+ a0=a[0]; 20463+ b0=b[0];b1=b[1]; 20464+ 20465+ d[0]+=a0*b0; 20466+ d[1]+=a0*b1; 20467+} 20468+inline void db_AddPolyProduct0_2(double *d,const double *a,const double *b) 20469+{ 20470+ double a0; 20471+ double b0,b1,b2; 20472+ a0=a[0]; 20473+ b0=b[0];b1=b[1];b2=b[2]; 20474+ 20475+ d[0]+=a0*b0; 20476+ d[1]+=a0*b1; 20477+ d[2]+=a0*b2; 20478+} 20479+/*! 20480+Multiply d=a*b where a is one degree and b is two degree*/ 20481+inline void db_SubtractPolyProduct0_0(double *d,const double *a,const double *b) 20482+{ 20483+ double a0; 20484+ double b0; 20485+ a0=a[0]; 20486+ b0=b[0]; 20487+ 20488+ d[0]-=a0*b0; 20489+} 20490+ 20491+inline void db_SubtractPolyProduct0_1(double *d,const double *a,const double *b) 20492+{ 20493+ double a0; 20494+ double b0,b1; 20495+ a0=a[0]; 20496+ b0=b[0];b1=b[1]; 20497+ 20498+ d[0]-=a0*b0; 20499+ d[1]-=a0*b1; 20500+} 20501+ 20502+inline void db_SubtractPolyProduct0_2(double *d,const double *a,const double *b) 20503+{ 20504+ double a0; 20505+ double b0,b1,b2; 20506+ a0=a[0]; 20507+ b0=b[0];b1=b[1];b2=b[2]; 20508+ 20509+ d[0]-=a0*b0; 20510+ d[1]-=a0*b1; 20511+ d[2]-=a0*b2; 20512+} 20513+ 20514+inline void db_SubtractPolyProduct1_3(double *d,const double *a,const double *b) 20515+{ 20516+ double a0,a1; 20517+ double b0,b1,b2,b3; 20518+ a0=a[0];a1=a[1]; 20519+ b0=b[0];b1=b[1];b2=b[2];b3=b[3]; 20520+ 20521+ d[0]-=a0*b0; 20522+ d[1]-=a0*b1+a1*b0; 20523+ d[2]-=a0*b2+a1*b1; 20524+ d[3]-=a0*b3+a1*b2; 20525+ d[4]-= a1*b3; 20526+} 20527+ 20528+inline void db_CharacteristicPolynomial4x4(double p[5],const double A[16]) 20529+{ 20530+ /*All two by two determinants of the first two rows*/ 20531+ double two01[3],two02[3],two03[3],two12[3],two13[3],two23[3]; 20532+ /*Polynomials representing third and fourth row of A*/ 20533+ double P0[2],P1[2],P2[2],P3[2]; 20534+ double P4[2],P5[2],P6[2],P7[2]; 20535+ /*All three by three determinants of the first three rows*/ 20536+ double neg_three0[4],neg_three1[4],three2[4],three3[4]; 20537+ 20538+ /*Compute 2x2 determinants*/ 20539+ two01[0]=A[0]*A[5]-A[1]*A[4]; 20540+ two01[1]= -(A[0]+A[5]); 20541+ two01[2]=1.0; 20542+ 20543+ two02[0]=A[0]*A[6]-A[2]*A[4]; 20544+ two02[1]= -A[6]; 20545+ 20546+ two03[0]=A[0]*A[7]-A[3]*A[4]; 20547+ two03[1]= -A[7]; 20548+ 20549+ two12[0]=A[1]*A[6]-A[2]*A[5]; 20550+ two12[1]=A[2]; 20551+ 20552+ two13[0]=A[1]*A[7]-A[3]*A[5]; 20553+ two13[1]=A[3]; 20554+ 20555+ two23[0]=A[2]*A[7]-A[3]*A[6]; 20556+ 20557+ P0[0]=A[8]; 20558+ P1[0]=A[9]; 20559+ P2[0]=A[10];P2[1]= -1.0; 20560+ P3[0]=A[11]; 20561+ 20562+ P4[0]=A[12]; 20563+ P5[0]=A[13]; 20564+ P6[0]=A[14]; 20565+ P7[0]=A[15];P7[1]= -1.0; 20566+ 20567+ /*Compute 3x3 determinants.Note that the highest 20568+ degree polynomial goes first and the smaller ones 20569+ are added or subtracted from it*/ 20570+ db_MultiplyPoly1_1( neg_three0,P2,two13); 20571+ db_SubtractPolyProduct0_0(neg_three0,P1,two23); 20572+ db_SubtractPolyProduct0_1(neg_three0,P3,two12); 20573+ 20574+ db_MultiplyPoly1_1( neg_three1,P2,two03); 20575+ db_SubtractPolyProduct0_1(neg_three1,P3,two02); 20576+ db_SubtractPolyProduct0_0(neg_three1,P0,two23); 20577+ 20578+ db_MultiplyPoly0_2( three2,P3,two01); 20579+ db_AddPolyProduct0_1( three2,P0,two13); 20580+ db_SubtractPolyProduct0_1(three2,P1,two03); 20581+ 20582+ db_MultiplyPoly1_2( three3,P2,two01); 20583+ db_AddPolyProduct0_1( three3,P0,two12); 20584+ db_SubtractPolyProduct0_1(three3,P1,two02); 20585+ 20586+ /*Compute 4x4 determinants*/ 20587+ db_MultiplyPoly1_3( p,P7,three3); 20588+ db_AddPolyProduct0_2( p,P4,neg_three0); 20589+ db_SubtractPolyProduct0_2(p,P5,neg_three1); 20590+ db_SubtractPolyProduct0_2(p,P6,three2); 20591+} 20592+ 20593+inline void db_RealEigenvalues4x4(double lambda[4],int *nr_roots,const double A[16],int forced=0) 20594+{ 20595+ double p[5]; 20596+ 20597+ db_CharacteristicPolynomial4x4(p,A); 20598+ if(forced) db_SolveQuarticForced(lambda,nr_roots,p[4],p[3],p[2],p[1],p[0]); 20599+ else db_SolveQuartic(lambda,nr_roots,p[4],p[3],p[2],p[1],p[0]); 20600+} 20601+ 20602+/*! 20603+Compute the unit norm eigenvector v of the matrix A corresponding 20604+to the eigenvalue lambda 20605+[96mult 60add 1sqrt=156flops 1sqrt]*/ 20606+inline void db_EigenVector4x4(double v[4],double lambda,const double A[16]) 20607+{ 20608+ double a0,a5,a10,a15; 20609+ double d01,d02,d03,d12,d13,d23; 20610+ double e01,e02,e03,e12,e13,e23; 20611+ double C[16],n0,n1,n2,n3,m; 20612+ 20613+ /*Compute diagonal 20614+ [4add=4flops]*/ 20615+ a0=A[0]-lambda; 20616+ a5=A[5]-lambda; 20617+ a10=A[10]-lambda; 20618+ a15=A[15]-lambda; 20619+ 20620+ /*Compute 2x2 determinants of rows 1,2 and 3,4 20621+ [24mult 12add=36flops]*/ 20622+ d01=a0*a5 -A[1]*A[4]; 20623+ d02=a0*A[6] -A[2]*A[4]; 20624+ d03=a0*A[7] -A[3]*A[4]; 20625+ d12=A[1]*A[6]-A[2]*a5; 20626+ d13=A[1]*A[7]-A[3]*a5; 20627+ d23=A[2]*A[7]-A[3]*A[6]; 20628+ 20629+ e01=A[8]*A[13]-A[9] *A[12]; 20630+ e02=A[8]*A[14]-a10 *A[12]; 20631+ e03=A[8]*a15 -A[11]*A[12]; 20632+ e12=A[9]*A[14]-a10 *A[13]; 20633+ e13=A[9]*a15 -A[11]*A[13]; 20634+ e23=a10 *a15 -A[11]*A[14]; 20635+ 20636+ /*Compute matrix of cofactors 20637+ [48mult 32 add=80flops*/ 20638+ C[0]= (a5 *e23-A[6]*e13+A[7]*e12); 20639+ C[1]= -(A[4]*e23-A[6]*e03+A[7]*e02); 20640+ C[2]= (A[4]*e13-a5 *e03+A[7]*e01); 20641+ C[3]= -(A[4]*e12-a5 *e02+A[6]*e01); 20642+ 20643+ C[4]= -(A[1]*e23-A[2]*e13+A[3]*e12); 20644+ C[5]= (a0 *e23-A[2]*e03+A[3]*e02); 20645+ C[6]= -(a0 *e13-A[1]*e03+A[3]*e01); 20646+ C[7]= (a0 *e12-A[1]*e02+A[2]*e01); 20647+ 20648+ C[8]= (A[13]*d23-A[14]*d13+a15 *d12); 20649+ C[9]= -(A[12]*d23-A[14]*d03+a15 *d02); 20650+ C[10]= (A[12]*d13-A[13]*d03+a15 *d01); 20651+ C[11]= -(A[12]*d12-A[13]*d02+A[14]*d01); 20652+ 20653+ C[12]= -(A[9]*d23-a10 *d13+A[11]*d12); 20654+ C[13]= (A[8]*d23-a10 *d03+A[11]*d02); 20655+ C[14]= -(A[8]*d13-A[9]*d03+A[11]*d01); 20656+ C[15]= (A[8]*d12-A[9]*d02+a10 *d01); 20657+ 20658+ /*Compute square sums of rows 20659+ [16mult 12add=28flops*/ 20660+ n0=db_sqr(C[0]) +db_sqr(C[1]) +db_sqr(C[2]) +db_sqr(C[3]); 20661+ n1=db_sqr(C[4]) +db_sqr(C[5]) +db_sqr(C[6]) +db_sqr(C[7]); 20662+ n2=db_sqr(C[8]) +db_sqr(C[9]) +db_sqr(C[10])+db_sqr(C[11]); 20663+ n3=db_sqr(C[12])+db_sqr(C[13])+db_sqr(C[14])+db_sqr(C[15]); 20664+ 20665+ /*Take the largest norm row and normalize 20666+ [4mult 1 sqrt=4flops 1sqrt]*/ 20667+ if(n0>=n1 && n0>=n2 && n0>=n3) 20668+ { 20669+ m=db_SafeReciprocal(sqrt(n0)); 20670+ db_MultiplyScalarCopy4(v,C,m); 20671+ } 20672+ else if(n1>=n2 && n1>=n3) 20673+ { 20674+ m=db_SafeReciprocal(sqrt(n1)); 20675+ db_MultiplyScalarCopy4(v,&(C[4]),m); 20676+ } 20677+ else if(n2>=n3) 20678+ { 20679+ m=db_SafeReciprocal(sqrt(n2)); 20680+ db_MultiplyScalarCopy4(v,&(C[8]),m); 20681+ } 20682+ else 20683+ { 20684+ m=db_SafeReciprocal(sqrt(n3)); 20685+ db_MultiplyScalarCopy4(v,&(C[12]),m); 20686+ } 20687+} 20688+ 20689+ 20690+ 20691+/*\}*/ 20692+#endif /* DB_UTILITIES_POLY */ 20693diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_random.h b/benchmark/feature_stab/db_vlvm/db_utilities_random.h 20694new file mode 100644 20695index 00000000..ef24039c 20696--- /dev/null 20697+++ b/benchmark/feature_stab/db_vlvm/db_utilities_random.h 20698@@ -0,0 +1,98 @@ 20699+/* 20700+ * Copyright (C) 2011 The Android Open Source Project 20701+ * 20702+ * Licensed under the Apache License, Version 2.0 (the "License"); 20703+ * you may not use this file except in compliance with the License. 20704+ * You may obtain a copy of the License at 20705+ * 20706+ * http://www.apache.org/licenses/LICENSE-2.0 20707+ * 20708+ * Unless required by applicable law or agreed to in writing, software 20709+ * distributed under the License is distributed on an "AS IS" BASIS, 20710+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20711+ * See the License for the specific language governing permissions and 20712+ * limitations under the License. 20713+ */ 20714+ 20715+/* $Id: db_utilities_random.h,v 1.1 2010/08/19 18:09:20 bsouthall Exp $ */ 20716+ 20717+#ifndef DB_UTILITIES_RANDOM 20718+#define DB_UTILITIES_RANDOM 20719+ 20720+#include "db_utilities.h" 20721+ 20722+ 20723+ 20724+/***************************************************************** 20725+* Lean and mean begins here * 20726+*****************************************************************/ 20727+/*! 20728+ * \defgroup LMRandom (LM) Random numbers, random sampling 20729+ */ 20730+/*\{*/ 20731+/*! 20732+ Random Number generator. Initialize with non-zero 20733+integer value r. A double between zero and one is 20734+returned. 20735+\param r seed 20736+\return random double 20737+*/ 20738+inline double db_QuickRandomDouble(int &r) 20739+{ 20740+ int c; 20741+ c=r/127773; 20742+ r=16807*(r-c*127773)-2836*c; 20743+ if(r<0) r+=2147483647; 20744+ return((1.0/((double)2147483647))*r); 20745+ //return (((double)rand())/(double)RAND_MAX); 20746+} 20747+ 20748+/*! 20749+Random Number generator. Initialize with non-zero 20750+integer value r. An int between and including 0 and max 20751+ \param r seed 20752+ \param max upped limit 20753+ \return random int 20754+*/ 20755+inline int db_RandomInt(int &r,int max) 20756+{ 20757+ double dtemp; 20758+ int itemp; 20759+ dtemp=db_QuickRandomDouble(r)*(max+1); 20760+ itemp=(int) dtemp; 20761+ if(itemp<=0) return(0); 20762+ if(itemp>=max) return(max); 20763+ return(itemp); 20764+} 20765+ 20766+/*! 20767+ Generate a random sample indexing into [0..pool_size-1]. 20768+ \param s sample (out) pre-allocated array of size sample_size 20769+ \param sample_size size of sample 20770+ \param pool_size upper limit on item index 20771+ \param r_seed random number generator seed 20772+ */ 20773+inline void db_RandomSample(int *s,int sample_size,int pool_size,int &r_seed) 20774+{ 20775+ int temp,temp2,i,j; 20776+ 20777+ for(i=0;i<sample_size;i++) 20778+ { 20779+ temp=db_RandomInt(r_seed,pool_size-1-i); 20780+ 20781+ for(j=0;j<i;j++) 20782+ { 20783+ if(s[j]<=temp) temp++; 20784+ else 20785+ { 20786+ /*swap*/ 20787+ temp2=temp; 20788+ temp=s[j]; 20789+ s[j]=temp2; 20790+ } 20791+ } 20792+ s[i]=temp; 20793+ } 20794+} 20795+/*\}*/ 20796+#endif /* DB_UTILITIES_RANDOM */ 20797diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_rotation.h b/benchmark/feature_stab/db_vlvm/db_utilities_rotation.h 20798new file mode 100644 20799index 00000000..7f5f937b 20800--- /dev/null 20801+++ b/benchmark/feature_stab/db_vlvm/db_utilities_rotation.h 20802@@ -0,0 +1,59 @@ 20803+/* 20804+ * Copyright (C) 2011 The Android Open Source Project 20805+ * 20806+ * Licensed under the Apache License, Version 2.0 (the "License"); 20807+ * you may not use this file except in compliance with the License. 20808+ * You may obtain a copy of the License at 20809+ * 20810+ * http://www.apache.org/licenses/LICENSE-2.0 20811+ * 20812+ * Unless required by applicable law or agreed to in writing, software 20813+ * distributed under the License is distributed on an "AS IS" BASIS, 20814+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20815+ * See the License for the specific language governing permissions and 20816+ * limitations under the License. 20817+ */ 20818+ 20819+/* $Id: db_utilities_rotation.h,v 1.2 2010/09/03 12:00:11 bsouthall Exp $ */ 20820+ 20821+#ifndef DB_UTILITIES_ROTATION 20822+#define DB_UTILITIES_ROTATION 20823+ 20824+#include "db_utilities.h" 20825+ 20826+ 20827+ 20828+/***************************************************************** 20829+* Lean and mean begins here * 20830+*****************************************************************/ 20831+/*! 20832+ * \defgroup LMRotation (LM) Rotation Utilities (quaternions, orthonormal) 20833+ */ 20834+/*\{*/ 20835+/*! 20836+ Takes a unit quaternion and gives its corresponding rotation matrix. 20837+ \param R rotation matrix (out) 20838+ \param q quaternion 20839+ */ 20840+inline void db_QuaternionToRotation(double R[9],const double q[4]) 20841+{ 20842+ double q0q0,q0qx,q0qy,q0qz,qxqx,qxqy,qxqz,qyqy,qyqz,qzqz; 20843+ 20844+ q0q0=q[0]*q[0]; 20845+ q0qx=q[0]*q[1]; 20846+ q0qy=q[0]*q[2]; 20847+ q0qz=q[0]*q[3]; 20848+ qxqx=q[1]*q[1]; 20849+ qxqy=q[1]*q[2]; 20850+ qxqz=q[1]*q[3]; 20851+ qyqy=q[2]*q[2]; 20852+ qyqz=q[2]*q[3]; 20853+ qzqz=q[3]*q[3]; 20854+ 20855+ R[0]=q0q0+qxqx-qyqy-qzqz; R[1]=2.0*(qxqy-q0qz); R[2]=2.0*(qxqz+q0qy); 20856+ R[3]=2.0*(qxqy+q0qz); R[4]=q0q0-qxqx+qyqy-qzqz; R[5]=2.0*(qyqz-q0qx); 20857+ R[6]=2.0*(qxqz-q0qy); R[7]=2.0*(qyqz+q0qx); R[8]=q0q0-qxqx-qyqy+qzqz; 20858+} 20859+ 20860+/*\}*/ 20861+#endif /* DB_UTILITIES_ROTATION */ 20862diff --git a/benchmark/feature_stab/doc/Readme.txt b/benchmark/feature_stab/doc/Readme.txt 20863new file mode 100644 20864index 00000000..fcd7c38c 20865--- /dev/null 20866+++ b/benchmark/feature_stab/doc/Readme.txt 20867@@ -0,0 +1,3 @@ 20868+To generate the html docs, execute 20869+doxygen dbreg_API_doxyfile 20870+ 20871diff --git a/benchmark/feature_stab/doc/dbreg_API_doxyfile b/benchmark/feature_stab/doc/dbreg_API_doxyfile 20872new file mode 100755 20873index 00000000..dc61a9c0 20874--- /dev/null 20875+++ b/benchmark/feature_stab/doc/dbreg_API_doxyfile 20876@@ -0,0 +1,1557 @@ 20877+# Doxyfile 1.6.1 20878+ 20879+# This file describes the settings to be used by the documentation system 20880+# doxygen (www.doxygen.org) for a project 20881+# 20882+# All text after a hash (#) is considered a comment and will be ignored 20883+# The format is: 20884+# TAG = value [value, ...] 20885+# For lists items can also be appended using: 20886+# TAG += value [value, ...] 20887+# Values that contain spaces should be placed between quotes (" ") 20888+ 20889+#--------------------------------------------------------------------------- 20890+# Project related configuration options 20891+#--------------------------------------------------------------------------- 20892+ 20893+# This tag specifies the encoding used for all characters in the config file 20894+# that follow. The default is UTF-8 which is also the encoding used for all 20895+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 20896+# iconv built into libc) for the transcoding. See 20897+# http://www.gnu.org/software/libiconv for the list of possible encodings. 20898+ 20899+DOXYFILE_ENCODING = UTF-8 20900+ 20901+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 20902+# by quotes) that should identify the project. 20903+ 20904+PROJECT_NAME = 20905+ 20906+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 20907+# This could be handy for archiving the generated documentation or 20908+# if some version control system is used. 20909+ 20910+PROJECT_NUMBER = 20911+ 20912+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 20913+# base path where the generated documentation will be put. 20914+# If a relative path is entered, it will be relative to the location 20915+# where doxygen was started. If left blank the current directory will be used. 20916+ 20917+OUTPUT_DIRECTORY = . 20918+ 20919+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 20920+# 4096 sub-directories (in 2 levels) under the output directory of each output 20921+# format and will distribute the generated files over these directories. 20922+# Enabling this option can be useful when feeding doxygen a huge amount of 20923+# source files, where putting all generated files in the same directory would 20924+# otherwise cause performance problems for the file system. 20925+ 20926+CREATE_SUBDIRS = NO 20927+ 20928+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 20929+# documentation generated by doxygen is written. Doxygen will use this 20930+# information to generate all constant output in the proper language. 20931+# The default language is English, other supported languages are: 20932+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 20933+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, 20934+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English 20935+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, 20936+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, 20937+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. 20938+ 20939+OUTPUT_LANGUAGE = English 20940+ 20941+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 20942+# include brief member descriptions after the members that are listed in 20943+# the file and class documentation (similar to JavaDoc). 20944+# Set to NO to disable this. 20945+ 20946+BRIEF_MEMBER_DESC = YES 20947+ 20948+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 20949+# the brief description of a member or function before the detailed description. 20950+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 20951+# brief descriptions will be completely suppressed. 20952+ 20953+REPEAT_BRIEF = YES 20954+ 20955+# This tag implements a quasi-intelligent brief description abbreviator 20956+# that is used to form the text in various listings. Each string 20957+# in this list, if found as the leading text of the brief description, will be 20958+# stripped from the text and the result after processing the whole list, is 20959+# used as the annotated text. Otherwise, the brief description is used as-is. 20960+# If left blank, the following values are used ("$name" is automatically 20961+# replaced with the name of the entity): "The $name class" "The $name widget" 20962+# "The $name file" "is" "provides" "specifies" "contains" 20963+# "represents" "a" "an" "the" 20964+ 20965+ABBREVIATE_BRIEF = "The $name class" \ 20966+ "The $name widget" \ 20967+ "The $name file" \ 20968+ is \ 20969+ provides \ 20970+ specifies \ 20971+ contains \ 20972+ represents \ 20973+ a \ 20974+ an \ 20975+ the 20976+ 20977+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 20978+# Doxygen will generate a detailed section even if there is only a brief 20979+# description. 20980+ 20981+ALWAYS_DETAILED_SEC = NO 20982+ 20983+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 20984+# inherited members of a class in the documentation of that class as if those 20985+# members were ordinary class members. Constructors, destructors and assignment 20986+# operators of the base classes will not be shown. 20987+ 20988+INLINE_INHERITED_MEMB = NO 20989+ 20990+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 20991+# path before files name in the file list and in the header files. If set 20992+# to NO the shortest path that makes the file name unique will be used. 20993+ 20994+FULL_PATH_NAMES = YES 20995+ 20996+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 20997+# can be used to strip a user-defined part of the path. Stripping is 20998+# only done if one of the specified strings matches the left-hand part of 20999+# the path. The tag can be used to show relative paths in the file list. 21000+# If left blank the directory from which doxygen is run is used as the 21001+# path to strip. 21002+ 21003+STRIP_FROM_PATH = /Users/dimitri/doxygen/mail/1.5.7/doxywizard/ 21004+ 21005+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 21006+# the path mentioned in the documentation of a class, which tells 21007+# the reader which header file to include in order to use a class. 21008+# If left blank only the name of the header file containing the class 21009+# definition is used. Otherwise one should specify the include paths that 21010+# are normally passed to the compiler using the -I flag. 21011+ 21012+STRIP_FROM_INC_PATH = 21013+ 21014+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 21015+# (but less readable) file names. This can be useful is your file systems 21016+# doesn't support long names like on DOS, Mac, or CD-ROM. 21017+ 21018+SHORT_NAMES = NO 21019+ 21020+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 21021+# will interpret the first line (until the first dot) of a JavaDoc-style 21022+# comment as the brief description. If set to NO, the JavaDoc 21023+# comments will behave just like regular Qt-style comments 21024+# (thus requiring an explicit @brief command for a brief description.) 21025+ 21026+JAVADOC_AUTOBRIEF = NO 21027+ 21028+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 21029+# interpret the first line (until the first dot) of a Qt-style 21030+# comment as the brief description. If set to NO, the comments 21031+# will behave just like regular Qt-style comments (thus requiring 21032+# an explicit \brief command for a brief description.) 21033+ 21034+QT_AUTOBRIEF = NO 21035+ 21036+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 21037+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 21038+# comments) as a brief description. This used to be the default behaviour. 21039+# The new default is to treat a multi-line C++ comment block as a detailed 21040+# description. Set this tag to YES if you prefer the old behaviour instead. 21041+ 21042+MULTILINE_CPP_IS_BRIEF = NO 21043+ 21044+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 21045+# member inherits the documentation from any documented member that it 21046+# re-implements. 21047+ 21048+INHERIT_DOCS = YES 21049+ 21050+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 21051+# a new page for each member. If set to NO, the documentation of a member will 21052+# be part of the file/class/namespace that contains it. 21053+ 21054+SEPARATE_MEMBER_PAGES = NO 21055+ 21056+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 21057+# Doxygen uses this value to replace tabs by spaces in code fragments. 21058+ 21059+TAB_SIZE = 8 21060+ 21061+# This tag can be used to specify a number of aliases that acts 21062+# as commands in the documentation. An alias has the form "name=value". 21063+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 21064+# put the command \sideeffect (or @sideeffect) in the documentation, which 21065+# will result in a user-defined paragraph with heading "Side Effects:". 21066+# You can put \n's in the value part of an alias to insert newlines. 21067+ 21068+ALIASES = 21069+ 21070+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 21071+# sources only. Doxygen will then generate output that is more tailored for C. 21072+# For instance, some of the names that are used will be different. The list 21073+# of all members will be omitted, etc. 21074+ 21075+OPTIMIZE_OUTPUT_FOR_C = NO 21076+ 21077+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 21078+# sources only. Doxygen will then generate output that is more tailored for 21079+# Java. For instance, namespaces will be presented as packages, qualified 21080+# scopes will look different, etc. 21081+ 21082+OPTIMIZE_OUTPUT_JAVA = NO 21083+ 21084+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 21085+# sources only. Doxygen will then generate output that is more tailored for 21086+# Fortran. 21087+ 21088+OPTIMIZE_FOR_FORTRAN = NO 21089+ 21090+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 21091+# sources. Doxygen will then generate output that is tailored for 21092+# VHDL. 21093+ 21094+OPTIMIZE_OUTPUT_VHDL = NO 21095+ 21096+# Doxygen selects the parser to use depending on the extension of the files it parses. 21097+# With this tag you can assign which parser to use for a given extension. 21098+# Doxygen has a built-in mapping, but you can override or extend it using this tag. 21099+# The format is ext=language, where ext is a file extension, and language is one of 21100+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, 21101+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat 21102+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), 21103+# use: inc=Fortran f=C. Note that for custom extensions you also need to set 21104+# FILE_PATTERNS otherwise the files are not read by doxygen. 21105+ 21106+EXTENSION_MAPPING = 21107+ 21108+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 21109+# to include (a tag file for) the STL sources as input, then you should 21110+# set this tag to YES in order to let doxygen match functions declarations and 21111+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 21112+# func(std::string) {}). This also make the inheritance and collaboration 21113+# diagrams that involve STL classes more complete and accurate. 21114+ 21115+BUILTIN_STL_SUPPORT = NO 21116+ 21117+# If you use Microsoft's C++/CLI language, you should set this option to YES to 21118+# enable parsing support. 21119+ 21120+CPP_CLI_SUPPORT = NO 21121+ 21122+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 21123+# Doxygen will parse them like normal C++ but will assume all classes use public 21124+# instead of private inheritance when no explicit protection keyword is present. 21125+ 21126+SIP_SUPPORT = NO 21127+ 21128+# For Microsoft's IDL there are propget and propput attributes to indicate getter 21129+# and setter methods for a property. Setting this option to YES (the default) 21130+# will make doxygen to replace the get and set methods by a property in the 21131+# documentation. This will only work if the methods are indeed getting or 21132+# setting a simple type. If this is not the case, or you want to show the 21133+# methods anyway, you should set this option to NO. 21134+ 21135+IDL_PROPERTY_SUPPORT = YES 21136+ 21137+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 21138+# tag is set to YES, then doxygen will reuse the documentation of the first 21139+# member in the group (if any) for the other members of the group. By default 21140+# all members of a group must be documented explicitly. 21141+ 21142+DISTRIBUTE_GROUP_DOC = NO 21143+ 21144+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 21145+# the same type (for instance a group of public functions) to be put as a 21146+# subgroup of that type (e.g. under the Public Functions section). Set it to 21147+# NO to prevent subgrouping. Alternatively, this can be done per class using 21148+# the \nosubgrouping command. 21149+ 21150+SUBGROUPING = YES 21151+ 21152+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 21153+# is documented as struct, union, or enum with the name of the typedef. So 21154+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 21155+# with name TypeT. When disabled the typedef will appear as a member of a file, 21156+# namespace, or class. And the struct will be named TypeS. This can typically 21157+# be useful for C code in case the coding convention dictates that all compound 21158+# types are typedef'ed and only the typedef is referenced, never the tag name. 21159+ 21160+TYPEDEF_HIDES_STRUCT = NO 21161+ 21162+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 21163+# determine which symbols to keep in memory and which to flush to disk. 21164+# When the cache is full, less often used symbols will be written to disk. 21165+# For small to medium size projects (<1000 input files) the default value is 21166+# probably good enough. For larger projects a too small cache size can cause 21167+# doxygen to be busy swapping symbols to and from disk most of the time 21168+# causing a significant performance penality. 21169+# If the system has enough physical memory increasing the cache will improve the 21170+# performance by keeping more symbols in memory. Note that the value works on 21171+# a logarithmic scale so increasing the size by one will rougly double the 21172+# memory usage. The cache size is given by this formula: 21173+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 21174+# corresponding to a cache size of 2^16 = 65536 symbols 21175+ 21176+SYMBOL_CACHE_SIZE = 0 21177+ 21178+#--------------------------------------------------------------------------- 21179+# Build related configuration options 21180+#--------------------------------------------------------------------------- 21181+ 21182+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 21183+# documentation are documented, even if no documentation was available. 21184+# Private class members and static file members will be hidden unless 21185+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES 21186+ 21187+EXTRACT_ALL = NO 21188+ 21189+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 21190+# will be included in the documentation. 21191+ 21192+EXTRACT_PRIVATE = NO 21193+ 21194+# If the EXTRACT_STATIC tag is set to YES all static members of a file 21195+# will be included in the documentation. 21196+ 21197+EXTRACT_STATIC = NO 21198+ 21199+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 21200+# defined locally in source files will be included in the documentation. 21201+# If set to NO only classes defined in header files are included. 21202+ 21203+EXTRACT_LOCAL_CLASSES = YES 21204+ 21205+# This flag is only useful for Objective-C code. When set to YES local 21206+# methods, which are defined in the implementation section but not in 21207+# the interface are included in the documentation. 21208+# If set to NO (the default) only methods in the interface are included. 21209+ 21210+EXTRACT_LOCAL_METHODS = NO 21211+ 21212+# If this flag is set to YES, the members of anonymous namespaces will be 21213+# extracted and appear in the documentation as a namespace called 21214+# 'anonymous_namespace{file}', where file will be replaced with the base 21215+# name of the file that contains the anonymous namespace. By default 21216+# anonymous namespace are hidden. 21217+ 21218+EXTRACT_ANON_NSPACES = NO 21219+ 21220+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 21221+# undocumented members of documented classes, files or namespaces. 21222+# If set to NO (the default) these members will be included in the 21223+# various overviews, but no documentation section is generated. 21224+# This option has no effect if EXTRACT_ALL is enabled. 21225+ 21226+HIDE_UNDOC_MEMBERS = NO 21227+ 21228+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 21229+# undocumented classes that are normally visible in the class hierarchy. 21230+# If set to NO (the default) these classes will be included in the various 21231+# overviews. This option has no effect if EXTRACT_ALL is enabled. 21232+ 21233+HIDE_UNDOC_CLASSES = NO 21234+ 21235+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 21236+# friend (class|struct|union) declarations. 21237+# If set to NO (the default) these declarations will be included in the 21238+# documentation. 21239+ 21240+HIDE_FRIEND_COMPOUNDS = NO 21241+ 21242+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 21243+# documentation blocks found inside the body of a function. 21244+# If set to NO (the default) these blocks will be appended to the 21245+# function's detailed documentation block. 21246+ 21247+HIDE_IN_BODY_DOCS = NO 21248+ 21249+# The INTERNAL_DOCS tag determines if documentation 21250+# that is typed after a \internal command is included. If the tag is set 21251+# to NO (the default) then the documentation will be excluded. 21252+# Set it to YES to include the internal documentation. 21253+ 21254+INTERNAL_DOCS = NO 21255+ 21256+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 21257+# file names in lower-case letters. If set to YES upper-case letters are also 21258+# allowed. This is useful if you have classes or files whose names only differ 21259+# in case and if your file system supports case sensitive file names. Windows 21260+# and Mac users are advised to set this option to NO. 21261+ 21262+CASE_SENSE_NAMES = NO 21263+ 21264+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 21265+# will show members with their full class and namespace scopes in the 21266+# documentation. If set to YES the scope will be hidden. 21267+ 21268+HIDE_SCOPE_NAMES = NO 21269+ 21270+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 21271+# will put a list of the files that are included by a file in the documentation 21272+# of that file. 21273+ 21274+SHOW_INCLUDE_FILES = YES 21275+ 21276+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 21277+# is inserted in the documentation for inline members. 21278+ 21279+INLINE_INFO = YES 21280+ 21281+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 21282+# will sort the (detailed) documentation of file and class members 21283+# alphabetically by member name. If set to NO the members will appear in 21284+# declaration order. 21285+ 21286+SORT_MEMBER_DOCS = YES 21287+ 21288+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 21289+# brief documentation of file, namespace and class members alphabetically 21290+# by member name. If set to NO (the default) the members will appear in 21291+# declaration order. 21292+ 21293+SORT_BRIEF_DOCS = NO 21294+ 21295+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen 21296+# will sort the (brief and detailed) documentation of class members so that 21297+# constructors and destructors are listed first. If set to NO (the default) 21298+# the constructors will appear in the respective orders defined by 21299+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. 21300+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO 21301+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. 21302+ 21303+SORT_MEMBERS_CTORS_1ST = NO 21304+ 21305+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 21306+# hierarchy of group names into alphabetical order. If set to NO (the default) 21307+# the group names will appear in their defined order. 21308+ 21309+SORT_GROUP_NAMES = NO 21310+ 21311+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 21312+# sorted by fully-qualified names, including namespaces. If set to 21313+# NO (the default), the class list will be sorted only by class name, 21314+# not including the namespace part. 21315+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 21316+# Note: This option applies only to the class list, not to the 21317+# alphabetical list. 21318+ 21319+SORT_BY_SCOPE_NAME = NO 21320+ 21321+# The GENERATE_TODOLIST tag can be used to enable (YES) or 21322+# disable (NO) the todo list. This list is created by putting \todo 21323+# commands in the documentation. 21324+ 21325+GENERATE_TODOLIST = YES 21326+ 21327+# The GENERATE_TESTLIST tag can be used to enable (YES) or 21328+# disable (NO) the test list. This list is created by putting \test 21329+# commands in the documentation. 21330+ 21331+GENERATE_TESTLIST = YES 21332+ 21333+# The GENERATE_BUGLIST tag can be used to enable (YES) or 21334+# disable (NO) the bug list. This list is created by putting \bug 21335+# commands in the documentation. 21336+ 21337+GENERATE_BUGLIST = YES 21338+ 21339+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 21340+# disable (NO) the deprecated list. This list is created by putting 21341+# \deprecated commands in the documentation. 21342+ 21343+GENERATE_DEPRECATEDLIST= YES 21344+ 21345+# The ENABLED_SECTIONS tag can be used to enable conditional 21346+# documentation sections, marked by \if sectionname ... \endif. 21347+ 21348+ENABLED_SECTIONS = 21349+ 21350+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 21351+# the initial value of a variable or define consists of for it to appear in 21352+# the documentation. If the initializer consists of more lines than specified 21353+# here it will be hidden. Use a value of 0 to hide initializers completely. 21354+# The appearance of the initializer of individual variables and defines in the 21355+# documentation can be controlled using \showinitializer or \hideinitializer 21356+# command in the documentation regardless of this setting. 21357+ 21358+MAX_INITIALIZER_LINES = 30 21359+ 21360+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 21361+# at the bottom of the documentation of classes and structs. If set to YES the 21362+# list will mention the files that were used to generate the documentation. 21363+ 21364+SHOW_USED_FILES = YES 21365+ 21366+# If the sources in your project are distributed over multiple directories 21367+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 21368+# in the documentation. The default is NO. 21369+ 21370+SHOW_DIRECTORIES = NO 21371+ 21372+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 21373+# This will remove the Files entry from the Quick Index and from the 21374+# Folder Tree View (if specified). The default is YES. 21375+ 21376+SHOW_FILES = YES 21377+ 21378+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 21379+# Namespaces page. This will remove the Namespaces entry from the Quick Index 21380+# and from the Folder Tree View (if specified). The default is YES. 21381+ 21382+SHOW_NAMESPACES = YES 21383+ 21384+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 21385+# doxygen should invoke to get the current version for each file (typically from 21386+# the version control system). Doxygen will invoke the program by executing (via 21387+# popen()) the command <command> <input-file>, where <command> is the value of 21388+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 21389+# provided by doxygen. Whatever the program writes to standard output 21390+# is used as the file version. See the manual for examples. 21391+ 21392+FILE_VERSION_FILTER = 21393+ 21394+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by 21395+# doxygen. The layout file controls the global structure of the generated output files 21396+# in an output format independent way. The create the layout file that represents 21397+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a 21398+# file name after the option, if omitted DoxygenLayout.xml will be used as the name 21399+# of the layout file. 21400+ 21401+LAYOUT_FILE = 21402+ 21403+#--------------------------------------------------------------------------- 21404+# configuration options related to warning and progress messages 21405+#--------------------------------------------------------------------------- 21406+ 21407+# The QUIET tag can be used to turn on/off the messages that are generated 21408+# by doxygen. Possible values are YES and NO. If left blank NO is used. 21409+ 21410+QUIET = NO 21411+ 21412+# The WARNINGS tag can be used to turn on/off the warning messages that are 21413+# generated by doxygen. Possible values are YES and NO. If left blank 21414+# NO is used. 21415+ 21416+WARNINGS = YES 21417+ 21418+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 21419+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 21420+# automatically be disabled. 21421+ 21422+WARN_IF_UNDOCUMENTED = YES 21423+ 21424+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 21425+# potential errors in the documentation, such as not documenting some 21426+# parameters in a documented function, or documenting parameters that 21427+# don't exist or using markup commands wrongly. 21428+ 21429+WARN_IF_DOC_ERROR = YES 21430+ 21431+# This WARN_NO_PARAMDOC option can be abled to get warnings for 21432+# functions that are documented, but have no documentation for their parameters 21433+# or return value. If set to NO (the default) doxygen will only warn about 21434+# wrong or incomplete parameter documentation, but not about the absence of 21435+# documentation. 21436+ 21437+WARN_NO_PARAMDOC = NO 21438+ 21439+# The WARN_FORMAT tag determines the format of the warning messages that 21440+# doxygen can produce. The string should contain the $file, $line, and $text 21441+# tags, which will be replaced by the file and line number from which the 21442+# warning originated and the warning text. Optionally the format may contain 21443+# $version, which will be replaced by the version of the file (if it could 21444+# be obtained via FILE_VERSION_FILTER) 21445+ 21446+WARN_FORMAT = "$file:$line: $text" 21447+ 21448+# The WARN_LOGFILE tag can be used to specify a file to which warning 21449+# and error messages should be written. If left blank the output is written 21450+# to stderr. 21451+ 21452+WARN_LOGFILE = 21453+ 21454+#--------------------------------------------------------------------------- 21455+# configuration options related to the input files 21456+#--------------------------------------------------------------------------- 21457+ 21458+# The INPUT tag can be used to specify the files and/or directories that contain 21459+# documented source files. You may enter file names like "myfile.cpp" or 21460+# directories like "/usr/src/myproject". Separate the files or directories 21461+# with spaces. 21462+ 21463+INPUT = ../src/dbreg/dbreg.h 21464+ 21465+# This tag can be used to specify the character encoding of the source files 21466+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 21467+# also the default input encoding. Doxygen uses libiconv (or the iconv built 21468+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 21469+# the list of possible encodings. 21470+ 21471+INPUT_ENCODING = UTF-8 21472+ 21473+# If the value of the INPUT tag contains directories, you can use the 21474+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 21475+# and *.h) to filter out the source-files in the directories. If left 21476+# blank the following patterns are tested: 21477+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 21478+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 21479+ 21480+FILE_PATTERNS = *.c \ 21481+ *.cc \ 21482+ *.cxx \ 21483+ *.cpp \ 21484+ *.c++ \ 21485+ *.d \ 21486+ *.java \ 21487+ *.ii \ 21488+ *.ixx \ 21489+ *.ipp \ 21490+ *.i++ \ 21491+ *.inl \ 21492+ *.h \ 21493+ *.hh \ 21494+ *.hxx \ 21495+ *.hpp \ 21496+ *.h++ \ 21497+ *.idl \ 21498+ *.odl \ 21499+ *.cs \ 21500+ *.php \ 21501+ *.php3 \ 21502+ *.inc \ 21503+ *.m \ 21504+ *.mm \ 21505+ *.dox \ 21506+ *.py \ 21507+ *.f90 \ 21508+ *.f \ 21509+ *.vhd \ 21510+ *.vhdl 21511+ 21512+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 21513+# should be searched for input files as well. Possible values are YES and NO. 21514+# If left blank NO is used. 21515+ 21516+RECURSIVE = NO 21517+ 21518+# The EXCLUDE tag can be used to specify files and/or directories that should 21519+# excluded from the INPUT source files. This way you can easily exclude a 21520+# subdirectory from a directory tree whose root is specified with the INPUT tag. 21521+ 21522+EXCLUDE = 21523+ 21524+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 21525+# directories that are symbolic links (a Unix filesystem feature) are excluded 21526+# from the input. 21527+ 21528+EXCLUDE_SYMLINKS = NO 21529+ 21530+# If the value of the INPUT tag contains directories, you can use the 21531+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 21532+# certain files from those directories. Note that the wildcards are matched 21533+# against the file with absolute path, so to exclude all test directories 21534+# for example use the pattern */test/* 21535+ 21536+EXCLUDE_PATTERNS = 21537+ 21538+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 21539+# (namespaces, classes, functions, etc.) that should be excluded from the 21540+# output. The symbol name can be a fully qualified name, a word, or if the 21541+# wildcard * is used, a substring. Examples: ANamespace, AClass, 21542+# AClass::ANamespace, ANamespace::*Test 21543+ 21544+EXCLUDE_SYMBOLS = 21545+ 21546+# The EXAMPLE_PATH tag can be used to specify one or more files or 21547+# directories that contain example code fragments that are included (see 21548+# the \include command). 21549+ 21550+EXAMPLE_PATH = 21551+ 21552+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 21553+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 21554+# and *.h) to filter out the source-files in the directories. If left 21555+# blank all files are included. 21556+ 21557+EXAMPLE_PATTERNS = * 21558+ 21559+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 21560+# searched for input files to be used with the \include or \dontinclude 21561+# commands irrespective of the value of the RECURSIVE tag. 21562+# Possible values are YES and NO. If left blank NO is used. 21563+ 21564+EXAMPLE_RECURSIVE = NO 21565+ 21566+# The IMAGE_PATH tag can be used to specify one or more files or 21567+# directories that contain image that are included in the documentation (see 21568+# the \image command). 21569+ 21570+IMAGE_PATH = 21571+ 21572+# The INPUT_FILTER tag can be used to specify a program that doxygen should 21573+# invoke to filter for each input file. Doxygen will invoke the filter program 21574+# by executing (via popen()) the command <filter> <input-file>, where <filter> 21575+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 21576+# input file. Doxygen will then use the output that the filter program writes 21577+# to standard output. If FILTER_PATTERNS is specified, this tag will be 21578+# ignored. 21579+ 21580+INPUT_FILTER = 21581+ 21582+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 21583+# basis. Doxygen will compare the file name with each pattern and apply the 21584+# filter if there is a match. The filters are a list of the form: 21585+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 21586+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 21587+# is applied to all files. 21588+ 21589+FILTER_PATTERNS = 21590+ 21591+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 21592+# INPUT_FILTER) will be used to filter the input files when producing source 21593+# files to browse (i.e. when SOURCE_BROWSER is set to YES). 21594+ 21595+FILTER_SOURCE_FILES = NO 21596+ 21597+#--------------------------------------------------------------------------- 21598+# configuration options related to source browsing 21599+#--------------------------------------------------------------------------- 21600+ 21601+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 21602+# be generated. Documented entities will be cross-referenced with these sources. 21603+# Note: To get rid of all source code in the generated output, make sure also 21604+# VERBATIM_HEADERS is set to NO. 21605+ 21606+SOURCE_BROWSER = NO 21607+ 21608+# Setting the INLINE_SOURCES tag to YES will include the body 21609+# of functions and classes directly in the documentation. 21610+ 21611+INLINE_SOURCES = NO 21612+ 21613+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 21614+# doxygen to hide any special comment blocks from generated source code 21615+# fragments. Normal C and C++ comments will always remain visible. 21616+ 21617+STRIP_CODE_COMMENTS = YES 21618+ 21619+# If the REFERENCED_BY_RELATION tag is set to YES 21620+# then for each documented function all documented 21621+# functions referencing it will be listed. 21622+ 21623+REFERENCED_BY_RELATION = NO 21624+ 21625+# If the REFERENCES_RELATION tag is set to YES 21626+# then for each documented function all documented entities 21627+# called/used by that function will be listed. 21628+ 21629+REFERENCES_RELATION = NO 21630+ 21631+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 21632+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 21633+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 21634+# link to the source code. Otherwise they will link to the documentation. 21635+ 21636+REFERENCES_LINK_SOURCE = YES 21637+ 21638+# If the USE_HTAGS tag is set to YES then the references to source code 21639+# will point to the HTML generated by the htags(1) tool instead of doxygen 21640+# built-in source browser. The htags tool is part of GNU's global source 21641+# tagging system (see http://www.gnu.org/software/global/global.html). You 21642+# will need version 4.8.6 or higher. 21643+ 21644+USE_HTAGS = NO 21645+ 21646+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 21647+# will generate a verbatim copy of the header file for each class for 21648+# which an include is specified. Set to NO to disable this. 21649+ 21650+VERBATIM_HEADERS = YES 21651+ 21652+#--------------------------------------------------------------------------- 21653+# configuration options related to the alphabetical class index 21654+#--------------------------------------------------------------------------- 21655+ 21656+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 21657+# of all compounds will be generated. Enable this if the project 21658+# contains a lot of classes, structs, unions or interfaces. 21659+ 21660+ALPHABETICAL_INDEX = NO 21661+ 21662+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 21663+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 21664+# in which this list will be split (can be a number in the range [1..20]) 21665+ 21666+COLS_IN_ALPHA_INDEX = 5 21667+ 21668+# In case all classes in a project start with a common prefix, all 21669+# classes will be put under the same header in the alphabetical index. 21670+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 21671+# should be ignored while generating the index headers. 21672+ 21673+IGNORE_PREFIX = 21674+ 21675+#--------------------------------------------------------------------------- 21676+# configuration options related to the HTML output 21677+#--------------------------------------------------------------------------- 21678+ 21679+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 21680+# generate HTML output. 21681+ 21682+GENERATE_HTML = YES 21683+ 21684+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 21685+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 21686+# put in front of it. If left blank `html' will be used as the default path. 21687+ 21688+HTML_OUTPUT = html 21689+ 21690+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 21691+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 21692+# doxygen will generate files with .html extension. 21693+ 21694+HTML_FILE_EXTENSION = .html 21695+ 21696+# The HTML_HEADER tag can be used to specify a personal HTML header for 21697+# each generated HTML page. If it is left blank doxygen will generate a 21698+# standard header. 21699+ 21700+HTML_HEADER = 21701+ 21702+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 21703+# each generated HTML page. If it is left blank doxygen will generate a 21704+# standard footer. 21705+ 21706+HTML_FOOTER = 21707+ 21708+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 21709+# style sheet that is used by each HTML page. It can be used to 21710+# fine-tune the look of the HTML output. If the tag is left blank doxygen 21711+# will generate a default style sheet. Note that doxygen will try to copy 21712+# the style sheet file to the HTML output directory, so don't put your own 21713+# stylesheet in the HTML output directory as well, or it will be erased! 21714+ 21715+HTML_STYLESHEET = 21716+ 21717+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 21718+# files or namespaces will be aligned in HTML using tables. If set to 21719+# NO a bullet list will be used. 21720+ 21721+HTML_ALIGN_MEMBERS = YES 21722+ 21723+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 21724+# documentation will contain sections that can be hidden and shown after the 21725+# page has loaded. For this to work a browser that supports 21726+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 21727+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). 21728+ 21729+HTML_DYNAMIC_SECTIONS = NO 21730+ 21731+# If the GENERATE_DOCSET tag is set to YES, additional index files 21732+# will be generated that can be used as input for Apple's Xcode 3 21733+# integrated development environment, introduced with OSX 10.5 (Leopard). 21734+# To create a documentation set, doxygen will generate a Makefile in the 21735+# HTML output directory. Running make will produce the docset in that 21736+# directory and running "make install" will install the docset in 21737+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 21738+# it at startup. 21739+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. 21740+ 21741+GENERATE_DOCSET = NO 21742+ 21743+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 21744+# feed. A documentation feed provides an umbrella under which multiple 21745+# documentation sets from a single provider (such as a company or product suite) 21746+# can be grouped. 21747+ 21748+DOCSET_FEEDNAME = "Doxygen generated docs" 21749+ 21750+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 21751+# should uniquely identify the documentation set bundle. This should be a 21752+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 21753+# will append .docset to the name. 21754+ 21755+DOCSET_BUNDLE_ID = org.doxygen.Project 21756+ 21757+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 21758+# will be generated that can be used as input for tools like the 21759+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 21760+# of the generated HTML documentation. 21761+ 21762+GENERATE_HTMLHELP = NO 21763+ 21764+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 21765+# be used to specify the file name of the resulting .chm file. You 21766+# can add a path in front of the file if the result should not be 21767+# written to the html output directory. 21768+ 21769+CHM_FILE = 21770+ 21771+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 21772+# be used to specify the location (absolute path including file name) of 21773+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 21774+# the HTML help compiler on the generated index.hhp. 21775+ 21776+HHC_LOCATION = 21777+ 21778+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 21779+# controls if a separate .chi index file is generated (YES) or that 21780+# it should be included in the master .chm file (NO). 21781+ 21782+GENERATE_CHI = NO 21783+ 21784+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 21785+# is used to encode HtmlHelp index (hhk), content (hhc) and project file 21786+# content. 21787+ 21788+CHM_INDEX_ENCODING = 21789+ 21790+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 21791+# controls whether a binary table of contents is generated (YES) or a 21792+# normal table of contents (NO) in the .chm file. 21793+ 21794+BINARY_TOC = NO 21795+ 21796+# The TOC_EXPAND flag can be set to YES to add extra items for group members 21797+# to the contents of the HTML help documentation and to the tree view. 21798+ 21799+TOC_EXPAND = NO 21800+ 21801+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER 21802+# are set, an additional index file will be generated that can be used as input for 21803+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated 21804+# HTML documentation. 21805+ 21806+GENERATE_QHP = NO 21807+ 21808+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 21809+# be used to specify the file name of the resulting .qch file. 21810+# The path specified is relative to the HTML output folder. 21811+ 21812+QCH_FILE = 21813+ 21814+# The QHP_NAMESPACE tag specifies the namespace to use when generating 21815+# Qt Help Project output. For more information please see 21816+# http://doc.trolltech.com/qthelpproject.html#namespace 21817+ 21818+QHP_NAMESPACE = 21819+ 21820+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 21821+# Qt Help Project output. For more information please see 21822+# http://doc.trolltech.com/qthelpproject.html#virtual-folders 21823+ 21824+QHP_VIRTUAL_FOLDER = doc 21825+ 21826+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. 21827+# For more information please see 21828+# http://doc.trolltech.com/qthelpproject.html#custom-filters 21829+ 21830+QHP_CUST_FILTER_NAME = 21831+ 21832+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see 21833+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>. 21834+ 21835+QHP_CUST_FILTER_ATTRS = 21836+ 21837+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's 21838+# filter section matches. 21839+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>. 21840+ 21841+QHP_SECT_FILTER_ATTRS = 21842+ 21843+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 21844+# be used to specify the location of Qt's qhelpgenerator. 21845+# If non-empty doxygen will try to run qhelpgenerator on the generated 21846+# .qhp file. 21847+ 21848+QHG_LOCATION = 21849+ 21850+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 21851+# top of each HTML page. The value NO (the default) enables the index and 21852+# the value YES disables it. 21853+ 21854+DISABLE_INDEX = NO 21855+ 21856+# This tag can be used to set the number of enum values (range [1..20]) 21857+# that doxygen will group on one line in the generated HTML documentation. 21858+ 21859+ENUM_VALUES_PER_LINE = 4 21860+ 21861+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 21862+# structure should be generated to display hierarchical information. 21863+# If the tag value is set to YES, a side panel will be generated 21864+# containing a tree-like index structure (just like the one that 21865+# is generated for HTML Help). For this to work a browser that supports 21866+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 21867+# Windows users are probably better off using the HTML help feature. 21868+ 21869+GENERATE_TREEVIEW = NO 21870+ 21871+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, 21872+# and Class Hierarchy pages using a tree view instead of an ordered list. 21873+ 21874+USE_INLINE_TREES = NO 21875+ 21876+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 21877+# used to set the initial width (in pixels) of the frame in which the tree 21878+# is shown. 21879+ 21880+TREEVIEW_WIDTH = 250 21881+ 21882+# Use this tag to change the font size of Latex formulas included 21883+# as images in the HTML documentation. The default is 10. Note that 21884+# when you change the font size after a successful doxygen run you need 21885+# to manually remove any form_*.png images from the HTML output directory 21886+# to force them to be regenerated. 21887+ 21888+FORMULA_FONTSIZE = 10 21889+ 21890+# When the SEARCHENGINE tag is enable doxygen will generate a search box 21891+# for the HTML output. The underlying search engine uses javascript 21892+# and DHTML and should work on any modern browser. Note that when using 21893+# HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) 21894+# there is already a search function so this one should typically 21895+# be disabled. 21896+ 21897+SEARCHENGINE = YES 21898+ 21899+#--------------------------------------------------------------------------- 21900+# configuration options related to the LaTeX output 21901+#--------------------------------------------------------------------------- 21902+ 21903+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 21904+# generate Latex output. 21905+ 21906+GENERATE_LATEX = NO 21907+ 21908+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 21909+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 21910+# put in front of it. If left blank `latex' will be used as the default path. 21911+ 21912+LATEX_OUTPUT = latex 21913+ 21914+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 21915+# invoked. If left blank `latex' will be used as the default command name. 21916+ 21917+LATEX_CMD_NAME = latex 21918+ 21919+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 21920+# generate index for LaTeX. If left blank `makeindex' will be used as the 21921+# default command name. 21922+ 21923+MAKEINDEX_CMD_NAME = makeindex 21924+ 21925+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 21926+# LaTeX documents. This may be useful for small projects and may help to 21927+# save some trees in general. 21928+ 21929+COMPACT_LATEX = NO 21930+ 21931+# The PAPER_TYPE tag can be used to set the paper type that is used 21932+# by the printer. Possible values are: a4, a4wide, letter, legal and 21933+# executive. If left blank a4wide will be used. 21934+ 21935+PAPER_TYPE = a4wide 21936+ 21937+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 21938+# packages that should be included in the LaTeX output. 21939+ 21940+EXTRA_PACKAGES = 21941+ 21942+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 21943+# the generated latex document. The header should contain everything until 21944+# the first chapter. If it is left blank doxygen will generate a 21945+# standard header. Notice: only use this tag if you know what you are doing! 21946+ 21947+LATEX_HEADER = 21948+ 21949+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 21950+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 21951+# contain links (just like the HTML output) instead of page references 21952+# This makes the output suitable for online browsing using a pdf viewer. 21953+ 21954+PDF_HYPERLINKS = YES 21955+ 21956+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 21957+# plain latex in the generated Makefile. Set this option to YES to get a 21958+# higher quality PDF documentation. 21959+ 21960+USE_PDFLATEX = YES 21961+ 21962+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 21963+# command to the generated LaTeX files. This will instruct LaTeX to keep 21964+# running if errors occur, instead of asking the user for help. 21965+# This option is also used when generating formulas in HTML. 21966+ 21967+LATEX_BATCHMODE = NO 21968+ 21969+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 21970+# include the index chapters (such as File Index, Compound Index, etc.) 21971+# in the output. 21972+ 21973+LATEX_HIDE_INDICES = NO 21974+ 21975+# If LATEX_SOURCE_CODE is set to YES then doxygen will include 21976+# source code with syntax highlighting in the LaTeX output. 21977+# Note that which sources are shown also depends on other settings 21978+# such as SOURCE_BROWSER. 21979+ 21980+LATEX_SOURCE_CODE = NO 21981+ 21982+#--------------------------------------------------------------------------- 21983+# configuration options related to the RTF output 21984+#--------------------------------------------------------------------------- 21985+ 21986+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 21987+# The RTF output is optimized for Word 97 and may not look very pretty with 21988+# other RTF readers or editors. 21989+ 21990+GENERATE_RTF = NO 21991+ 21992+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 21993+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 21994+# put in front of it. If left blank `rtf' will be used as the default path. 21995+ 21996+RTF_OUTPUT = rtf 21997+ 21998+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 21999+# RTF documents. This may be useful for small projects and may help to 22000+# save some trees in general. 22001+ 22002+COMPACT_RTF = NO 22003+ 22004+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 22005+# will contain hyperlink fields. The RTF file will 22006+# contain links (just like the HTML output) instead of page references. 22007+# This makes the output suitable for online browsing using WORD or other 22008+# programs which support those fields. 22009+# Note: wordpad (write) and others do not support links. 22010+ 22011+RTF_HYPERLINKS = NO 22012+ 22013+# Load stylesheet definitions from file. Syntax is similar to doxygen's 22014+# config file, i.e. a series of assignments. You only have to provide 22015+# replacements, missing definitions are set to their default value. 22016+ 22017+RTF_STYLESHEET_FILE = 22018+ 22019+# Set optional variables used in the generation of an rtf document. 22020+# Syntax is similar to doxygen's config file. 22021+ 22022+RTF_EXTENSIONS_FILE = 22023+ 22024+#--------------------------------------------------------------------------- 22025+# configuration options related to the man page output 22026+#--------------------------------------------------------------------------- 22027+ 22028+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 22029+# generate man pages 22030+ 22031+GENERATE_MAN = NO 22032+ 22033+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 22034+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 22035+# put in front of it. If left blank `man' will be used as the default path. 22036+ 22037+MAN_OUTPUT = man 22038+ 22039+# The MAN_EXTENSION tag determines the extension that is added to 22040+# the generated man pages (default is the subroutine's section .3) 22041+ 22042+MAN_EXTENSION = .3 22043+ 22044+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 22045+# then it will generate one additional man file for each entity 22046+# documented in the real man page(s). These additional files 22047+# only source the real man page, but without them the man command 22048+# would be unable to find the correct page. The default is NO. 22049+ 22050+MAN_LINKS = NO 22051+ 22052+#--------------------------------------------------------------------------- 22053+# configuration options related to the XML output 22054+#--------------------------------------------------------------------------- 22055+ 22056+# If the GENERATE_XML tag is set to YES Doxygen will 22057+# generate an XML file that captures the structure of 22058+# the code including all documentation. 22059+ 22060+GENERATE_XML = NO 22061+ 22062+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 22063+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 22064+# put in front of it. If left blank `xml' will be used as the default path. 22065+ 22066+XML_OUTPUT = xml 22067+ 22068+# The XML_SCHEMA tag can be used to specify an XML schema, 22069+# which can be used by a validating XML parser to check the 22070+# syntax of the XML files. 22071+ 22072+XML_SCHEMA = 22073+ 22074+# The XML_DTD tag can be used to specify an XML DTD, 22075+# which can be used by a validating XML parser to check the 22076+# syntax of the XML files. 22077+ 22078+XML_DTD = 22079+ 22080+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 22081+# dump the program listings (including syntax highlighting 22082+# and cross-referencing information) to the XML output. Note that 22083+# enabling this will significantly increase the size of the XML output. 22084+ 22085+XML_PROGRAMLISTING = YES 22086+ 22087+#--------------------------------------------------------------------------- 22088+# configuration options for the AutoGen Definitions output 22089+#--------------------------------------------------------------------------- 22090+ 22091+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 22092+# generate an AutoGen Definitions (see autogen.sf.net) file 22093+# that captures the structure of the code including all 22094+# documentation. Note that this feature is still experimental 22095+# and incomplete at the moment. 22096+ 22097+GENERATE_AUTOGEN_DEF = NO 22098+ 22099+#--------------------------------------------------------------------------- 22100+# configuration options related to the Perl module output 22101+#--------------------------------------------------------------------------- 22102+ 22103+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 22104+# generate a Perl module file that captures the structure of 22105+# the code including all documentation. Note that this 22106+# feature is still experimental and incomplete at the 22107+# moment. 22108+ 22109+GENERATE_PERLMOD = NO 22110+ 22111+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 22112+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 22113+# to generate PDF and DVI output from the Perl module output. 22114+ 22115+PERLMOD_LATEX = NO 22116+ 22117+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 22118+# nicely formatted so it can be parsed by a human reader. This is useful 22119+# if you want to understand what is going on. On the other hand, if this 22120+# tag is set to NO the size of the Perl module output will be much smaller 22121+# and Perl will parse it just the same. 22122+ 22123+PERLMOD_PRETTY = YES 22124+ 22125+# The names of the make variables in the generated doxyrules.make file 22126+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 22127+# This is useful so different doxyrules.make files included by the same 22128+# Makefile don't overwrite each other's variables. 22129+ 22130+PERLMOD_MAKEVAR_PREFIX = 22131+ 22132+#--------------------------------------------------------------------------- 22133+# Configuration options related to the preprocessor 22134+#--------------------------------------------------------------------------- 22135+ 22136+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 22137+# evaluate all C-preprocessor directives found in the sources and include 22138+# files. 22139+ 22140+ENABLE_PREPROCESSING = YES 22141+ 22142+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 22143+# names in the source code. If set to NO (the default) only conditional 22144+# compilation will be performed. Macro expansion can be done in a controlled 22145+# way by setting EXPAND_ONLY_PREDEF to YES. 22146+ 22147+MACRO_EXPANSION = NO 22148+ 22149+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 22150+# then the macro expansion is limited to the macros specified with the 22151+# PREDEFINED and EXPAND_AS_DEFINED tags. 22152+ 22153+EXPAND_ONLY_PREDEF = NO 22154+ 22155+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 22156+# in the INCLUDE_PATH (see below) will be search if a #include is found. 22157+ 22158+SEARCH_INCLUDES = YES 22159+ 22160+# The INCLUDE_PATH tag can be used to specify one or more directories that 22161+# contain include files that are not input files but should be processed by 22162+# the preprocessor. 22163+ 22164+INCLUDE_PATH = 22165+ 22166+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 22167+# patterns (like *.h and *.hpp) to filter out the header-files in the 22168+# directories. If left blank, the patterns specified with FILE_PATTERNS will 22169+# be used. 22170+ 22171+INCLUDE_FILE_PATTERNS = 22172+ 22173+# The PREDEFINED tag can be used to specify one or more macro names that 22174+# are defined before the preprocessor is started (similar to the -D option of 22175+# gcc). The argument of the tag is a list of macros of the form: name 22176+# or name=definition (no spaces). If the definition and the = are 22177+# omitted =1 is assumed. To prevent a macro definition from being 22178+# undefined via #undef or recursively expanded use the := operator 22179+# instead of the = operator. 22180+ 22181+PREDEFINED = 22182+ 22183+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 22184+# this tag can be used to specify a list of macro names that should be expanded. 22185+# The macro definition that is found in the sources will be used. 22186+# Use the PREDEFINED tag if you want to use a different macro definition. 22187+ 22188+EXPAND_AS_DEFINED = 22189+ 22190+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 22191+# doxygen's preprocessor will remove all function-like macros that are alone 22192+# on a line, have an all uppercase name, and do not end with a semicolon. Such 22193+# function macros are typically used for boiler-plate code, and will confuse 22194+# the parser if not removed. 22195+ 22196+SKIP_FUNCTION_MACROS = YES 22197+ 22198+#--------------------------------------------------------------------------- 22199+# Configuration::additions related to external references 22200+#--------------------------------------------------------------------------- 22201+ 22202+# The TAGFILES option can be used to specify one or more tagfiles. 22203+# Optionally an initial location of the external documentation 22204+# can be added for each tagfile. The format of a tag file without 22205+# this location is as follows: 22206+# TAGFILES = file1 file2 ... 22207+# Adding location for the tag files is done as follows: 22208+# TAGFILES = file1=loc1 "file2 = loc2" ... 22209+# where "loc1" and "loc2" can be relative or absolute paths or 22210+# URLs. If a location is present for each tag, the installdox tool 22211+# does not have to be run to correct the links. 22212+# Note that each tag file must have a unique name 22213+# (where the name does NOT include the path) 22214+# If a tag file is not located in the directory in which doxygen 22215+# is run, you must also specify the path to the tagfile here. 22216+ 22217+TAGFILES = 22218+ 22219+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 22220+# a tag file that is based on the input files it reads. 22221+ 22222+GENERATE_TAGFILE = 22223+ 22224+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 22225+# in the class index. If set to NO only the inherited external classes 22226+# will be listed. 22227+ 22228+ALLEXTERNALS = NO 22229+ 22230+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 22231+# in the modules index. If set to NO, only the current project's groups will 22232+# be listed. 22233+ 22234+EXTERNAL_GROUPS = YES 22235+ 22236+# The PERL_PATH should be the absolute path and name of the perl script 22237+# interpreter (i.e. the result of `which perl'). 22238+ 22239+PERL_PATH = /usr/bin/perl 22240+ 22241+#--------------------------------------------------------------------------- 22242+# Configuration options related to the dot tool 22243+#--------------------------------------------------------------------------- 22244+ 22245+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 22246+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 22247+# or super classes. Setting the tag to NO turns the diagrams off. Note that 22248+# this option is superseded by the HAVE_DOT option below. This is only a 22249+# fallback. It is recommended to install and use dot, since it yields more 22250+# powerful graphs. 22251+ 22252+CLASS_DIAGRAMS = YES 22253+ 22254+# You can define message sequence charts within doxygen comments using the \msc 22255+# command. Doxygen will then run the mscgen tool (see 22256+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 22257+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 22258+# the mscgen tool resides. If left empty the tool is assumed to be found in the 22259+# default search path. 22260+ 22261+MSCGEN_PATH = 22262+ 22263+# If set to YES, the inheritance and collaboration graphs will hide 22264+# inheritance and usage relations if the target is undocumented 22265+# or is not a class. 22266+ 22267+HIDE_UNDOC_RELATIONS = YES 22268+ 22269+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 22270+# available from the path. This tool is part of Graphviz, a graph visualization 22271+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 22272+# have no effect if this option is set to NO (the default) 22273+ 22274+HAVE_DOT = NO 22275+ 22276+# By default doxygen will write a font called FreeSans.ttf to the output 22277+# directory and reference it in all dot files that doxygen generates. This 22278+# font does not include all possible unicode characters however, so when you need 22279+# these (or just want a differently looking font) you can specify the font name 22280+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 22281+# which can be done by putting it in a standard location or by setting the 22282+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 22283+# containing the font. 22284+ 22285+DOT_FONTNAME = FreeSans 22286+ 22287+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 22288+# The default size is 10pt. 22289+ 22290+DOT_FONTSIZE = 10 22291+ 22292+# By default doxygen will tell dot to use the output directory to look for the 22293+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 22294+# different font using DOT_FONTNAME you can set the path where dot 22295+# can find it using this tag. 22296+ 22297+DOT_FONTPATH = 22298+ 22299+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 22300+# will generate a graph for each documented class showing the direct and 22301+# indirect inheritance relations. Setting this tag to YES will force the 22302+# the CLASS_DIAGRAMS tag to NO. 22303+ 22304+CLASS_GRAPH = YES 22305+ 22306+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 22307+# will generate a graph for each documented class showing the direct and 22308+# indirect implementation dependencies (inheritance, containment, and 22309+# class references variables) of the class with other documented classes. 22310+ 22311+COLLABORATION_GRAPH = YES 22312+ 22313+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 22314+# will generate a graph for groups, showing the direct groups dependencies 22315+ 22316+GROUP_GRAPHS = YES 22317+ 22318+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 22319+# collaboration diagrams in a style similar to the OMG's Unified Modeling 22320+# Language. 22321+ 22322+UML_LOOK = NO 22323+ 22324+# If set to YES, the inheritance and collaboration graphs will show the 22325+# relations between templates and their instances. 22326+ 22327+TEMPLATE_RELATIONS = NO 22328+ 22329+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 22330+# tags are set to YES then doxygen will generate a graph for each documented 22331+# file showing the direct and indirect include dependencies of the file with 22332+# other documented files. 22333+ 22334+INCLUDE_GRAPH = YES 22335+ 22336+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 22337+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 22338+# documented header file showing the documented files that directly or 22339+# indirectly include this file. 22340+ 22341+INCLUDED_BY_GRAPH = YES 22342+ 22343+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 22344+# doxygen will generate a call dependency graph for every global function 22345+# or class method. Note that enabling this option will significantly increase 22346+# the time of a run. So in most cases it will be better to enable call graphs 22347+# for selected functions only using the \callgraph command. 22348+ 22349+CALL_GRAPH = NO 22350+ 22351+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 22352+# doxygen will generate a caller dependency graph for every global function 22353+# or class method. Note that enabling this option will significantly increase 22354+# the time of a run. So in most cases it will be better to enable caller 22355+# graphs for selected functions only using the \callergraph command. 22356+ 22357+CALLER_GRAPH = NO 22358+ 22359+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 22360+# will graphical hierarchy of all classes instead of a textual one. 22361+ 22362+GRAPHICAL_HIERARCHY = YES 22363+ 22364+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 22365+# then doxygen will show the dependencies a directory has on other directories 22366+# in a graphical way. The dependency relations are determined by the #include 22367+# relations between the files in the directories. 22368+ 22369+DIRECTORY_GRAPH = YES 22370+ 22371+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 22372+# generated by dot. Possible values are png, jpg, or gif 22373+# If left blank png will be used. 22374+ 22375+DOT_IMAGE_FORMAT = png 22376+ 22377+# The tag DOT_PATH can be used to specify the path where the dot tool can be 22378+# found. If left blank, it is assumed the dot tool can be found in the path. 22379+ 22380+DOT_PATH = 22381+ 22382+# The DOTFILE_DIRS tag can be used to specify one or more directories that 22383+# contain dot files that are included in the documentation (see the 22384+# \dotfile command). 22385+ 22386+DOTFILE_DIRS = 22387+ 22388+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 22389+# nodes that will be shown in the graph. If the number of nodes in a graph 22390+# becomes larger than this value, doxygen will truncate the graph, which is 22391+# visualized by representing a node as a red box. Note that doxygen if the 22392+# number of direct children of the root node in a graph is already larger than 22393+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 22394+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. 22395+ 22396+DOT_GRAPH_MAX_NODES = 50 22397+ 22398+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 22399+# graphs generated by dot. A depth value of 3 means that only nodes reachable 22400+# from the root by following a path via at most 3 edges will be shown. Nodes 22401+# that lay further from the root node will be omitted. Note that setting this 22402+# option to 1 or 2 may greatly reduce the computation time needed for large 22403+# code bases. Also note that the size of a graph can be further restricted by 22404+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. 22405+ 22406+MAX_DOT_GRAPH_DEPTH = 0 22407+ 22408+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 22409+# background. This is disabled by default, because dot on Windows does not 22410+# seem to support this out of the box. Warning: Depending on the platform used, 22411+# enabling this option may lead to badly anti-aliased labels on the edges of 22412+# a graph (i.e. they become hard to read). 22413+ 22414+DOT_TRANSPARENT = NO 22415+ 22416+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 22417+# files in one run (i.e. multiple -o and -T options on the command line). This 22418+# makes dot run faster, but since only newer versions of dot (>1.8.10) 22419+# support this, this feature is disabled by default. 22420+ 22421+DOT_MULTI_TARGETS = NO 22422+ 22423+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 22424+# generate a legend page explaining the meaning of the various boxes and 22425+# arrows in the dot generated graphs. 22426+ 22427+GENERATE_LEGEND = YES 22428+ 22429+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 22430+# remove the intermediate dot files that are used to generate 22431+# the various graphs. 22432+ 22433+DOT_CLEANUP = YES 22434diff --git a/benchmark/feature_stab/src/dbreg/dbreg.cpp b/benchmark/feature_stab/src/dbreg/dbreg.cpp 22435new file mode 100644 22436index 00000000..986e255e 22437--- /dev/null 22438+++ b/benchmark/feature_stab/src/dbreg/dbreg.cpp 22439@@ -0,0 +1,793 @@ 22440+/* 22441+ * Copyright (C) 2011 The Android Open Source Project 22442+ * 22443+ * Licensed under the Apache License, Version 2.0 (the "License"); 22444+ * you may not use this file except in compliance with the License. 22445+ * You may obtain a copy of the License at 22446+ * 22447+ * http://www.apache.org/licenses/LICENSE-2.0 22448+ * 22449+ * Unless required by applicable law or agreed to in writing, software 22450+ * distributed under the License is distributed on an "AS IS" BASIS, 22451+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22452+ * See the License for the specific language governing permissions and 22453+ * limitations under the License. 22454+ */ 22455+ 22456+// $Id: dbreg.cpp,v 1.31 2011/06/17 14:04:32 mbansal Exp $ 22457+#include "dbreg.h" 22458+#include <string.h> 22459+#include <stdio.h> 22460+ 22461+ 22462+#if PROFILE 22463+#endif 22464+ 22465+//#include <iostream> 22466+ 22467+db_FrameToReferenceRegistration::db_FrameToReferenceRegistration() : 22468+ m_initialized(false),m_nr_matches(0),m_over_allocation(256),m_nr_bins(20),m_max_cost_pix(30), m_quarter_resolution(false) 22469+{ 22470+ m_reference_image = NULL; 22471+ m_aligned_ins_image = NULL; 22472+ 22473+ m_quarter_res_image = NULL; 22474+ m_horz_smooth_subsample_image = NULL; 22475+ 22476+ m_x_corners_ref = NULL; 22477+ m_y_corners_ref = NULL; 22478+ 22479+ m_x_corners_ins = NULL; 22480+ m_y_corners_ins = NULL; 22481+ 22482+ m_match_index_ref = NULL; 22483+ m_match_index_ins = NULL; 22484+ 22485+ m_inlier_indices = NULL; 22486+ 22487+ m_num_inlier_indices = 0; 22488+ 22489+ m_temp_double = NULL; 22490+ m_temp_int = NULL; 22491+ 22492+ m_corners_ref = NULL; 22493+ m_corners_ins = NULL; 22494+ 22495+ m_sq_cost = NULL; 22496+ m_cost_histogram = NULL; 22497+ 22498+ profile_string = NULL; 22499+ 22500+ db_Identity3x3(m_K); 22501+ db_Identity3x3(m_H_ref_to_ins); 22502+ db_Identity3x3(m_H_dref_to_ref); 22503+ 22504+ m_sq_cost_computed = false; 22505+ m_reference_set = false; 22506+ 22507+ m_reference_update_period = 0; 22508+ m_nr_frames_processed = 0; 22509+ 22510+ return; 22511+} 22512+ 22513+db_FrameToReferenceRegistration::~db_FrameToReferenceRegistration() 22514+{ 22515+ Clean(); 22516+} 22517+ 22518+void db_FrameToReferenceRegistration::Clean() 22519+{ 22520+ if ( m_reference_image ) 22521+ db_FreeImage_u(m_reference_image,m_im_height); 22522+ 22523+ if ( m_aligned_ins_image ) 22524+ db_FreeImage_u(m_aligned_ins_image,m_im_height); 22525+ 22526+ if ( m_quarter_res_image ) 22527+ { 22528+ db_FreeImage_u(m_quarter_res_image, m_im_height); 22529+ } 22530+ 22531+ if ( m_horz_smooth_subsample_image ) 22532+ { 22533+ db_FreeImage_u(m_horz_smooth_subsample_image, m_im_height*2); 22534+ } 22535+ 22536+ delete [] m_x_corners_ref; 22537+ delete [] m_y_corners_ref; 22538+ 22539+ delete [] m_x_corners_ins; 22540+ delete [] m_y_corners_ins; 22541+ 22542+ delete [] m_match_index_ref; 22543+ delete [] m_match_index_ins; 22544+ 22545+ delete [] m_temp_double; 22546+ delete [] m_temp_int; 22547+ 22548+ delete [] m_corners_ref; 22549+ delete [] m_corners_ins; 22550+ 22551+ delete [] m_sq_cost; 22552+ delete [] m_cost_histogram; 22553+ 22554+ delete [] m_inlier_indices; 22555+ 22556+ if(profile_string) 22557+ delete [] profile_string; 22558+ 22559+ m_reference_image = NULL; 22560+ m_aligned_ins_image = NULL; 22561+ 22562+ m_quarter_res_image = NULL; 22563+ m_horz_smooth_subsample_image = NULL; 22564+ 22565+ m_x_corners_ref = NULL; 22566+ m_y_corners_ref = NULL; 22567+ 22568+ m_x_corners_ins = NULL; 22569+ m_y_corners_ins = NULL; 22570+ 22571+ m_match_index_ref = NULL; 22572+ m_match_index_ins = NULL; 22573+ 22574+ m_inlier_indices = NULL; 22575+ 22576+ m_temp_double = NULL; 22577+ m_temp_int = NULL; 22578+ 22579+ m_corners_ref = NULL; 22580+ m_corners_ins = NULL; 22581+ 22582+ m_sq_cost = NULL; 22583+ m_cost_histogram = NULL; 22584+} 22585+ 22586+void db_FrameToReferenceRegistration::Init(int width, int height, 22587+ int homography_type, 22588+ int max_iterations, 22589+ bool linear_polish, 22590+ bool quarter_resolution, 22591+ double scale, 22592+ unsigned int reference_update_period, 22593+ bool do_motion_smoothing, 22594+ double motion_smoothing_gain, 22595+ int nr_samples, 22596+ int chunk_size, 22597+ int cd_target_nr_corners, 22598+ double cm_max_disparity, 22599+ bool cm_use_smaller_matching_window, 22600+ int cd_nr_horz_blocks, 22601+ int cd_nr_vert_blocks 22602+ ) 22603+{ 22604+ Clean(); 22605+ 22606+ m_reference_update_period = reference_update_period; 22607+ m_nr_frames_processed = 0; 22608+ 22609+ m_do_motion_smoothing = do_motion_smoothing; 22610+ m_motion_smoothing_gain = motion_smoothing_gain; 22611+ 22612+ m_stab_smoother.setSmoothingFactor(m_motion_smoothing_gain); 22613+ 22614+ m_quarter_resolution = quarter_resolution; 22615+ 22616+ profile_string = new char[10240]; 22617+ 22618+ if (m_quarter_resolution == true) 22619+ { 22620+ width = width/2; 22621+ height = height/2; 22622+ 22623+ m_horz_smooth_subsample_image = db_AllocImage_u(width,height*2,m_over_allocation); 22624+ m_quarter_res_image = db_AllocImage_u(width,height,m_over_allocation); 22625+ } 22626+ 22627+ m_im_width = width; 22628+ m_im_height = height; 22629+ 22630+ double temp[9]; 22631+ db_Approx3DCalMat(m_K,temp,m_im_width,m_im_height); 22632+ 22633+ m_homography_type = homography_type; 22634+ m_max_iterations = max_iterations; 22635+ m_scale = 2/(m_K[0]+m_K[4]); 22636+ m_nr_samples = nr_samples; 22637+ m_chunk_size = chunk_size; 22638+ 22639+ double outlier_t1 = 5.0; 22640+ 22641+ m_outlier_t2 = outlier_t1*outlier_t1;//*m_scale*m_scale; 22642+ 22643+ m_current_is_reference = false; 22644+ 22645+ m_linear_polish = linear_polish; 22646+ 22647+ m_reference_image = db_AllocImage_u(m_im_width,m_im_height,m_over_allocation); 22648+ m_aligned_ins_image = db_AllocImage_u(m_im_width,m_im_height,m_over_allocation); 22649+ 22650+ // initialize feature detection and matching: 22651+ //m_max_nr_corners = m_cd.Init(m_im_width,m_im_height,cd_target_nr_corners,cd_nr_horz_blocks,cd_nr_vert_blocks,0.0,0.0); 22652+ m_max_nr_corners = m_cd.Init(m_im_width,m_im_height,cd_target_nr_corners,cd_nr_horz_blocks,cd_nr_vert_blocks,DB_DEFAULT_ABS_CORNER_THRESHOLD/500.0,0.0); 22653+ 22654+ int use_21 = 0; 22655+ m_max_nr_matches = m_cm.Init(m_im_width,m_im_height,cm_max_disparity,m_max_nr_corners,DB_DEFAULT_NO_DISPARITY,cm_use_smaller_matching_window,use_21); 22656+ 22657+ // allocate space for corner feature locations for reference and inspection images: 22658+ m_x_corners_ref = new double [m_max_nr_corners]; 22659+ m_y_corners_ref = new double [m_max_nr_corners]; 22660+ 22661+ m_x_corners_ins = new double [m_max_nr_corners]; 22662+ m_y_corners_ins = new double [m_max_nr_corners]; 22663+ 22664+ // allocate space for match indices: 22665+ m_match_index_ref = new int [m_max_nr_matches]; 22666+ m_match_index_ins = new int [m_max_nr_matches]; 22667+ 22668+ m_temp_double = new double [12*DB_DEFAULT_NR_SAMPLES+10*m_max_nr_matches]; 22669+ m_temp_int = new int [db_maxi(DB_DEFAULT_NR_SAMPLES,m_max_nr_matches)]; 22670+ 22671+ // allocate space for homogenous image points: 22672+ m_corners_ref = new double [3*m_max_nr_corners]; 22673+ m_corners_ins = new double [3*m_max_nr_corners]; 22674+ 22675+ // allocate cost array and histogram: 22676+ m_sq_cost = new double [m_max_nr_matches]; 22677+ m_cost_histogram = new int [m_nr_bins]; 22678+ 22679+ // reserve array: 22680+ //m_inlier_indices.reserve(m_max_nr_matches); 22681+ m_inlier_indices = new int[m_max_nr_matches]; 22682+ 22683+ m_initialized = true; 22684+ 22685+ m_max_inlier_count = 0; 22686+} 22687+ 22688+ 22689+#define MB 0 22690+// Save the reference image, detect features and update the dref-to-ref transformation 22691+int db_FrameToReferenceRegistration::UpdateReference(const unsigned char * const * im, bool subsample, bool detect_corners) 22692+{ 22693+ double temp[9]; 22694+ db_Multiply3x3_3x3(temp,m_H_dref_to_ref,m_H_ref_to_ins); 22695+ db_Copy9(m_H_dref_to_ref,temp); 22696+ 22697+ const unsigned char * const * imptr = im; 22698+ 22699+ if (m_quarter_resolution && subsample) 22700+ { 22701+ GenerateQuarterResImage(im); 22702+ imptr = m_quarter_res_image; 22703+ } 22704+ 22705+ // save the reference image, detect features and quit 22706+ db_CopyImage_u(m_reference_image,imptr,m_im_width,m_im_height,m_over_allocation); 22707+ 22708+ if(detect_corners) 22709+ { 22710+ #if MB 22711+ m_cd.DetectCorners(imptr, m_x_corners_ref,m_y_corners_ref,&m_nr_corners_ref); 22712+ int nr = 0; 22713+ for(int k=0; k<m_nr_corners_ref; k++) 22714+ { 22715+ if(m_x_corners_ref[k]>m_im_width/3) 22716+ { 22717+ m_x_corners_ref[nr] = m_x_corners_ref[k]; 22718+ m_y_corners_ref[nr] = m_y_corners_ref[k]; 22719+ nr++; 22720+ } 22721+ 22722+ } 22723+ m_nr_corners_ref = nr; 22724+ #else 22725+ m_cd.DetectCorners(imptr, m_x_corners_ref,m_y_corners_ref,&m_nr_corners_ref); 22726+ #endif 22727+ } 22728+ else 22729+ { 22730+ m_nr_corners_ref = m_nr_corners_ins; 22731+ 22732+ for(int k=0; k<m_nr_corners_ins; k++) 22733+ { 22734+ m_x_corners_ref[k] = m_x_corners_ins[k]; 22735+ m_y_corners_ref[k] = m_y_corners_ins[k]; 22736+ } 22737+ 22738+ } 22739+ 22740+ db_Identity3x3(m_H_ref_to_ins); 22741+ 22742+ m_max_inlier_count = 0; // Reset to 0 as no inliers seen until now 22743+ m_sq_cost_computed = false; 22744+ m_reference_set = true; 22745+ m_current_is_reference = true; 22746+ return 1; 22747+} 22748+ 22749+void db_FrameToReferenceRegistration::Get_H_dref_to_ref(double H[9]) 22750+{ 22751+ db_Copy9(H,m_H_dref_to_ref); 22752+} 22753+ 22754+void db_FrameToReferenceRegistration::Get_H_dref_to_ins(double H[9]) 22755+{ 22756+ db_Multiply3x3_3x3(H,m_H_dref_to_ref,m_H_ref_to_ins); 22757+} 22758+ 22759+void db_FrameToReferenceRegistration::Set_H_dref_to_ins(double H[9]) 22760+{ 22761+ double H_ins_to_ref[9]; 22762+ 22763+ db_Identity3x3(H_ins_to_ref); // Ensure it has proper values 22764+ db_InvertAffineTransform(H_ins_to_ref,m_H_ref_to_ins); // Invert to get ins to ref 22765+ db_Multiply3x3_3x3(m_H_dref_to_ref,H,H_ins_to_ref); // Update dref to ref using the input H from dref to ins 22766+} 22767+ 22768+ 22769+void db_FrameToReferenceRegistration::ResetDisplayReference() 22770+{ 22771+ db_Identity3x3(m_H_dref_to_ref); 22772+} 22773+ 22774+bool db_FrameToReferenceRegistration::NeedReferenceUpdate() 22775+{ 22776+ // If less than 50% of the starting number of inliers left, then its time to update the reference. 22777+ if(m_max_inlier_count>0 && float(m_num_inlier_indices)/float(m_max_inlier_count)<0.5) 22778+ return true; 22779+ else 22780+ return false; 22781+} 22782+ 22783+int db_FrameToReferenceRegistration::AddFrame(const unsigned char * const * im, double H[9],bool force_reference,bool prewarp) 22784+{ 22785+ m_current_is_reference = false; 22786+ if(!m_reference_set || force_reference) 22787+ { 22788+ db_Identity3x3(m_H_ref_to_ins); 22789+ db_Copy9(H,m_H_ref_to_ins); 22790+ 22791+ UpdateReference(im,true,true); 22792+ return 0; 22793+ } 22794+ 22795+ const unsigned char * const * imptr = im; 22796+ 22797+ if (m_quarter_resolution) 22798+ { 22799+ if (m_quarter_res_image) 22800+ { 22801+ GenerateQuarterResImage(im); 22802+ } 22803+ 22804+ imptr = (const unsigned char * const* )m_quarter_res_image; 22805+ } 22806+ 22807+ double H_last[9]; 22808+ db_Copy9(H_last,m_H_ref_to_ins); 22809+ db_Identity3x3(m_H_ref_to_ins); 22810+ 22811+ m_sq_cost_computed = false; 22812+ 22813+ // detect corners on inspection image and match to reference image features:s 22814+ 22815+ // @jke - Adding code to time the functions. TODO: Remove after test 22816+#if PROFILE 22817+ double iTimer1, iTimer2; 22818+ char str[255]; 22819+ strcpy(profile_string,"\n"); 22820+ sprintf(str,"[%dx%d] %p\n",m_im_width,m_im_height,im); 22821+ strcat(profile_string, str); 22822+#endif 22823+ 22824+ // @jke - Adding code to time the functions. TODO: Remove after test 22825+#if PROFILE 22826+ iTimer1 = now_ms(); 22827+#endif 22828+ m_cd.DetectCorners(imptr, m_x_corners_ins,m_y_corners_ins,&m_nr_corners_ins); 22829+ // @jke - Adding code to time the functions. TODO: Remove after test 22830+# if PROFILE 22831+ iTimer2 = now_ms(); 22832+ double elapsedTimeCorner = iTimer2 - iTimer1; 22833+ sprintf(str,"Corner Detection [%d corners] = %g ms\n",m_nr_corners_ins, elapsedTimeCorner); 22834+ strcat(profile_string, str); 22835+#endif 22836+ 22837+ // @jke - Adding code to time the functions. TODO: Remove after test 22838+#if PROFILE 22839+ iTimer1 = now_ms(); 22840+#endif 22841+ if(prewarp) 22842+ m_cm.Match(m_reference_image,imptr,m_x_corners_ref,m_y_corners_ref,m_nr_corners_ref, 22843+ m_x_corners_ins,m_y_corners_ins,m_nr_corners_ins, 22844+ m_match_index_ref,m_match_index_ins,&m_nr_matches,H,0); 22845+ else 22846+ m_cm.Match(m_reference_image,imptr,m_x_corners_ref,m_y_corners_ref,m_nr_corners_ref, 22847+ m_x_corners_ins,m_y_corners_ins,m_nr_corners_ins, 22848+ m_match_index_ref,m_match_index_ins,&m_nr_matches); 22849+ // @jke - Adding code to time the functions. TODO: Remove after test 22850+# if PROFILE 22851+ iTimer2 = now_ms(); 22852+ double elapsedTimeMatch = iTimer2 - iTimer1; 22853+ sprintf(str,"Matching [%d] = %g ms\n",m_nr_matches,elapsedTimeMatch); 22854+ strcat(profile_string, str); 22855+#endif 22856+ 22857+ 22858+ // copy out matching features: 22859+ for ( int i = 0; i < m_nr_matches; ++i ) 22860+ { 22861+ int offset = 3*i; 22862+ m_corners_ref[offset ] = m_x_corners_ref[m_match_index_ref[i]]; 22863+ m_corners_ref[offset+1] = m_y_corners_ref[m_match_index_ref[i]]; 22864+ m_corners_ref[offset+2] = 1.0; 22865+ 22866+ m_corners_ins[offset ] = m_x_corners_ins[m_match_index_ins[i]]; 22867+ m_corners_ins[offset+1] = m_y_corners_ins[m_match_index_ins[i]]; 22868+ m_corners_ins[offset+2] = 1.0; 22869+ } 22870+ 22871+ // @jke - Adding code to time the functions. TODO: Remove after test 22872+#if PROFILE 22873+ iTimer1 = now_ms(); 22874+#endif 22875+ // perform the alignment: 22876+ db_RobImageHomography(m_H_ref_to_ins, m_corners_ref, m_corners_ins, m_nr_matches, m_K, m_K, m_temp_double, m_temp_int, 22877+ m_homography_type,NULL,m_max_iterations,m_max_nr_matches,m_scale, 22878+ m_nr_samples, m_chunk_size); 22879+ // @jke - Adding code to time the functions. TODO: Remove after test 22880+# if PROFILE 22881+ iTimer2 = now_ms(); 22882+ double elapsedTimeHomography = iTimer2 - iTimer1; 22883+ sprintf(str,"Homography = %g ms\n",elapsedTimeHomography); 22884+ strcat(profile_string, str); 22885+#endif 22886+ 22887+ 22888+ SetOutlierThreshold(); 22889+ 22890+ // Compute the inliers for the db compute m_H_ref_to_ins 22891+ ComputeInliers(m_H_ref_to_ins); 22892+ 22893+ // Update the max inlier count 22894+ m_max_inlier_count = (m_max_inlier_count > m_num_inlier_indices)?m_max_inlier_count:m_num_inlier_indices; 22895+ 22896+ // Fit a least-squares model to just the inliers and put it in m_H_ref_to_ins 22897+ if(m_linear_polish) 22898+ Polish(m_inlier_indices, m_num_inlier_indices); 22899+ 22900+ if (m_quarter_resolution) 22901+ { 22902+ m_H_ref_to_ins[2] *= 2.0; 22903+ m_H_ref_to_ins[5] *= 2.0; 22904+ } 22905+ 22906+#if PROFILE 22907+ sprintf(str,"#Inliers = %d \n",m_num_inlier_indices); 22908+ strcat(profile_string, str); 22909+#endif 22910+/* 22911+ ///// CHECK IF CURRENT TRANSFORMATION GOOD OR BAD //// 22912+ ///// IF BAD, then update reference to the last correctly aligned inspection frame; 22913+ if(m_num_inlier_indices<5)//0.9*m_nr_matches || m_nr_matches < 20) 22914+ { 22915+ db_Copy9(m_H_ref_to_ins,H_last); 22916+ UpdateReference(imptr,false); 22917+// UpdateReference(m_aligned_ins_image,false); 22918+ } 22919+ else 22920+ { 22921+ ///// IF GOOD, then update the last correctly aligned inspection frame to be this; 22922+ //db_CopyImage_u(m_aligned_ins_image,imptr,m_im_width,m_im_height,m_over_allocation); 22923+*/ 22924+ if(m_do_motion_smoothing) 22925+ SmoothMotion(); 22926+ 22927+ // Disable debug printing 22928+ // db_PrintDoubleMatrix(m_H_ref_to_ins,3,3); 22929+ 22930+ db_Copy9(H, m_H_ref_to_ins); 22931+ 22932+ m_nr_frames_processed++; 22933+{ 22934+ if ( (m_nr_frames_processed % m_reference_update_period) == 0 ) 22935+ { 22936+ //UpdateReference(imptr,false, false); 22937+ 22938+ #if MB 22939+ UpdateReference(imptr,false, true); 22940+ #else 22941+ UpdateReference(imptr,false, false); 22942+ #endif 22943+ } 22944+ 22945+ 22946+ } 22947+ 22948+ 22949+ 22950+ return 1; 22951+} 22952+ 22953+//void db_FrameToReferenceRegistration::ComputeInliers(double H[9],std::vector<int> &inlier_indices) 22954+void db_FrameToReferenceRegistration::ComputeInliers(double H[9]) 22955+{ 22956+ double totnummatches = m_nr_matches; 22957+ int inliercount=0; 22958+ 22959+ m_num_inlier_indices = 0; 22960+// inlier_indices.clear(); 22961+ 22962+ for(int c=0; c < totnummatches; c++ ) 22963+ { 22964+ if (m_sq_cost[c] <= m_outlier_t2) 22965+ { 22966+ m_inlier_indices[inliercount] = c; 22967+ inliercount++; 22968+ } 22969+ } 22970+ 22971+ m_num_inlier_indices = inliercount; 22972+} 22973+ 22974+//void db_FrameToReferenceRegistration::Polish(std::vector<int> &inlier_indices) 22975+void db_FrameToReferenceRegistration::Polish(int *inlier_indices, int &num_inlier_indices) 22976+{ 22977+ db_Zero(m_polish_C,36); 22978+ db_Zero(m_polish_D,6); 22979+ for (int i=0;i<num_inlier_indices;i++) 22980+ { 22981+ int j = 3*inlier_indices[i]; 22982+ m_polish_C[0]+=m_corners_ref[j]*m_corners_ref[j]; 22983+ m_polish_C[1]+=m_corners_ref[j]*m_corners_ref[j+1]; 22984+ m_polish_C[2]+=m_corners_ref[j]; 22985+ m_polish_C[7]+=m_corners_ref[j+1]*m_corners_ref[j+1]; 22986+ m_polish_C[8]+=m_corners_ref[j+1]; 22987+ m_polish_C[14]+=1; 22988+ m_polish_D[0]+=m_corners_ref[j]*m_corners_ins[j]; 22989+ m_polish_D[1]+=m_corners_ref[j+1]*m_corners_ins[j]; 22990+ m_polish_D[2]+=m_corners_ins[j]; 22991+ m_polish_D[3]+=m_corners_ref[j]*m_corners_ins[j+1]; 22992+ m_polish_D[4]+=m_corners_ref[j+1]*m_corners_ins[j+1]; 22993+ m_polish_D[5]+=m_corners_ins[j+1]; 22994+ } 22995+ 22996+ double a=db_maxd(m_polish_C[0],m_polish_C[7]); 22997+ m_polish_C[0]/=a; m_polish_C[1]/=a; m_polish_C[2]/=a; 22998+ m_polish_C[7]/=a; m_polish_C[8]/=a; m_polish_C[14]/=a; 22999+ 23000+ m_polish_D[0]/=a; m_polish_D[1]/=a; m_polish_D[2]/=a; 23001+ m_polish_D[3]/=a; m_polish_D[4]/=a; m_polish_D[5]/=a; 23002+ 23003+ 23004+ m_polish_C[6]=m_polish_C[1]; 23005+ m_polish_C[12]=m_polish_C[2]; 23006+ m_polish_C[13]=m_polish_C[8]; 23007+ 23008+ m_polish_C[21]=m_polish_C[0]; m_polish_C[22]=m_polish_C[1]; m_polish_C[23]=m_polish_C[2]; 23009+ m_polish_C[28]=m_polish_C[7]; m_polish_C[29]=m_polish_C[8]; 23010+ m_polish_C[35]=m_polish_C[14]; 23011+ 23012+ 23013+ double d[6]; 23014+ db_CholeskyDecomp6x6(m_polish_C,d); 23015+ db_CholeskyBacksub6x6(m_H_ref_to_ins,m_polish_C,d,m_polish_D); 23016+} 23017+ 23018+void db_FrameToReferenceRegistration::EstimateSecondaryModel(double H[9]) 23019+{ 23020+ /* if ( m_current_is_reference ) 23021+ { 23022+ db_Identity3x3(H); 23023+ return; 23024+ } 23025+ */ 23026+ 23027+ // select the outliers of the current model: 23028+ SelectOutliers(); 23029+ 23030+ // perform the alignment: 23031+ db_RobImageHomography(m_H_ref_to_ins, m_corners_ref, m_corners_ins, m_nr_matches, m_K, m_K, m_temp_double, m_temp_int, 23032+ m_homography_type,NULL,m_max_iterations,m_max_nr_matches,m_scale, 23033+ m_nr_samples, m_chunk_size); 23034+ 23035+ db_Copy9(H,m_H_ref_to_ins); 23036+} 23037+ 23038+void db_FrameToReferenceRegistration::ComputeCostArray() 23039+{ 23040+ if ( m_sq_cost_computed ) return; 23041+ 23042+ for( int c=0, k=0 ;c < m_nr_matches; c++, k=k+3) 23043+ { 23044+ m_sq_cost[c] = SquaredInhomogenousHomographyError(m_corners_ins+k,m_H_ref_to_ins,m_corners_ref+k); 23045+ } 23046+ 23047+ m_sq_cost_computed = true; 23048+} 23049+ 23050+void db_FrameToReferenceRegistration::SelectOutliers() 23051+{ 23052+ int nr_outliers=0; 23053+ 23054+ ComputeCostArray(); 23055+ 23056+ for(int c=0, k=0 ;c<m_nr_matches;c++,k=k+3) 23057+ { 23058+ if (m_sq_cost[c] > m_outlier_t2) 23059+ { 23060+ int offset = 3*nr_outliers++; 23061+ db_Copy3(m_corners_ref+offset,m_corners_ref+k); 23062+ db_Copy3(m_corners_ins+offset,m_corners_ins+k); 23063+ } 23064+ } 23065+ 23066+ m_nr_matches = nr_outliers; 23067+} 23068+ 23069+void db_FrameToReferenceRegistration::ComputeCostHistogram() 23070+{ 23071+ ComputeCostArray(); 23072+ 23073+ for ( int b = 0; b < m_nr_bins; ++b ) 23074+ m_cost_histogram[b] = 0; 23075+ 23076+ for(int c = 0; c < m_nr_matches; c++) 23077+ { 23078+ double error = db_SafeSqrt(m_sq_cost[c]); 23079+ int bin = (int)(error/m_max_cost_pix*m_nr_bins); 23080+ if ( bin < m_nr_bins ) 23081+ m_cost_histogram[bin]++; 23082+ else 23083+ m_cost_histogram[m_nr_bins-1]++; 23084+ } 23085+ 23086+/* 23087+ for ( int i = 0; i < m_nr_bins; ++i ) 23088+ std::cout << m_cost_histogram[i] << " "; 23089+ std::cout << std::endl; 23090+*/ 23091+} 23092+ 23093+void db_FrameToReferenceRegistration::SetOutlierThreshold() 23094+{ 23095+ ComputeCostHistogram(); 23096+ 23097+ int i = 0, last=0; 23098+ for (; i < m_nr_bins-1; ++i ) 23099+ { 23100+ if ( last > m_cost_histogram[i] ) 23101+ break; 23102+ last = m_cost_histogram[i]; 23103+ } 23104+ 23105+ //std::cout << "I " << i << std::endl; 23106+ 23107+ int max = m_cost_histogram[i]; 23108+ 23109+ for (; i < m_nr_bins-1; ++i ) 23110+ { 23111+ if ( m_cost_histogram[i] < (int)(0.1*max) ) 23112+ //if ( last < m_cost_histogram[i] ) 23113+ break; 23114+ last = m_cost_histogram[i]; 23115+ } 23116+ //std::cout << "J " << i << std::endl; 23117+ 23118+ m_outlier_t2 = db_sqr(i*m_max_cost_pix/m_nr_bins); 23119+ 23120+ //std::cout << "m_outlier_t2 " << m_outlier_t2 << std::endl; 23121+} 23122+ 23123+void db_FrameToReferenceRegistration::SmoothMotion(void) 23124+{ 23125+ VP_MOTION inmot,outmot; 23126+ 23127+ double H[9]; 23128+ 23129+ Get_H_dref_to_ins(H); 23130+ 23131+ MXX(inmot) = H[0]; 23132+ MXY(inmot) = H[1]; 23133+ MXZ(inmot) = H[2]; 23134+ MXW(inmot) = 0.0; 23135+ 23136+ MYX(inmot) = H[3]; 23137+ MYY(inmot) = H[4]; 23138+ MYZ(inmot) = H[5]; 23139+ MYW(inmot) = 0.0; 23140+ 23141+ MZX(inmot) = H[6]; 23142+ MZY(inmot) = H[7]; 23143+ MZZ(inmot) = H[8]; 23144+ MZW(inmot) = 0.0; 23145+ 23146+ MWX(inmot) = 0.0; 23147+ MWY(inmot) = 0.0; 23148+ MWZ(inmot) = 0.0; 23149+ MWW(inmot) = 1.0; 23150+ 23151+ inmot.type = VP_MOTION_AFFINE; 23152+ 23153+ int w = m_im_width; 23154+ int h = m_im_height; 23155+ 23156+ if(m_quarter_resolution) 23157+ { 23158+ w = w*2; 23159+ h = h*2; 23160+ } 23161+ 23162+#if 0 23163+ m_stab_smoother.smoothMotionAdaptive(w,h,&inmot,&outmot); 23164+#else 23165+ m_stab_smoother.smoothMotion(&inmot,&outmot); 23166+#endif 23167+ 23168+ H[0] = MXX(outmot); 23169+ H[1] = MXY(outmot); 23170+ H[2] = MXZ(outmot); 23171+ 23172+ H[3] = MYX(outmot); 23173+ H[4] = MYY(outmot); 23174+ H[5] = MYZ(outmot); 23175+ 23176+ H[6] = MZX(outmot); 23177+ H[7] = MZY(outmot); 23178+ H[8] = MZZ(outmot); 23179+ 23180+ Set_H_dref_to_ins(H); 23181+} 23182+ 23183+void db_FrameToReferenceRegistration::GenerateQuarterResImage(const unsigned char* const* im) 23184+{ 23185+ int input_h = m_im_height*2; 23186+ int input_w = m_im_width*2; 23187+ 23188+ for (int j = 0; j < input_h; j++) 23189+ { 23190+ const unsigned char* in_row_ptr = im[j]; 23191+ unsigned char* out_row_ptr = m_horz_smooth_subsample_image[j]+1; 23192+ 23193+ for (int i = 2; i < input_w-2; i += 2) 23194+ { 23195+ int smooth_val = ( 23196+ 6*in_row_ptr[i] + 23197+ ((in_row_ptr[i-1]+in_row_ptr[i+1])<<2) + 23198+ in_row_ptr[i-2]+in_row_ptr[i+2] 23199+ ) >> 4; 23200+ *out_row_ptr++ = (unsigned char) smooth_val; 23201+ 23202+ if ( (smooth_val < 0) || (smooth_val > 255)) 23203+ { 23204+ return; 23205+ } 23206+ 23207+ } 23208+ } 23209+ 23210+ for (int j = 2; j < input_h-2; j+=2) 23211+ { 23212+ 23213+ unsigned char* in_row_ptr = m_horz_smooth_subsample_image[j]; 23214+ unsigned char* out_row_ptr = m_quarter_res_image[j/2]; 23215+ 23216+ for (int i = 1; i < m_im_width-1; i++) 23217+ { 23218+ int smooth_val = ( 23219+ 6*in_row_ptr[i] + 23220+ ((in_row_ptr[i-m_im_width]+in_row_ptr[i+m_im_width]) << 2)+ 23221+ in_row_ptr[i-2*m_im_width]+in_row_ptr[i+2*m_im_width] 23222+ ) >> 4; 23223+ *out_row_ptr++ = (unsigned char)smooth_val; 23224+ 23225+ if ( (smooth_val < 0) || (smooth_val > 255)) 23226+ { 23227+ return; 23228+ } 23229+ 23230+ } 23231+ } 23232+} 23233diff --git a/benchmark/feature_stab/src/dbreg/dbreg.h b/benchmark/feature_stab/src/dbreg/dbreg.h 23234new file mode 100644 23235index 00000000..4eb24448 23236--- /dev/null 23237+++ b/benchmark/feature_stab/src/dbreg/dbreg.h 23238@@ -0,0 +1,581 @@ 23239+/* 23240+ * Copyright (C) 2011 The Android Open Source Project 23241+ * 23242+ * Licensed under the Apache License, Version 2.0 (the "License"); 23243+ * you may not use this file except in compliance with the License. 23244+ * You may obtain a copy of the License at 23245+ * 23246+ * http://www.apache.org/licenses/LICENSE-2.0 23247+ * 23248+ * Unless required by applicable law or agreed to in writing, software 23249+ * distributed under the License is distributed on an "AS IS" BASIS, 23250+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23251+ * See the License for the specific language governing permissions and 23252+ * limitations under the License. 23253+ */ 23254+ 23255+ 23256+#pragma once 23257+ 23258+#ifdef _WIN32 23259+#ifdef DBREG_EXPORTS 23260+#define DBREG_API __declspec(dllexport) 23261+#else 23262+#define DBREG_API __declspec(dllimport) 23263+#endif 23264+#else 23265+#define DBREG_API 23266+#endif 23267+ 23268+// @jke - the next few lines are for extracting timing data. TODO: Remove after test 23269+#define PROFILE 0 23270+ 23271+#include "dbstabsmooth.h" 23272+ 23273+#include <db_feature_detection.h> 23274+#include <db_feature_matching.h> 23275+#include <db_rob_image_homography.h> 23276+ 23277+#if PROFILE 23278+ #include <sys/time.h> 23279+#endif 23280+ 23281+/*! \mainpage db_FrameToReferenceRegistration 23282+ 23283+ \section intro Introduction 23284+ 23285+ db_FrameToReferenceRegistration provides a simple interface to a set of sophisticated algorithms for stabilizing 23286+ video sequences. As its name suggests, the class is used to compute parameters that will allow us to warp incoming video 23287+ frames and register them with respect to a so-called <i>reference</i> frame. The reference frame is simply the first 23288+ frame of a sequence; the registration process is that of estimating the parameters of a warp that can be applied to 23289+ subsequent frames to make those frames align with the reference. A video made up of these warped frames will be more 23290+ stable than the input video. 23291+ 23292+ For more technical information on the internal structure of the algorithms used within the db_FrameToRegistration class, 23293+ please follow this <a href="../Sarnoff image registration.docx">link</a>. 23294+ 23295+ \section usage Usage 23296+ In addition to the class constructor, there are two main functions of db_FrameToReferenceRegistration that are of 23297+ interest to the programmer. db_FrameToReferenceRegistration::Init(...) is used to initialize the parameters of the 23298+ registration algorithm. db_FrameToReferenceRegistration::AddFrame(...) is the method by which each new video frame 23299+ is introduced to the registration algorithm, and produces the estimated registration warp parameters. 23300+ 23301+ The following example illustrates how the major methods of the class db_FrameToReferenceRegistration can be used together 23302+ to calculate the registration parameters for an image sequence. In the example, the calls to the methods of 23303+ db_FrameToReferenceRegistration match those found in the API, but supporting code should be considered pseudo-code. 23304+ For a more complete example, please consult the source code for dbregtest. 23305+ 23306+ 23307+ \code 23308+ // feature-based image registration class: 23309+ db_FrameToReferenceRegistration reg; 23310+ 23311+ // Image data 23312+ const unsigned char * const * image_storage; 23313+ 23314+ // The 3x3 frame to reference registration parameters 23315+ double frame_to_ref_homography[9]; 23316+ 23317+ // a counter to count the number of frames processed. 23318+ unsigned long frame_counter; 23319+ // ... 23320+ 23321+ // main loop - keep going while there are images to process. 23322+ while (ImagesAreAvailable) 23323+ { 23324+ // Call functions to place latest data into image_storage 23325+ // ... 23326+ 23327+ // if the registration object is not yet initialized, then do so 23328+ // The arguments to this function are explained in the accompanying 23329+ // html API documentation 23330+ if (!reg.Initialized()) 23331+ { 23332+ reg.Init(w,h,motion_model_type,25,linear_polish,quarter_resolution, 23333+ DB_POINT_STANDARDDEV,reference_update_period, 23334+ do_motion_smoothing,motion_smoothing_gain, 23335+ DB_DEFAULT_NR_SAMPLES,DB_DEFAULT_CHUNK_SIZE, 23336+ nr_corners,max_disparity); 23337+ } 23338+ 23339+ // Present the new image data to the registration algorithm, 23340+ // with the result being stored in the frame_to_ref_homography 23341+ // variable. 23342+ reg.AddFrame(image_storage,frame_to_ref_homography); 23343+ 23344+ // frame_to_ref_homography now contains the stabilizing transform 23345+ // use this to warp the latest image for display, etc. 23346+ 23347+ // if this is the first frame, we need to tell the registration 23348+ // class to store the image as its reference. Otherwise, AddFrame 23349+ // takes care of that. 23350+ if (frame_counter == 0) 23351+ { 23352+ reg.UpdateReference(image_storage); 23353+ } 23354+ 23355+ // increment the frame counter 23356+ frame_counter++; 23357+ } 23358+ 23359+ \endcode 23360+ 23361+ */ 23362+ 23363+/*! 23364+ * Performs feature-based frame to reference image registration. 23365+ */ 23366+class DBREG_API db_FrameToReferenceRegistration 23367+{ 23368+public: 23369+ db_FrameToReferenceRegistration(void); 23370+ ~db_FrameToReferenceRegistration(); 23371+ 23372+ /*! 23373+ * Set parameters and allocate memory. Note: The default values of these parameters have been set to the values used for the android implementation (i.e. the demo APK). 23374+ * \param width image width 23375+ * \param height image height 23376+ * \param homography_type see definitions in \ref LMRobImageHomography 23377+ * \param max_iterations max number of polishing steps 23378+ * \param linear_polish whether to perform a linear polishing step after RANSAC 23379+ * \param quarter_resolution whether to process input images at quarter resolution (for computational efficiency) 23380+ * \param scale Cauchy scale coefficient (see db_ExpCauchyReprojectionError() ) 23381+ * \param reference_update_period how often to update the alignment reference (in units of number of frames) 23382+ * \param do_motion_smoothing whether to perform display reference smoothing 23383+ * \param motion_smoothing_gain weight factor to reflect how fast the display reference must follow the current frame if motion smoothing is enabled 23384+ * \param nr_samples number of times to compute a hypothesis 23385+ * \param chunk_size size of cost chunks 23386+ * \param cd_target_nr_corners target number of corners for corner detector 23387+ * \param cm_max_disparity maximum disparity search range for corner matcher (in units of ratio of image width) 23388+ * \param cm_use_smaller_matching_window if set to true, uses a correlation window of 5x5 instead of the default 11x11 23389+ * \param cd_nr_horz_blocks the number of horizontal blocks for the corner detector to partition the image 23390+ * \param cd_nr_vert_blocks the number of vertical blocks for the corner detector to partition the image 23391+ */ 23392+ void Init(int width, int height, 23393+ int homography_type = DB_HOMOGRAPHY_TYPE_DEFAULT, 23394+ int max_iterations = DB_DEFAULT_MAX_ITERATIONS, 23395+ bool linear_polish = false, 23396+ bool quarter_resolution = true, 23397+ double scale = DB_POINT_STANDARDDEV, 23398+ unsigned int reference_update_period = 3, 23399+ bool do_motion_smoothing = false, 23400+ double motion_smoothing_gain = 0.75, 23401+ int nr_samples = DB_DEFAULT_NR_SAMPLES, 23402+ int chunk_size = DB_DEFAULT_CHUNK_SIZE, 23403+ int cd_target_nr_corners = 500, 23404+ double cm_max_disparity = 0.2, 23405+ bool cm_use_smaller_matching_window = false, 23406+ int cd_nr_horz_blocks = 5, 23407+ int cd_nr_vert_blocks = 5); 23408+ 23409+ /*! 23410+ * Reset the transformation type that is being use to perform alignment. Use this to change the alignment type at run time. 23411+ * \param homography_type the type of transformation to use for performing alignment (see definitions in \ref LMRobImageHomography) 23412+ */ 23413+ void ResetHomographyType(int homography_type) { m_homography_type = homography_type; } 23414+ 23415+ /*! 23416+ * Enable/Disable motion smoothing. Use this to turn motion smoothing on/off at run time. 23417+ * \param enable flag indicating whether to turn the motion smoothing on or off. 23418+ */ 23419+ void ResetSmoothing(bool enable) { m_do_motion_smoothing = enable; } 23420+ 23421+ /*! 23422+ * Align an inspection image to an existing reference image, update the reference image if due and perform motion smoothing if enabled. 23423+ * \param im new inspection image 23424+ * \param H computed transformation from reference to inspection coordinate frame. Identity is returned if no reference frame was set. 23425+ * \param force_reference make this the new reference image 23426+ */ 23427+ int AddFrame(const unsigned char * const * im, double H[9], bool force_reference=false, bool prewarp=false); 23428+ 23429+ /*! 23430+ * Returns true if Init() was run. 23431+ */ 23432+ bool Initialized() const { return m_initialized; } 23433+ 23434+ /*! 23435+ * Returns true if the current frame is being used as the alignment reference. 23436+ */ 23437+ bool IsCurrentReference() const { return m_current_is_reference; } 23438+ 23439+ /*! 23440+ * Returns true if we need to call UpdateReference now. 23441+ */ 23442+ bool NeedReferenceUpdate(); 23443+ 23444+ /*! 23445+ * Returns the pointer reference to the alignment reference image data 23446+ */ 23447+ unsigned char ** GetReferenceImage() { return m_reference_image; } 23448+ 23449+ /*! 23450+ * Returns the pointer reference to the double array containing the homogeneous coordinates for the matched reference image corners. 23451+ */ 23452+ double * GetRefCorners() { return m_corners_ref; } 23453+ /*! 23454+ * Returns the pointer reference to the double array containing the homogeneous coordinates for the matched inspection image corners. 23455+ */ 23456+ double * GetInsCorners() { return m_corners_ins; } 23457+ /*! 23458+ * Returns the number of correspondences between the reference and inspection images. 23459+ */ 23460+ int GetNrMatches() { return m_nr_matches; } 23461+ 23462+ /*! 23463+ * Returns the number of corners detected in the current reference image. 23464+ */ 23465+ int GetNrRefCorners() { return m_nr_corners_ref; } 23466+ 23467+ /*! 23468+ * Returns the pointer to an array of indices that were found to be RANSAC inliers from the matched corner lists. 23469+ */ 23470+ int* GetInliers() { return m_inlier_indices; } 23471+ 23472+ /*! 23473+ * Returns the number of inliers from the RANSAC matching step. 23474+ */ 23475+ int GetNrInliers() { return m_num_inlier_indices; } 23476+ 23477+ //std::vector<int>& GetInliers(); 23478+ //void Polish(std::vector<int> &inlier_indices); 23479+ 23480+ /*! 23481+ * Perform a linear polishing step by re-estimating the alignment transformation using the RANSAC inliers. 23482+ * \param inlier_indices pointer to an array of indices that were found to be RANSAC inliers from the matched corner lists. 23483+ * \param num_inlier_indices number of inliers i.e. the length of the array passed as the first argument. 23484+ */ 23485+ void Polish(int *inlier_indices, int &num_inlier_indices); 23486+ 23487+ /*! 23488+ * Reset the motion smoothing parameters to their initial values. 23489+ */ 23490+ void ResetMotionSmoothingParameters() { m_stab_smoother.Init(); } 23491+ 23492+ /*! 23493+ * Update the alignment reference image to the specified image. 23494+ * \param im pointer to the image data to be used as the new alignment reference. 23495+ * \param subsample boolean flag to control whether the function should internally subsample the provided image to the size provided in the Init() function. 23496+ */ 23497+ int UpdateReference(const unsigned char * const * im, bool subsample = true, bool detect_corners = true); 23498+ 23499+ /*! 23500+ * Returns the transformation from the display reference to the alignment reference frame 23501+ */ 23502+ void Get_H_dref_to_ref(double H[9]); 23503+ /*! 23504+ * Returns the transformation from the display reference to the inspection reference frame 23505+ */ 23506+ void Get_H_dref_to_ins(double H[9]); 23507+ /*! 23508+ * Set the transformation from the display reference to the inspection reference frame 23509+ * \param H the transformation to set 23510+ */ 23511+ void Set_H_dref_to_ins(double H[9]); 23512+ 23513+ /*! 23514+ * Reset the display reference to the current frame. 23515+ */ 23516+ void ResetDisplayReference(); 23517+ 23518+ /*! 23519+ * Estimate a secondary motion model starting from the specified transformation. 23520+ * \param H the primary motion model to start from 23521+ */ 23522+ void EstimateSecondaryModel(double H[9]); 23523+ 23524+ /*! 23525+ * 23526+ */ 23527+ void SelectOutliers(); 23528+ 23529+ char *profile_string; 23530+ 23531+protected: 23532+ void Clean(); 23533+ void GenerateQuarterResImage(const unsigned char* const * im); 23534+ 23535+ int m_im_width; 23536+ int m_im_height; 23537+ 23538+ // RANSAC and refinement parameters: 23539+ int m_homography_type; 23540+ int m_max_iterations; 23541+ double m_scale; 23542+ int m_nr_samples; 23543+ int m_chunk_size; 23544+ double m_outlier_t2; 23545+ 23546+ // Whether to fit a linear model to just the inliers at the end 23547+ bool m_linear_polish; 23548+ double m_polish_C[36]; 23549+ double m_polish_D[6]; 23550+ 23551+ // local state 23552+ bool m_current_is_reference; 23553+ bool m_initialized; 23554+ 23555+ // inspection to reference homography: 23556+ double m_H_ref_to_ins[9]; 23557+ double m_H_dref_to_ref[9]; 23558+ 23559+ // feature extraction and matching: 23560+ db_CornerDetector_u m_cd; 23561+ db_Matcher_u m_cm; 23562+ 23563+ // length of corner arrays: 23564+ unsigned long m_max_nr_corners; 23565+ 23566+ // corner locations of reference image features: 23567+ double * m_x_corners_ref; 23568+ double * m_y_corners_ref; 23569+ int m_nr_corners_ref; 23570+ 23571+ // corner locations of inspection image features: 23572+ double * m_x_corners_ins; 23573+ double * m_y_corners_ins; 23574+ int m_nr_corners_ins; 23575+ 23576+ // length of match index arrays: 23577+ unsigned long m_max_nr_matches; 23578+ 23579+ // match indices: 23580+ int * m_match_index_ref; 23581+ int * m_match_index_ins; 23582+ int m_nr_matches; 23583+ 23584+ // pointer to internal copy of the reference image: 23585+ unsigned char ** m_reference_image; 23586+ 23587+ // pointer to internal copy of last aligned inspection image: 23588+ unsigned char ** m_aligned_ins_image; 23589+ 23590+ // pointer to quarter resolution image, if used. 23591+ unsigned char** m_quarter_res_image; 23592+ 23593+ // temporary storage for the quarter resolution image processing 23594+ unsigned char** m_horz_smooth_subsample_image; 23595+ 23596+ // temporary space for homography computation: 23597+ double * m_temp_double; 23598+ int * m_temp_int; 23599+ 23600+ // homogenous image point arrays: 23601+ double * m_corners_ref; 23602+ double * m_corners_ins; 23603+ 23604+ // Indices of the points within the match lists 23605+ int * m_inlier_indices; 23606+ int m_num_inlier_indices; 23607+ 23608+ //void ComputeInliers(double H[9], std::vector<int> &inlier_indices); 23609+ void ComputeInliers(double H[9]); 23610+ 23611+ // cost arrays: 23612+ void ComputeCostArray(); 23613+ bool m_sq_cost_computed; 23614+ double * m_sq_cost; 23615+ 23616+ // cost histogram: 23617+ void ComputeCostHistogram(); 23618+ int *m_cost_histogram; 23619+ 23620+ void SetOutlierThreshold(); 23621+ 23622+ // utility function for smoothing the motion parameters. 23623+ void SmoothMotion(void); 23624+ 23625+private: 23626+ double m_K[9]; 23627+ const int m_over_allocation; 23628+ 23629+ bool m_reference_set; 23630+ 23631+ // Maximum number of inliers seen until now w.r.t the current reference frame 23632+ int m_max_inlier_count; 23633+ 23634+ // Number of cost histogram bins: 23635+ int m_nr_bins; 23636+ // All costs above this threshold get put into the last bin: 23637+ int m_max_cost_pix; 23638+ 23639+ // whether to quarter the image resolution for processing, or not 23640+ bool m_quarter_resolution; 23641+ 23642+ // the period (in number of frames) for reference update. 23643+ unsigned int m_reference_update_period; 23644+ 23645+ // the number of frames processed so far. 23646+ unsigned int m_nr_frames_processed; 23647+ 23648+ // smoother for motion transformations 23649+ db_StabilizationSmoother m_stab_smoother; 23650+ 23651+ // boolean to control whether motion smoothing occurs (or not) 23652+ bool m_do_motion_smoothing; 23653+ 23654+ // double to set the gain for motion smoothing 23655+ double m_motion_smoothing_gain; 23656+}; 23657+/*! 23658+ Create look-up tables to undistort images. Only Bougeut (Matlab toolkit) 23659+ is currently supported. Can be used with db_WarpImageLut_u(). 23660+ \code 23661+ xd = H*xs; 23662+ xd = xd/xd(3); 23663+ \endcode 23664+ \param lut_x pre-allocated float image 23665+ \param lut_y pre-allocated float image 23666+ \param w width 23667+ \param h height 23668+ \param H image homography from source to destination 23669+ */ 23670+inline void db_GenerateHomographyLut(float ** lut_x,float ** lut_y,int w,int h,const double H[9]) 23671+{ 23672+ assert(lut_x && lut_y); 23673+ double x[3] = {0.0,0.0,1.0}; 23674+ double xb[3]; 23675+ 23676+/* 23677+ double xl[3]; 23678+ 23679+ // Determine the output coordinate system ROI 23680+ double Hinv[9]; 23681+ db_InvertAffineTransform(Hinv,H); 23682+ db_Multiply3x3_3x1(xl, Hinv, x); 23683+ xl[0] = db_SafeDivision(xl[0],xl[2]); 23684+ xl[1] = db_SafeDivision(xl[1],xl[2]); 23685+*/ 23686+ 23687+ for ( int i = 0; i < w; ++i ) 23688+ for ( int j = 0; j < h; ++j ) 23689+ { 23690+ x[0] = double(i); 23691+ x[1] = double(j); 23692+ db_Multiply3x3_3x1(xb, H, x); 23693+ xb[0] = db_SafeDivision(xb[0],xb[2]); 23694+ xb[1] = db_SafeDivision(xb[1],xb[2]); 23695+ 23696+ lut_x[j][i] = float(xb[0]); 23697+ lut_y[j][i] = float(xb[1]); 23698+ } 23699+} 23700+ 23701+/*! 23702+ * Perform a look-up table warp for packed RGB ([rgbrgbrgb...]) images. 23703+ * The LUTs must be float images of the same size as source image. 23704+ * The source value x_s is determined from destination (x_d,y_d) through lut_x 23705+ * and y_s is determined from lut_y: 23706+ \code 23707+ x_s = lut_x[y_d][x_d]; 23708+ y_s = lut_y[y_d][x_d]; 23709+ \endcode 23710+ 23711+ * \param src source image (w*3 by h) 23712+ * \param dst destination image (w*3 by h) 23713+ * \param w width 23714+ * \param h height 23715+ * \param lut_x LUT for x 23716+ * \param lut_y LUT for y 23717+ */ 23718+inline void db_WarpImageLutFast_rgb(const unsigned char * const * src, unsigned char ** dst, int w, int h, 23719+ const float * const * lut_x, const float * const * lut_y) 23720+{ 23721+ assert(src && dst); 23722+ int xd=0, yd=0; 23723+ 23724+ for ( int i = 0; i < w; ++i ) 23725+ for ( int j = 0; j < h; ++j ) 23726+ { 23727+ xd = static_cast<unsigned int>(lut_x[j][i]); 23728+ yd = static_cast<unsigned int>(lut_y[j][i]); 23729+ if ( xd >= w || yd >= h || 23730+ xd < 0 || yd < 0) 23731+ { 23732+ dst[j][3*i ] = 0; 23733+ dst[j][3*i+1] = 0; 23734+ dst[j][3*i+2] = 0; 23735+ } 23736+ else 23737+ { 23738+ dst[j][3*i ] = src[yd][3*xd ]; 23739+ dst[j][3*i+1] = src[yd][3*xd+1]; 23740+ dst[j][3*i+2] = src[yd][3*xd+2]; 23741+ } 23742+ } 23743+} 23744+ 23745+inline unsigned char db_BilinearInterpolationRGB(double y, double x, const unsigned char * const * v, int offset) 23746+{ 23747+ int floor_x=(int) x; 23748+ int floor_y=(int) y; 23749+ 23750+ int ceil_x=floor_x+1; 23751+ int ceil_y=floor_y+1; 23752+ 23753+ unsigned char f00 = v[floor_y][3*floor_x+offset]; 23754+ unsigned char f01 = v[floor_y][3*ceil_x+offset]; 23755+ unsigned char f10 = v[ceil_y][3*floor_x+offset]; 23756+ unsigned char f11 = v[ceil_y][3*ceil_x+offset]; 23757+ 23758+ double xl = x-floor_x; 23759+ double yl = y-floor_y; 23760+ 23761+ return (unsigned char)(f00*(1-yl)*(1-xl) + f10*yl*(1-xl) + f01*(1-yl)*xl + f11*yl*xl); 23762+} 23763+ 23764+inline void db_WarpImageLutBilinear_rgb(const unsigned char * const * src, unsigned char ** dst, int w, int h, 23765+ const float * const * lut_x, const float * const * lut_y) 23766+{ 23767+ assert(src && dst); 23768+ double xd=0.0, yd=0.0; 23769+ 23770+ for ( int i = 0; i < w; ++i ) 23771+ for ( int j = 0; j < h; ++j ) 23772+ { 23773+ xd = static_cast<double>(lut_x[j][i]); 23774+ yd = static_cast<double>(lut_y[j][i]); 23775+ if ( xd > w-2 || yd > h-2 || 23776+ xd < 0.0 || yd < 0.0) 23777+ { 23778+ dst[j][3*i ] = 0; 23779+ dst[j][3*i+1] = 0; 23780+ dst[j][3*i+2] = 0; 23781+ } 23782+ else 23783+ { 23784+ dst[j][3*i ] = db_BilinearInterpolationRGB(yd,xd,src,0); 23785+ dst[j][3*i+1] = db_BilinearInterpolationRGB(yd,xd,src,1); 23786+ dst[j][3*i+2] = db_BilinearInterpolationRGB(yd,xd,src,2); 23787+ } 23788+ } 23789+} 23790+ 23791+inline double SquaredInhomogenousHomographyError(double y[3],double H[9],double x[3]){ 23792+ double x0,x1,x2,mult; 23793+ double sd; 23794+ 23795+ x0=H[0]*x[0]+H[1]*x[1]+H[2]; 23796+ x1=H[3]*x[0]+H[4]*x[1]+H[5]; 23797+ x2=H[6]*x[0]+H[7]*x[1]+H[8]; 23798+ mult=1.0/((x2!=0.0)?x2:1.0); 23799+ sd=(y[0]-x0*mult)*(y[0]-x0*mult)+(y[1]-x1*mult)*(y[1]-x1*mult); 23800+ 23801+ return(sd); 23802+} 23803+ 23804+ 23805+// functions related to profiling 23806+#if PROFILE 23807+ 23808+/* return current time in milliseconds */ 23809+static double 23810+now_ms(void) 23811+{ 23812+ //struct timespec res; 23813+ struct timeval res; 23814+ //clock_gettime(CLOCK_REALTIME, &res); 23815+ gettimeofday(&res, NULL); 23816+ return 1000.0*res.tv_sec + (double)res.tv_usec/1e3; 23817+} 23818+ 23819+#endif 23820diff --git a/benchmark/feature_stab/src/dbreg/dbstabsmooth.cpp b/benchmark/feature_stab/src/dbreg/dbstabsmooth.cpp 23821new file mode 100644 23822index 00000000..03608c69 23823--- /dev/null 23824+++ b/benchmark/feature_stab/src/dbreg/dbstabsmooth.cpp 23825@@ -0,0 +1,301 @@ 23826+/* 23827+ * Copyright (C) 2011 The Android Open Source Project 23828+ * 23829+ * Licensed under the Apache License, Version 2.0 (the "License"); 23830+ * you may not use this file except in compliance with the License. 23831+ * You may obtain a copy of the License at 23832+ * 23833+ * http://www.apache.org/licenses/LICENSE-2.0 23834+ * 23835+ * Unless required by applicable law or agreed to in writing, software 23836+ * distributed under the License is distributed on an "AS IS" BASIS, 23837+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23838+ * See the License for the specific language governing permissions and 23839+ * limitations under the License. 23840+ */ 23841+ 23842+#include <stdlib.h> 23843+#include "dbstabsmooth.h" 23844+ 23845+///// TODO TODO ////////// Replace this with the actual definition from Jayan's reply ///////////// 23846+#define vp_copy_motion_no_id vp_copy_motion 23847+/////////////////////////////////////////////////////////////////////////////////////////////////// 23848+ 23849+db_StabilizationSmoother::db_StabilizationSmoother() 23850+{ 23851+ Init(); 23852+} 23853+ 23854+void db_StabilizationSmoother::Init() 23855+{ 23856+ f_smoothOn = true; 23857+ f_smoothReset = false; 23858+ f_smoothFactor = 1.0f; 23859+ f_minDampingFactor = 0.2f; 23860+ f_zoom = 1.0f; 23861+ VP_MOTION_ID(f_motLF); 23862+ VP_MOTION_ID(f_imotLF); 23863+ f_hsize = 0; 23864+ f_vsize = 0; 23865+ 23866+ VP_MOTION_ID(f_disp_mot); 23867+ VP_MOTION_ID(f_src_mot); 23868+ VP_MOTION_ID(f_diff_avg); 23869+ 23870+ for( int i = 0; i < MOTION_ARRAY-1; i++) { 23871+ VP_MOTION_ID(f_hist_mot_speed[i]); 23872+ VP_MOTION_ID(f_hist_mot[i]); 23873+ VP_MOTION_ID(f_hist_diff_mot[i]); 23874+ } 23875+ VP_MOTION_ID(f_hist_mot[MOTION_ARRAY-1]); 23876+ 23877+} 23878+ 23879+db_StabilizationSmoother::~db_StabilizationSmoother() 23880+{} 23881+ 23882+ 23883+bool db_StabilizationSmoother::smoothMotion(VP_MOTION *inmot, VP_MOTION *outmot) 23884+{ 23885+ VP_MOTION_ID(f_motLF); 23886+ VP_MOTION_ID(f_imotLF); 23887+ f_motLF.insid = inmot->refid; 23888+ f_motLF.refid = inmot->insid; 23889+ 23890+ if(f_smoothOn) { 23891+ if(!f_smoothReset) { 23892+ MXX(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MXX(f_motLF) + (1.0-f_smoothFactor)* (double) MXX(*inmot)); 23893+ MXY(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MXY(f_motLF) + (1.0-f_smoothFactor)* (double) MXY(*inmot)); 23894+ MXZ(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MXZ(f_motLF) + (1.0-f_smoothFactor)* (double) MXZ(*inmot)); 23895+ MXW(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MXW(f_motLF) + (1.0-f_smoothFactor)* (double) MXW(*inmot)); 23896+ 23897+ MYX(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MYX(f_motLF) + (1.0-f_smoothFactor)* (double) MYX(*inmot)); 23898+ MYY(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MYY(f_motLF) + (1.0-f_smoothFactor)* (double) MYY(*inmot)); 23899+ MYZ(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MYZ(f_motLF) + (1.0-f_smoothFactor)* (double) MYZ(*inmot)); 23900+ MYW(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MYW(f_motLF) + (1.0-f_smoothFactor)* (double) MYW(*inmot)); 23901+ 23902+ MZX(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MZX(f_motLF) + (1.0-f_smoothFactor)* (double) MZX(*inmot)); 23903+ MZY(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MZY(f_motLF) + (1.0-f_smoothFactor)* (double) MZY(*inmot)); 23904+ MZZ(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MZZ(f_motLF) + (1.0-f_smoothFactor)* (double) MZZ(*inmot)); 23905+ MZW(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MZW(f_motLF) + (1.0-f_smoothFactor)* (double) MZW(*inmot)); 23906+ 23907+ MWX(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MWX(f_motLF) + (1.0-f_smoothFactor)* (double) MWX(*inmot)); 23908+ MWY(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MWY(f_motLF) + (1.0-f_smoothFactor)* (double) MWY(*inmot)); 23909+ MWZ(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MWZ(f_motLF) + (1.0-f_smoothFactor)* (double) MWZ(*inmot)); 23910+ MWW(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MWW(f_motLF) + (1.0-f_smoothFactor)* (double) MWW(*inmot)); 23911+ } 23912+ else 23913+ vp_copy_motion_no_id(inmot, &f_motLF); // f_smoothFactor = 0.0 23914+ 23915+ // Only allow LF motion to be compensated. Remove HF motion from 23916+ // the output transformation 23917+ if(!vp_invert_motion(&f_motLF, &f_imotLF)) 23918+ return false; 23919+ 23920+ if(!vp_cascade_motion(&f_imotLF, inmot, outmot)) 23921+ return false; 23922+ } 23923+ else { 23924+ vp_copy_motion_no_id(inmot, outmot); 23925+ } 23926+ 23927+ return true; 23928+} 23929+ 23930+bool db_StabilizationSmoother::smoothMotionAdaptive(/*VP_BIMG *bimg,*/int hsize, int vsize, VP_MOTION *inmot, VP_MOTION *outmot) 23931+{ 23932+ VP_MOTION tmpMotion, testMotion; 23933+ VP_PAR p1x, p2x, p3x, p4x; 23934+ VP_PAR p1y, p2y, p3y, p4y; 23935+ double smoothFactor; 23936+ double minSmoothFactor = f_minDampingFactor; 23937+ 23938+// int hsize = bimg->w; 23939+// int vsize = bimg->h; 23940+ double border_factor = 0.01;//0.2; 23941+ double border_x = border_factor * hsize; 23942+ double border_y = border_factor * vsize; 23943+ 23944+ VP_MOTION_ID(f_motLF); 23945+ VP_MOTION_ID(f_imotLF); 23946+ VP_MOTION_ID(testMotion); 23947+ VP_MOTION_ID(tmpMotion); 23948+ 23949+ if (f_smoothOn) { 23950+ VP_MOTION identityMotion; 23951+ VP_MOTION_ID(identityMotion); // initialize the motion 23952+ vp_copy_motion(inmot/*in*/, &testMotion/*out*/); 23953+ VP_PAR delta = vp_motion_cornerdiff(&testMotion, &identityMotion, 0, 0,(int)hsize, (int)vsize); 23954+ 23955+ smoothFactor = 0.99 - 0.0015 * delta; 23956+ 23957+ if(smoothFactor < minSmoothFactor) 23958+ smoothFactor = minSmoothFactor; 23959+ 23960+ // Find the amount of motion that must be compensated so that no "border" pixels are seen in the stable video 23961+ for (; smoothFactor >= minSmoothFactor; smoothFactor -= 0.01) { 23962+ // Compute the smoothed motion 23963+ if(!smoothMotion(inmot, &tmpMotion, smoothFactor)) 23964+ break; 23965+ 23966+ // TmpMotion, or Qsi where s is the smoothed display reference and i is the 23967+ // current image, tells us how points in the S co-ordinate system map to 23968+ // points in the I CS. We would like to check whether the four corners of the 23969+ // warped and smoothed display reference lies entirely within the I co-ordinate 23970+ // system. If yes, then the amount of smoothing is sufficient so that NO 23971+ // border pixels are seen at the output. We test for f_smoothFactor terms 23972+ // between 0.9 and 1.0, in steps of 0.01, and between 0.5 ands 0.9 in steps of 0.1 23973+ 23974+ (void) vp_zoom_motion2d(&tmpMotion, &testMotion, 1, hsize, vsize, (double)f_zoom); // needs to return bool 23975+ 23976+ VP_WARP_POINT_2D(0, 0, testMotion, p1x, p1y); 23977+ VP_WARP_POINT_2D(hsize - 1, 0, testMotion, p2x, p2y); 23978+ VP_WARP_POINT_2D(hsize - 1, vsize - 1, testMotion, p3x, p3y); 23979+ VP_WARP_POINT_2D(0, vsize - 1, testMotion, p4x, p4y); 23980+ 23981+ if (!is_point_in_rect((double)p1x,(double)p1y,-border_x,-border_y,(double)(hsize+2.0*border_x),(double)(vsize+2.0*border_y))) { 23982+ continue; 23983+ } 23984+ if (!is_point_in_rect((double)p2x, (double)p2y,-border_x,-border_y,(double)(hsize+2.0*border_x),(double)(vsize+2.0*border_y))) { 23985+ continue; 23986+ } 23987+ if (!is_point_in_rect((double)p3x,(double)p3y,-border_x,-border_y,(double)(hsize+2.0*border_x),(double)(vsize+2.0*border_y))) { 23988+ continue; 23989+ } 23990+ if (!is_point_in_rect((double)p4x, (double)p4y,-border_x,-border_y,(double)(hsize+2.0*border_x),(double)(vsize+2.0*border_y))) { 23991+ continue; 23992+ } 23993+ 23994+ // If we get here, then all the points are in the rectangle. 23995+ // Therefore, break out of this loop 23996+ break; 23997+ } 23998+ 23999+ // if we get here and f_smoothFactor <= fMinDampingFactor, reset the stab reference 24000+ if (smoothFactor < f_minDampingFactor) 24001+ smoothFactor = f_minDampingFactor; 24002+ 24003+ // use the smoothed motion for stabilization 24004+ vp_copy_motion_no_id(&tmpMotion/*in*/, outmot/*out*/); 24005+ } 24006+ else 24007+ { 24008+ vp_copy_motion_no_id(inmot, outmot); 24009+ } 24010+ 24011+ return true; 24012+} 24013+ 24014+bool db_StabilizationSmoother::smoothMotion(VP_MOTION *inmot, VP_MOTION *outmot, double smooth_factor) 24015+{ 24016+ f_motLF.insid = inmot->refid; 24017+ f_motLF.refid = inmot->insid; 24018+ 24019+ if(f_smoothOn) { 24020+ if(!f_smoothReset) { 24021+ MXX(f_motLF) = (VP_PAR) (smooth_factor*(double) MXX(f_motLF) + (1.0-smooth_factor)* (double) MXX(*inmot)); 24022+ MXY(f_motLF) = (VP_PAR) (smooth_factor*(double) MXY(f_motLF) + (1.0-smooth_factor)* (double) MXY(*inmot)); 24023+ MXZ(f_motLF) = (VP_PAR) (smooth_factor*(double) MXZ(f_motLF) + (1.0-smooth_factor)* (double) MXZ(*inmot)); 24024+ MXW(f_motLF) = (VP_PAR) (smooth_factor*(double) MXW(f_motLF) + (1.0-smooth_factor)* (double) MXW(*inmot)); 24025+ 24026+ MYX(f_motLF) = (VP_PAR) (smooth_factor*(double) MYX(f_motLF) + (1.0-smooth_factor)* (double) MYX(*inmot)); 24027+ MYY(f_motLF) = (VP_PAR) (smooth_factor*(double) MYY(f_motLF) + (1.0-smooth_factor)* (double) MYY(*inmot)); 24028+ MYZ(f_motLF) = (VP_PAR) (smooth_factor*(double) MYZ(f_motLF) + (1.0-smooth_factor)* (double) MYZ(*inmot)); 24029+ MYW(f_motLF) = (VP_PAR) (smooth_factor*(double) MYW(f_motLF) + (1.0-smooth_factor)* (double) MYW(*inmot)); 24030+ 24031+ MZX(f_motLF) = (VP_PAR) (smooth_factor*(double) MZX(f_motLF) + (1.0-smooth_factor)* (double) MZX(*inmot)); 24032+ MZY(f_motLF) = (VP_PAR) (smooth_factor*(double) MZY(f_motLF) + (1.0-smooth_factor)* (double) MZY(*inmot)); 24033+ MZZ(f_motLF) = (VP_PAR) (smooth_factor*(double) MZZ(f_motLF) + (1.0-smooth_factor)* (double) MZZ(*inmot)); 24034+ MZW(f_motLF) = (VP_PAR) (smooth_factor*(double) MZW(f_motLF) + (1.0-smooth_factor)* (double) MZW(*inmot)); 24035+ 24036+ MWX(f_motLF) = (VP_PAR) (smooth_factor*(double) MWX(f_motLF) + (1.0-smooth_factor)* (double) MWX(*inmot)); 24037+ MWY(f_motLF) = (VP_PAR) (smooth_factor*(double) MWY(f_motLF) + (1.0-smooth_factor)* (double) MWY(*inmot)); 24038+ MWZ(f_motLF) = (VP_PAR) (smooth_factor*(double) MWZ(f_motLF) + (1.0-smooth_factor)* (double) MWZ(*inmot)); 24039+ MWW(f_motLF) = (VP_PAR) (smooth_factor*(double) MWW(f_motLF) + (1.0-smooth_factor)* (double) MWW(*inmot)); 24040+ } 24041+ else 24042+ vp_copy_motion_no_id(inmot, &f_motLF); // smooth_factor = 0.0 24043+ 24044+ // Only allow LF motion to be compensated. Remove HF motion from 24045+ // the output transformation 24046+ if(!vp_invert_motion(&f_motLF, &f_imotLF)) 24047+ return false; 24048+ 24049+ if(!vp_cascade_motion(&f_imotLF, inmot, outmot)) 24050+ return false; 24051+ } 24052+ else { 24053+ vp_copy_motion_no_id(inmot, outmot); 24054+ } 24055+ 24056+ return true; 24057+} 24058+ 24059+//! Overloaded smoother function that takes in user-specidied smoothing factor 24060+bool 24061+db_StabilizationSmoother::smoothMotion1(VP_MOTION *inmot, VP_MOTION *outmot, VP_MOTION *motLF, VP_MOTION *imotLF, double factor) 24062+{ 24063+ 24064+ if(!f_smoothOn) { 24065+ vp_copy_motion(inmot, outmot); 24066+ return true; 24067+ } 24068+ else { 24069+ if(!f_smoothReset) { 24070+ MXX(*motLF) = (VP_PAR) (factor*(double) MXX(*motLF) + (1.0-factor)* (double) MXX(*inmot)); 24071+ MXY(*motLF) = (VP_PAR) (factor*(double) MXY(*motLF) + (1.0-factor)* (double) MXY(*inmot)); 24072+ MXZ(*motLF) = (VP_PAR) (factor*(double) MXZ(*motLF) + (1.0-factor)* (double) MXZ(*inmot)); 24073+ MXW(*motLF) = (VP_PAR) (factor*(double) MXW(*motLF) + (1.0-factor)* (double) MXW(*inmot)); 24074+ 24075+ MYX(*motLF) = (VP_PAR) (factor*(double) MYX(*motLF) + (1.0-factor)* (double) MYX(*inmot)); 24076+ MYY(*motLF) = (VP_PAR) (factor*(double) MYY(*motLF) + (1.0-factor)* (double) MYY(*inmot)); 24077+ MYZ(*motLF) = (VP_PAR) (factor*(double) MYZ(*motLF) + (1.0-factor)* (double) MYZ(*inmot)); 24078+ MYW(*motLF) = (VP_PAR) (factor*(double) MYW(*motLF) + (1.0-factor)* (double) MYW(*inmot)); 24079+ 24080+ MZX(*motLF) = (VP_PAR) (factor*(double) MZX(*motLF) + (1.0-factor)* (double) MZX(*inmot)); 24081+ MZY(*motLF) = (VP_PAR) (factor*(double) MZY(*motLF) + (1.0-factor)* (double) MZY(*inmot)); 24082+ MZZ(*motLF) = (VP_PAR) (factor*(double) MZZ(*motLF) + (1.0-factor)* (double) MZZ(*inmot)); 24083+ MZW(*motLF) = (VP_PAR) (factor*(double) MZW(*motLF) + (1.0-factor)* (double) MZW(*inmot)); 24084+ 24085+ MWX(*motLF) = (VP_PAR) (factor*(double) MWX(*motLF) + (1.0-factor)* (double) MWX(*inmot)); 24086+ MWY(*motLF) = (VP_PAR) (factor*(double) MWY(*motLF) + (1.0-factor)* (double) MWY(*inmot)); 24087+ MWZ(*motLF) = (VP_PAR) (factor*(double) MWZ(*motLF) + (1.0-factor)* (double) MWZ(*inmot)); 24088+ MWW(*motLF) = (VP_PAR) (factor*(double) MWW(*motLF) + (1.0-factor)* (double) MWW(*inmot)); 24089+ } 24090+ else { 24091+ vp_copy_motion(inmot, motLF); 24092+ } 24093+ // Only allow LF motion to be compensated. Remove HF motion from the output transformation 24094+ if(!vp_invert_motion(motLF, imotLF)) { 24095+#if DEBUG_PRINT 24096+ printfOS("Invert failed \n"); 24097+#endif 24098+ return false; 24099+ } 24100+ if(!vp_cascade_motion(imotLF, inmot, outmot)) { 24101+#if DEBUG_PRINT 24102+ printfOS("cascade failed \n"); 24103+#endif 24104+ return false; 24105+ } 24106+ } 24107+ return true; 24108+} 24109+ 24110+ 24111+ 24112+ 24113+bool db_StabilizationSmoother::is_point_in_rect(double px, double py, double rx, double ry, double w, double h) 24114+{ 24115+ if (px < rx) 24116+ return(false); 24117+ if (px >= rx + w) 24118+ return(false); 24119+ if (py < ry) 24120+ return(false); 24121+ if (py >= ry + h) 24122+ return(false); 24123+ 24124+ return(true); 24125+} 24126+ 24127diff --git a/benchmark/feature_stab/src/dbreg/dbstabsmooth.h b/benchmark/feature_stab/src/dbreg/dbstabsmooth.h 24128new file mode 100644 24129index 00000000..f03546ef 24130--- /dev/null 24131+++ b/benchmark/feature_stab/src/dbreg/dbstabsmooth.h 24132@@ -0,0 +1,157 @@ 24133+/* 24134+ * Copyright (C) 2011 The Android Open Source Project 24135+ * 24136+ * Licensed under the Apache License, Version 2.0 (the "License"); 24137+ * you may not use this file except in compliance with the License. 24138+ * You may obtain a copy of the License at 24139+ * 24140+ * http://www.apache.org/licenses/LICENSE-2.0 24141+ * 24142+ * Unless required by applicable law or agreed to in writing, software 24143+ * distributed under the License is distributed on an "AS IS" BASIS, 24144+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24145+ * See the License for the specific language governing permissions and 24146+ * limitations under the License. 24147+ */ 24148+ 24149+#pragma once 24150+ 24151+ 24152+#ifdef _WIN32 24153+#ifdef DBREG_EXPORTS 24154+#define DBREG_API __declspec(dllexport) 24155+#else 24156+#define DBREG_API __declspec(dllimport) 24157+#endif 24158+#else 24159+#define DBREG_API 24160+#endif 24161+ 24162+extern "C" { 24163+#include "vp_motionmodel.h" 24164+} 24165+ 24166+#define MOTION_ARRAY 5 24167+ 24168+ 24169+/*! 24170+ * Performs smoothing on the motion estimate from feature_stab. 24171+ */ 24172+class DBREG_API db_StabilizationSmoother 24173+{ 24174+public: 24175+ db_StabilizationSmoother(); 24176+ ~db_StabilizationSmoother(); 24177+ 24178+ /*! 24179+ * Initialize parameters for stab-smoother. 24180+ */ 24181+ void Init(); 24182+ 24183+ //! Smothing type 24184+ typedef enum { 24185+ SimpleSmooth = 0, //!< simple smooth 24186+ AdaptSmooth = 1, //!< adaptive smooth 24187+ PanSmooth = 2 //!< pan motion smooth 24188+ } SmoothType; 24189+ 24190+ /*! 24191+ * Smooth-motion is to do a weight-average between the current affine and 24192+ * motLF. The way to change the affine is only for the display purpose. 24193+ * It removes the high frequency motion and keep the low frequency motion 24194+ * to the display. IIR implmentation. 24195+ * \param inmot input motion parameters 24196+ * \param outmot smoothed output motion parameters 24197+ */ 24198+ bool smoothMotion(VP_MOTION *inmot, VP_MOTION *outmot); 24199+ 24200+ /*! 24201+ * The adaptive smoothing version of the above fixed smoothing function. 24202+ * \param hsize width of the image being aligned 24203+ * \param vsize height of the image being aligned 24204+ * \param inmot input motion parameters 24205+ * \param outmot smoothed output motion parameters 24206+ */ 24207+ bool smoothMotionAdaptive(/*VP_BIMG *bimg,*/int hsize, int vsize, VP_MOTION *inmot, VP_MOTION *outmot); 24208+ bool smoothPanMotion_1(VP_MOTION *inmot, VP_MOTION *outmot); 24209+ bool smoothPanMotion_2(VP_MOTION *inmot, VP_MOTION *outmot); 24210+ 24211+ /*! 24212+ * Set the smoothing factor for the stab-smoother. 24213+ * \param factor the factor value to set 24214+ */ 24215+ inline void setSmoothingFactor(float factor) { f_smoothFactor = factor; } 24216+ 24217+ /*! 24218+ * Reset smoothing 24219+ */ 24220+ inline void resetSmoothing(bool flag) { f_smoothReset = flag; } 24221+ /*! 24222+ * Set the zoom factor value. 24223+ * \param zoom the value to set to 24224+ */ 24225+ inline void setZoomFactor(float zoom) { f_zoom = zoom; } 24226+ /*! 24227+ * Set the minimum damping factor value. 24228+ * \param factor the value to set to 24229+ */ 24230+ inline void setminDampingFactor(float factor) { f_minDampingFactor = factor; } 24231+ 24232+ /*! 24233+ * Returns the current smoothing factor. 24234+ */ 24235+ inline float getSmoothingFactor(void) { return f_smoothFactor; } 24236+ /*! 24237+ * Returns the current zoom factor. 24238+ */ 24239+ inline float getZoomFactor(void) { return f_zoom; } 24240+ /*! 24241+ * Returns the current minimum damping factor. 24242+ */ 24243+ inline float getminDampingFactor(void) { return f_minDampingFactor; } 24244+ /*! 24245+ * Returns the current state of the smoothing reset flag. 24246+ */ 24247+ inline bool getSmoothReset(void) { return f_smoothReset; } 24248+ /*! 24249+ * Returns the current low frequency motion parameters. 24250+ */ 24251+ inline VP_MOTION getMotLF(void) { return f_motLF; } 24252+ /*! 24253+ * Returns the inverse of the current low frequency motion parameters. 24254+ */ 24255+ inline VP_MOTION getImotLF(void) { return f_imotLF; } 24256+ /*! 24257+ * Set the dimensions of the alignment image. 24258+ * \param hsize width of the image 24259+ * \param vsize height of the image 24260+ */ 24261+ inline void setSize(int hsize, int vsize) { f_hsize = hsize; f_vsize = vsize; } 24262+ 24263+protected: 24264+ 24265+ bool smoothMotion(VP_MOTION *inmot, VP_MOTION *outmot, double smooth_factor); 24266+ bool smoothMotion1(VP_MOTION *inmot, VP_MOTION *outmot, VP_MOTION *motLF, VP_MOTION *imotLF, double smooth_factor); 24267+ void iterativeSmooth(VP_MOTION *input, VP_MOTION *output, double border_factor); 24268+ bool is_point_in_rect(double px, double py, double rx, double ry, double w, double h); 24269+ 24270+ 24271+private: 24272+ int f_hsize; 24273+ int f_vsize; 24274+ bool f_smoothOn; 24275+ bool f_smoothReset; 24276+ float f_smoothFactor; 24277+ float f_minDampingFactor; 24278+ float f_zoom; 24279+ VP_MOTION f_motLF; 24280+ VP_MOTION f_imotLF; 24281+ VP_MOTION f_hist_mot[MOTION_ARRAY]; 24282+ VP_MOTION f_hist_mot_speed[MOTION_ARRAY-1]; 24283+ VP_MOTION f_hist_diff_mot[MOTION_ARRAY-1]; 24284+ VP_MOTION f_disp_mot; 24285+ VP_MOTION f_src_mot; 24286+ VP_MOTION f_diff_avg; 24287+ 24288+}; 24289+ 24290diff --git a/benchmark/feature_stab/src/dbreg/targetver.h b/benchmark/feature_stab/src/dbreg/targetver.h 24291new file mode 100644 24292index 00000000..3ca3e879 24293--- /dev/null 24294+++ b/benchmark/feature_stab/src/dbreg/targetver.h 24295@@ -0,0 +1,40 @@ 24296+/* 24297+ * Copyright (C) 2011 The Android Open Source Project 24298+ * 24299+ * Licensed under the Apache License, Version 2.0 (the "License"); 24300+ * you may not use this file except in compliance with the License. 24301+ * You may obtain a copy of the License at 24302+ * 24303+ * http://www.apache.org/licenses/LICENSE-2.0 24304+ * 24305+ * Unless required by applicable law or agreed to in writing, software 24306+ * distributed under the License is distributed on an "AS IS" BASIS, 24307+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24308+ * See the License for the specific language governing permissions and 24309+ * limitations under the License. 24310+ */ 24311+ 24312+#pragma once 24313+ 24314+// The following macros define the minimum required platform. The minimum required platform 24315+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run 24316+// your application. The macros work by enabling all features available on platform versions up to and 24317+// including the version specified. 24318+ 24319+// Modify the following defines if you have to target a platform prior to the ones specified below. 24320+// Refer to MSDN for the latest info on corresponding values for different platforms. 24321+#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. 24322+#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows. 24323+#endif 24324+ 24325+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. 24326+#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. 24327+#endif 24328+ 24329+#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. 24330+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. 24331+#endif 24332+ 24333+#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. 24334+#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. 24335+#endif 24336diff --git a/benchmark/feature_stab/src/dbreg/vp_motionmodel.c b/benchmark/feature_stab/src/dbreg/vp_motionmodel.c 24337new file mode 100644 24338index 00000000..1f6af15b 24339--- /dev/null 24340+++ b/benchmark/feature_stab/src/dbreg/vp_motionmodel.c 24341@@ -0,0 +1,377 @@ 24342+/* 24343+ * Copyright (C) 2011 The Android Open Source Project 24344+ * 24345+ * Licensed under the Apache License, Version 2.0 (the "License"); 24346+ * you may not use this file except in compliance with the License. 24347+ * You may obtain a copy of the License at 24348+ * 24349+ * http://www.apache.org/licenses/LICENSE-2.0 24350+ * 24351+ * Unless required by applicable law or agreed to in writing, software 24352+ * distributed under the License is distributed on an "AS IS" BASIS, 24353+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24354+ * See the License for the specific language governing permissions and 24355+ * limitations under the License. 24356+ */ 24357+ 24358+/* 24359+#sourcefile vpmotion/vp_motionmodel.c 24360+#category motion-model 24361+* 24362+* Copyright 1998 Sarnoff Corporation 24363+* All Rights Reserved 24364+* 24365+* Modification History 24366+* Date: 02/14/98 24367+* Author: supuns 24368+* Shop Order: 17xxx 24369+* @(#) $Id: vp_motionmodel.c,v 1.4 2011/06/17 14:04:33 mbansal Exp $ 24370+*/ 24371+ 24372+/* 24373+* =================================================================== 24374+* Include Files 24375+*/ 24376+ 24377+#include <string.h> /* memmove */ 24378+#include <math.h> 24379+#include "vp_motionmodel.h" 24380+ 24381+/* Static Functions */ 24382+static 24383+double Det3(double m[3][3]) 24384+{ 24385+ double result; 24386+ 24387+ result = 24388+ m[0][0]*m[1][1]*m[2][2] + m[0][1]*m[1][2]*m[2][0] + 24389+ m[0][2]*m[1][0]*m[2][1] - m[0][2]*m[1][1]*m[2][0] - 24390+ m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2]; 24391+ 24392+ return(result); 24393+} 24394+ 24395+typedef double MATRIX[4][4]; 24396+ 24397+static 24398+double Det4(MATRIX m) 24399+{ 24400+ /* ==> This is a poor implementation of determinant. 24401+ Writing the formula out in closed form is unnecessarily complicated 24402+ and mistakes are easy to make. */ 24403+ double result; 24404+ 24405+ result= 24406+ m[0][3] *m[1][2] *m[2][1] *m[3][0] - m[0][2] *m[1][3] *m[2][1] *m[3][0] - m[0][3] *m[1][1] *m[2][2] *m[3][0] + 24407+ m[0][1] *m[1][3] *m[2][2] *m[3][0] + m[0][2] *m[1][1] *m[2][3] *m[3][0] - m[0][1] *m[1][2] *m[2][3] *m[3][0] - m[0][3] *m[1][2] *m[2][0] *m[3][1] + 24408+ m[0][2] *m[1][3] *m[2][0] *m[3][1] + m[0][3] *m[1][0] *m[2][2] *m[3][1] - m[0][0] *m[1][3] *m[2][2] *m[3][1] - m[0][2] *m[1][0] *m[2][3] *m[3][1] + 24409+ m[0][0] *m[1][2] *m[2][3] *m[3][1] + m[0][3] *m[1][1] *m[2][0] *m[3][2] - m[0][1] *m[1][3] *m[2][0] *m[3][2] - m[0][3] *m[1][0] *m[2][1] *m[3][2] + 24410+ m[0][0] *m[1][3] *m[2][1] *m[3][2] + m[0][1] *m[1][0] *m[2][3] *m[3][2] - m[0][0] *m[1][1] *m[2][3] *m[3][2] - m[0][2] *m[1][1] *m[2][0] *m[3][3] + 24411+ m[0][1] *m[1][2] *m[2][0] *m[3][3] + m[0][2] *m[1][0] *m[2][1] *m[3][3] - m[0][0] *m[1][2] *m[2][1] *m[3][3] - m[0][1] *m[1][0] *m[2][2] *m[3][3] + 24412+ m[0][0] *m[1][1] *m[2][2] *m[3][3]; 24413+ /* 24414+ m[0][0]*m[1][1]*m[2][2]*m[3][3]-m[0][1]*m[1][0]*m[2][2]*m[3][3]+ 24415+ m[0][1]*m[1][2]*m[2][0]*m[3][3]-m[0][2]*m[1][1]*m[2][0]*m[3][3]+ 24416+ m[0][2]*m[1][0]*m[2][1]*m[3][3]-m[0][0]*m[1][2]*m[2][1]*m[3][3]+ 24417+ m[0][0]*m[1][2]*m[2][3]*m[3][1]-m[0][2]*m[1][0]*m[2][3]*m[3][1]+ 24418+ m[0][2]*m[1][3]*m[2][0]*m[3][1]-m[0][3]*m[1][2]*m[2][0]*m[3][1]+ 24419+ m[0][3]*m[1][0]*m[2][2]*m[3][1]-m[0][0]*m[1][3]*m[2][2]*m[3][1]+ 24420+ m[0][0]*m[1][3]*m[2][1]*m[3][2]-m[0][3]*m[1][0]*m[2][3]*m[3][2]+ 24421+ m[0][1]*m[1][0]*m[2][3]*m[3][2]-m[0][0]*m[1][1]*m[2][0]*m[3][2]+ 24422+ m[0][3]*m[1][1]*m[2][0]*m[3][2]-m[0][1]*m[1][3]*m[2][1]*m[3][2]+ 24423+ m[0][1]*m[1][3]*m[2][2]*m[3][0]-m[0][3]*m[1][1]*m[2][2]*m[3][0]+ 24424+ m[0][2]*m[1][1]*m[2][3]*m[3][0]-m[0][1]*m[1][2]*m[2][3]*m[3][0]+ 24425+ m[0][3]*m[1][2]*m[2][1]*m[3][0]-m[0][2]*m[1][3]*m[2][1]*m[3][0]; 24426+ */ 24427+ return(result); 24428+} 24429+ 24430+static 24431+int inv4Mat(const VP_MOTION* in, VP_MOTION* out) 24432+{ 24433+ /* ==> This is a poor implementation of inversion. The determinant 24434+ method is O(N^4), i.e. unnecessarily slow, and not numerically accurate. 24435+ The real complexity of inversion is O(N^3), and is best done using 24436+ LU decomposition. */ 24437+ 24438+ MATRIX inmat,outmat; 24439+ int i, j, k, l, m, n,ntemp; 24440+ double mat[3][3], indet, temp; 24441+ 24442+ /* check for non-empty structures structure */ 24443+ if (((VP_MOTION *) NULL == in) || ((VP_MOTION *) NULL == out)) { 24444+ return 1; 24445+ } 24446+ 24447+ for(k=0,i=0;i<4;i++) 24448+ for(j=0;j<4;j++,k++) 24449+ inmat[i][j]=(double)in->par[k]; 24450+ 24451+ indet = Det4(inmat); 24452+ if (indet==0) return(-1); 24453+ 24454+ for (i=0;i<4;i++) { 24455+ for (j=0;j<4;j++) { 24456+ m = 0; 24457+ for (k=0;k<4;k++) { 24458+ if (i != k) { 24459+ n = 0; 24460+ for (l=0;l<4;l++) 24461+ if (j != l) { 24462+ mat[m][n] = inmat[k][l]; 24463+ n++; 24464+ } 24465+ m++; 24466+ } 24467+ } 24468+ 24469+ temp = -1.; 24470+ ntemp = (i +j ) %2; 24471+ if( ntemp == 0) temp = 1.; 24472+ 24473+ outmat[j][i] = temp * Det3(mat)/indet; 24474+ } 24475+ } 24476+ 24477+ for(k=0,i=0;i<4;i++) 24478+ for(j=0;j<4;j++,k++) 24479+ out->par[k]=(VP_PAR)outmat[i][j]; /*lint !e771*/ 24480+ 24481+ return(0); 24482+} 24483+ 24484+/* 24485+* =================================================================== 24486+* Public Functions 24487+#htmlstart 24488+*/ 24489+ 24490+/* 24491+ * =================================================================== 24492+#fn vp_invert_motion 24493+#ft invert a motion 24494+#fd DEFINITION 24495+ Bool 24496+ vp_invert_motion(const VP_MOTION* in,VP_MOTION* out) 24497+#fd PURPOSE 24498+ This inverts the motion given in 'in'. 24499+ All motion models upto VP_MOTION_SEMI_PROJ_3D are supported. 24500+ It is assumed that the all 16 parameters are properly 24501+ initialized although you may not be using them. You could 24502+ use the VP_KEEP_ macro's defined in vp_motionmodel.h to set 24503+ the un-initialized parameters. This uses a 4x4 matrix invertion 24504+ function internally. 24505+ It is SAFE to pass the same pointer as both the 'in' and 'out' 24506+ parameters. 24507+#fd INPUTS 24508+ in - input motion 24509+#fd OUTPUTS 24510+ out - output inverted motion. If singular matrix uninitialized. 24511+ if MWW(in) is non-zero it is also normalized. 24512+#fd RETURNS 24513+ FALSE - matrix is singular or motion model not supported 24514+ TRUE - otherwise 24515+#fd SIDE EFFECTS 24516+ None 24517+#endfn 24518+*/ 24519+ 24520+int vp_invert_motion(const VP_MOTION* in,VP_MOTION* out) 24521+{ 24522+ int refid; 24523+ 24524+ /* check for non-empty structures structure */ 24525+ if (((VP_MOTION *) NULL == in) || ((VP_MOTION *) NULL == out)) { 24526+ return FALSE; 24527+ } 24528+ 24529+ if (in->type>VP_MOTION_SEMI_PROJ_3D) { 24530+ return FALSE; 24531+ } 24532+ 24533+ if (inv4Mat(in,out)<0) 24534+ return FALSE; 24535+ 24536+ /*VP_NORMALIZE(*out);*/ 24537+ out->type = in->type; 24538+ refid=in->refid; 24539+ out->refid=in->insid; 24540+ out->insid=refid; 24541+ return TRUE; 24542+} 24543+ 24544+/* 24545+* =================================================================== 24546+#fn vp_cascade_motion 24547+#ft Cascade two motion transforms 24548+#fd DEFINITION 24549+ Bool 24550+ vp_cascade_motion(const VP_MOTION* InAB,const VP_MOTION* InBC,VP_MOTION* OutAC) 24551+#fd PURPOSE 24552+ Given Motion Transforms A->B and B->C, this function will 24553+ generate a New Motion that describes the transformation 24554+ from A->C. 24555+ More specifically, OutAC = InBC * InAC. 24556+ This function works ok if InAB,InBC and OutAC are the same pointer. 24557+#fd INPUTS 24558+ InAB - First Motion Transform 24559+ InBC - Second Motion Tranform 24560+#fd OUTPUTS 24561+ OutAC - Cascaded Motion 24562+#fd RETURNS 24563+ FALSE - motion model not supported 24564+ TRUE - otherwise 24565+#fd SIDE EFFECTS 24566+ None 24567+#endfn 24568+*/ 24569+ 24570+int vp_cascade_motion(const VP_MOTION* InA, const VP_MOTION* InB,VP_MOTION* Out) 24571+{ 24572+ /* ==> This is a poor implementation of matrix multiplication. 24573+ Writing the formula out in closed form is unnecessarily complicated 24574+ and mistakes are easy to make. */ 24575+ VP_PAR mxx,mxy,mxz,mxw; 24576+ VP_PAR myx,myy,myz,myw; 24577+ VP_PAR mzx,mzy,mzz,mzw; 24578+ VP_PAR mwx,mwy,mwz,mww; 24579+ 24580+ /* check for non-empty structures structure */ 24581+ if (((VP_MOTION *) NULL == InA) || ((VP_MOTION *) NULL == InB) || 24582+ ((VP_MOTION *) NULL == Out)) { 24583+ return FALSE; 24584+ } 24585+ 24586+ if (InA->type>VP_MOTION_PROJ_3D) { 24587+ return FALSE; 24588+ } 24589+ 24590+ if (InB->type>VP_MOTION_PROJ_3D) { 24591+ return FALSE; 24592+ } 24593+ 24594+ mxx = MXX(*InB)*MXX(*InA)+MXY(*InB)*MYX(*InA)+MXZ(*InB)*MZX(*InA)+MXW(*InB)*MWX(*InA); 24595+ mxy = MXX(*InB)*MXY(*InA)+MXY(*InB)*MYY(*InA)+MXZ(*InB)*MZY(*InA)+MXW(*InB)*MWY(*InA); 24596+ mxz = MXX(*InB)*MXZ(*InA)+MXY(*InB)*MYZ(*InA)+MXZ(*InB)*MZZ(*InA)+MXW(*InB)*MWZ(*InA); 24597+ mxw = MXX(*InB)*MXW(*InA)+MXY(*InB)*MYW(*InA)+MXZ(*InB)*MZW(*InA)+MXW(*InB)*MWW(*InA); 24598+ myx = MYX(*InB)*MXX(*InA)+MYY(*InB)*MYX(*InA)+MYZ(*InB)*MZX(*InA)+MYW(*InB)*MWX(*InA); 24599+ myy = MYX(*InB)*MXY(*InA)+MYY(*InB)*MYY(*InA)+MYZ(*InB)*MZY(*InA)+MYW(*InB)*MWY(*InA); 24600+ myz = MYX(*InB)*MXZ(*InA)+MYY(*InB)*MYZ(*InA)+MYZ(*InB)*MZZ(*InA)+MYW(*InB)*MWZ(*InA); 24601+ myw = MYX(*InB)*MXW(*InA)+MYY(*InB)*MYW(*InA)+MYZ(*InB)*MZW(*InA)+MYW(*InB)*MWW(*InA); 24602+ mzx = MZX(*InB)*MXX(*InA)+MZY(*InB)*MYX(*InA)+MZZ(*InB)*MZX(*InA)+MZW(*InB)*MWX(*InA); 24603+ mzy = MZX(*InB)*MXY(*InA)+MZY(*InB)*MYY(*InA)+MZZ(*InB)*MZY(*InA)+MZW(*InB)*MWY(*InA); 24604+ mzz = MZX(*InB)*MXZ(*InA)+MZY(*InB)*MYZ(*InA)+MZZ(*InB)*MZZ(*InA)+MZW(*InB)*MWZ(*InA); 24605+ mzw = MZX(*InB)*MXW(*InA)+MZY(*InB)*MYW(*InA)+MZZ(*InB)*MZW(*InA)+MZW(*InB)*MWW(*InA); 24606+ mwx = MWX(*InB)*MXX(*InA)+MWY(*InB)*MYX(*InA)+MWZ(*InB)*MZX(*InA)+MWW(*InB)*MWX(*InA); 24607+ mwy = MWX(*InB)*MXY(*InA)+MWY(*InB)*MYY(*InA)+MWZ(*InB)*MZY(*InA)+MWW(*InB)*MWY(*InA); 24608+ mwz = MWX(*InB)*MXZ(*InA)+MWY(*InB)*MYZ(*InA)+MWZ(*InB)*MZZ(*InA)+MWW(*InB)*MWZ(*InA); 24609+ mww = MWX(*InB)*MXW(*InA)+MWY(*InB)*MYW(*InA)+MWZ(*InB)*MZW(*InA)+MWW(*InB)*MWW(*InA); 24610+ 24611+ MXX(*Out)=mxx; MXY(*Out)=mxy; MXZ(*Out)=mxz; MXW(*Out)=mxw; 24612+ MYX(*Out)=myx; MYY(*Out)=myy; MYZ(*Out)=myz; MYW(*Out)=myw; 24613+ MZX(*Out)=mzx; MZY(*Out)=mzy; MZZ(*Out)=mzz; MZW(*Out)=mzw; 24614+ MWX(*Out)=mwx; MWY(*Out)=mwy; MWZ(*Out)=mwz; MWW(*Out)=mww; 24615+ /* VP_NORMALIZE(*Out); */ 24616+ Out->type= (InA->type > InB->type) ? InA->type : InB->type; 24617+ Out->refid=InA->refid; 24618+ Out->insid=InB->insid; 24619+ 24620+ return TRUE; 24621+} 24622+ 24623+/* 24624+* =================================================================== 24625+#fn vp_copy_motion 24626+#ft Copies the source motion to the destination motion. 24627+#fd DEFINITION 24628+ void 24629+ vp_copy_motion (const VP_MOTION *src, VP_MOTION *dst) 24630+#fd PURPOSE 24631+ Copies the source motion to the destination motion. 24632+ It is OK if src == dst. 24633+ NOTE THAT THE SOURCE IS THE FIRST ARGUMENT. 24634+ This is different from some of the other VP 24635+ copy functions. 24636+#fd INPUTS 24637+ src is the source motion 24638+ dst is the destination motion 24639+#fd RETURNS 24640+ void 24641+#endfn 24642+*/ 24643+void vp_copy_motion (const VP_MOTION *src, VP_MOTION *dst) 24644+{ 24645+ /* Use memmove rather than memcpy because it handles overlapping memory 24646+ OK. */ 24647+ memmove(dst, src, sizeof(VP_MOTION)); 24648+ return; 24649+} /* vp_copy_motion() */ 24650+ 24651+#define VP_SQR(x) ( (x)*(x) ) 24652+double vp_motion_cornerdiff(const VP_MOTION *mot_a, const VP_MOTION *mot_b, 24653+ int xo, int yo, int w, int h) 24654+{ 24655+ double ax1, ay1, ax2, ay2, ax3, ay3, ax4, ay4; 24656+ double bx1, by1, bx2, by2, bx3, by3, bx4, by4; 24657+ double err; 24658+ 24659+ /*lint -e639 -e632 -e633 */ 24660+ VP_WARP_POINT_2D(xo, yo, *mot_a, ax1, ay1); 24661+ VP_WARP_POINT_2D(xo+w-1, yo, *mot_a, ax2, ay2); 24662+ VP_WARP_POINT_2D(xo+w-1, yo+h-1, *mot_a, ax3, ay3); 24663+ VP_WARP_POINT_2D(xo, yo+h-1, *mot_a, ax4, ay4); 24664+ VP_WARP_POINT_2D(xo, yo, *mot_b, bx1, by1); 24665+ VP_WARP_POINT_2D(xo+w-1, yo, *mot_b, bx2, by2); 24666+ VP_WARP_POINT_2D(xo+w-1, yo+h-1, *mot_b, bx3, by3); 24667+ VP_WARP_POINT_2D(xo, yo+h-1, *mot_b, bx4, by4); 24668+ /*lint +e639 +e632 +e633 */ 24669+ 24670+ err = 0; 24671+ err += (VP_SQR(ax1 - bx1) + VP_SQR(ay1 - by1)); 24672+ err += (VP_SQR(ax2 - bx2) + VP_SQR(ay2 - by2)); 24673+ err += (VP_SQR(ax3 - bx3) + VP_SQR(ay3 - by3)); 24674+ err += (VP_SQR(ax4 - bx4) + VP_SQR(ay4 - by4)); 24675+ 24676+ return(sqrt(err)); 24677+} 24678+ 24679+int vp_zoom_motion2d(VP_MOTION* in, VP_MOTION* out, 24680+ int n, int w, int h, double zoom) 24681+{ 24682+ int ii; 24683+ VP_PAR inv_zoom; 24684+ VP_PAR cx, cy; 24685+ VP_MOTION R2r,R2f; 24686+ VP_MOTION *res; 24687+ 24688+ /* check for non-empty structures structure */ 24689+ if (((VP_MOTION *) NULL == in)||(zoom <= 0.0)||(w <= 0)||(h <= 0)) { 24690+ return FALSE; 24691+ } 24692+ 24693+ /* ==> Not sure why the special case of out=NULL is necessary. Why couldn't 24694+ the caller just pass the same pointer for both in and out? */ 24695+ res = ((VP_MOTION *) NULL == out)?in:out; 24696+ 24697+ cx = (VP_PAR) (w/2.0); 24698+ cy = (VP_PAR) (h/2.0); 24699+ 24700+ VP_MOTION_ID(R2r); 24701+ inv_zoom = (VP_PAR)(1.0/zoom); 24702+ MXX(R2r) = inv_zoom; 24703+ MYY(R2r) = inv_zoom; 24704+ MXW(R2r)=cx*(((VP_PAR)1.0) - inv_zoom); 24705+ MYW(R2r)=cy*(((VP_PAR)1.0) - inv_zoom); 24706+ 24707+ VP_KEEP_AFFINE_2D(R2r); 24708+ 24709+ for(ii=0;ii<n;ii++) { 24710+ (void) vp_cascade_motion(&R2r,in+ii,&R2f); 24711+ res[ii]=R2f; 24712+ } 24713+ 24714+ return TRUE; 24715+} /* vp_zoom_motion2d() */ 24716+ 24717+/* =================================================================== */ 24718+/* end vp_motionmodel.c */ 24719diff --git a/benchmark/feature_stab/src/dbreg/vp_motionmodel.h b/benchmark/feature_stab/src/dbreg/vp_motionmodel.h 24720new file mode 100644 24721index 00000000..a63ac001 24722--- /dev/null 24723+++ b/benchmark/feature_stab/src/dbreg/vp_motionmodel.h 24724@@ -0,0 +1,282 @@ 24725+/* 24726+ * Copyright (C) 2011 The Android Open Source Project 24727+ * 24728+ * Licensed under the Apache License, Version 2.0 (the "License"); 24729+ * you may not use this file except in compliance with the License. 24730+ * You may obtain a copy of the License at 24731+ * 24732+ * http://www.apache.org/licenses/LICENSE-2.0 24733+ * 24734+ * Unless required by applicable law or agreed to in writing, software 24735+ * distributed under the License is distributed on an "AS IS" BASIS, 24736+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24737+ * See the License for the specific language governing permissions and 24738+ * limitations under the License. 24739+ */ 24740+ 24741+/* 24742+#sourcefile vp_motionmodel.h 24743+#category warp 24744+#description general motion model for tranlation/affine/projective 24745+#title motion-model 24746+#parentlink hindex.html 24747+* 24748+* Copyright 1998 Sarnoff Corporation 24749+* All Rights Reserved 24750+* 24751+* Modification History 24752+* Date: 02/13/98 24753+* Author: supuns 24754+* Shop Order: 15491 001 24755+* @(#) $Id: vp_motionmodel.h,v 1.4 2011/06/17 14:04:33 mbansal Exp $ 24756+*/ 24757+ 24758+#ifndef VP_MOTIONMODEL_H 24759+#define VP_MOTIONMODEL_H 24760+#include <stdio.h> 24761+ 24762+#define FALSE 0 24763+#define TRUE 1 24764+ 24765+#if 0 /* Moved mottomat.c and mattomot_d.c from vpmotion.h to vpcompat.h 24766+ in order to remove otherwise unnecessary dependency of vpmotion, 24767+ vpwarp, and newvpio on vpmath */ 24768+#ifndef VPMATH_H 24769+#include "vpmath.h" 24770+#endif 24771+#endif 24772+ 24773+#if 0 24774+#ifndef VP_WARP_H 24775+#include "vp_warp.h" 24776+#endif 24777+#endif 24778+/* 24779+ 24780+#htmlstart 24781+# =================================================================== 24782+#h 1 Introduction 24783+ 24784+ This defines a motion model that can describe translation, 24785+ affine, and projective projective 3d and 3d view transforms. 24786+ 24787+ The main structure VP_MOTION contains a 16 parameter array (That 24788+ can be considered as elements of a 4x4 matrix) and a type field 24789+ which can be one of VP_MOTION_NONE,VP_MOTION_TRANSLATION, 24790+ VP_MOTION_AFFINE, VP_MOTION_PROJECTIVE,VP_MOTION_PROJ_3D or 24791+ VP_MOTION_VIEW_3D. (These are defined using enums with gaps of 10 24792+ so that subsets of these motions that are still consistant can be 24793+ added in between. Motion models that are inconsistant with this set 24794+ should be added at the end so the routines can hadle them 24795+ independently. 24796+ 24797+ The transformation VP_MOTION_NONE,VP_MOTION_TRANSLATION, 24798+ VP_MOTION_AFFINE, VP_MOTION_PROJECTIVE, VP_MOTION_PROJ_3D and 24799+ VP_MOTION_SEMI_PROJ_3D would map a point P={x,y,z,w} to a new point 24800+ P'={x',y',z',w'} using a motion model M such that P'= M.par * P. 24801+ Where M.par is thought of as elements of a 4x4 matrix ordered row 24802+ by row. The interpretation of all models except VP_MOTION_SEMI_PROJ_3D 24803+ is taken to be mapping of a 3d point P"={x",y",z"} which is obtained 24804+ from the normalization {x'/w',y'/w',z'/w'}. In the VP_MOTION_SEMI_PROJ_3D 24805+ the mapping to a point P"={x",y",z"} is obtained from the normalization 24806+ {x'/w',y'/w',z'}. All these motion models have the property that they 24807+ can be inverted using 4x4 matrices. Except for the VP_MOTION_SEMI_PROJ_3D all 24808+ other types can also be cascaded using 4x4 matrices. 24809+ 24810+ Specific macros and functions have been provided to handle 2d instances 24811+ of these functions. As the parameter interpretations can change when adding 24812+ new motion models it is HIGHLY RECOMMENDED that you use the macros MXX,MXY.. 24813+ ect. to interpret each motion component. 24814+#pre 24815+*/ 24816+ 24817+/* 24818+#endpre 24819+# =================================================================== 24820+#h 1 Typedef and Struct Declarations 24821+#pre 24822+*/ 24823+ 24824+#define VP_MAX_MOTION_PAR 16 24825+ 24826+typedef double VP_PAR; 24827+typedef VP_PAR VP_TRS[VP_MAX_MOTION_PAR]; 24828+ 24829+/* Do not add any motion models before VP_MOTION_PROJECTIVE */ 24830+/* The order is assumed in vp functions */ 24831+enum VP_MOTION_MODEL { 24832+ VP_MOTION_NONE=0, 24833+ VP_MOTION_TRANSLATION=10, 24834+ VP_MOTION_SCALE=11, 24835+ VP_MOTION_ROTATE=12, 24836+ VP_MOTION_X_SHEAR=13, 24837+ VP_MOTION_Y_SHEAR=14, 24838+ VP_MOTION_SIMILARITY=15, 24839+ VP_MOTION_AFFINE=20, 24840+ VP_MOTION_PROJECTIVE=30, 24841+ VP_MOTION_PROJ_3D=40, 24842+ VP_MOTION_SEMI_PROJ_3D=80, 24843+ VP_SIMILARITY=100, 24844+ VP_VFE_AFFINE=120 24845+}; 24846+ 24847+#define VP_REFID -1 /* Default ID used for reference frame */ 24848+ 24849+typedef struct { 24850+ VP_TRS par; /* Contains the motion paramerers. 24851+ For the standard motion types this is 24852+ represented as 16 number that refer 24853+ to a 4x4 matrix */ 24854+ enum VP_MOTION_MODEL type; 24855+ int refid; /* Reference frame ( takes a point in refid frame 24856+ and moves it by the par to get a point in insid 24857+ frame ) */ 24858+ int insid; /* Inspection frame */ 24859+} VP_MOTION; 24860+ 24861+//typedef VP_LIST VP_MOTION_LIST; 24862+/* 24863+#endpre 24864+# =================================================================== 24865+#h 1 Constant Declarations 24866+*/ 24867+ 24868+/* Macros related to the 4x4 matrix parameters */ 24869+#define MXX(m) (m).par[0] 24870+#define MXY(m) (m).par[1] 24871+#define MXZ(m) (m).par[2] 24872+#define MXW(m) (m).par[3] 24873+#define MYX(m) (m).par[4] 24874+#define MYY(m) (m).par[5] 24875+#define MYZ(m) (m).par[6] 24876+#define MYW(m) (m).par[7] 24877+#define MZX(m) (m).par[8] 24878+#define MZY(m) (m).par[9] 24879+#define MZZ(m) (m).par[10] 24880+#define MZW(m) (m).par[11] 24881+#define MWX(m) (m).par[12] 24882+#define MWY(m) (m).par[13] 24883+#define MWZ(m) (m).par[14] 24884+#define MWW(m) (m).par[15] 24885+ 24886+/* The do {...} while (0) technique creates a statement that can be used legally 24887+ in an if-else statement. See "Swallowing the semicolon", 24888+ http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC23 */ 24889+/* Initialize the Motion to be Identity */ 24890+#define VP_MOTION_ID(m) do {\ 24891+ MXX(m)=MYY(m)=MZZ(m)=MWW(m)=(VP_PAR)1.0; \ 24892+ MXY(m)=MXZ(m)=MXW(m)=(VP_PAR)0.0; \ 24893+ MYX(m)=MYZ(m)=MYW(m)=(VP_PAR)0.0; \ 24894+ MZX(m)=MZY(m)=MZW(m)=(VP_PAR)0.0; \ 24895+ MWX(m)=MWY(m)=MWZ(m)=(VP_PAR)0.0; \ 24896+(m).type = VP_MOTION_TRANSLATION; } while (0) 24897+ 24898+/* Initialize without altering the translation components */ 24899+#define VP_KEEP_TRANSLATION_3D(m) do {\ 24900+ MXX(m)=MYY(m)=MZZ(m)=MWW(m)=(VP_PAR)1.0; \ 24901+ MXY(m)=MXZ(m)=(VP_PAR)0.0; \ 24902+ MYX(m)=MYZ(m)=(VP_PAR)0.0; \ 24903+ MZX(m)=MZY(m)=(VP_PAR)0.0; \ 24904+ MWX(m)=MWY(m)=MWZ(m)=(VP_PAR)0.0; \ 24905+ (m).type = VP_MOTION_PROJ_3D; } while (0) 24906+ 24907+/* Initialize without altering the 2d translation components */ 24908+#define VP_KEEP_TRANSLATION_2D(m) do {\ 24909+ VP_KEEP_TRANSLATION_3D(m); MZW(m)=(VP_PAR)0.0; (m).type= VP_MOTION_TRANSLATION;} while (0) 24910+ 24911+/* Initialize without altering the affine & translation components */ 24912+#define VP_KEEP_AFFINE_3D(m) do {\ 24913+ MWX(m)=MWY(m)=MWZ(m)=(VP_PAR)0.0; MWW(m)=(VP_PAR)1.0; \ 24914+ (m).type = VP_MOTION_PROJ_3D; } while (0) 24915+ 24916+/* Initialize without altering the 2d affine & translation components */ 24917+#define VP_KEEP_AFFINE_2D(m) do {\ 24918+ VP_KEEP_AFFINE_3D(m); \ 24919+ MXZ(m)=MYZ(m)=(VP_PAR)0.0; MZZ(m)=(VP_PAR)1.0; \ 24920+ MZX(m)=MZY(m)=MZW(m)=(VP_PAR)0.0; \ 24921+ (m).type = VP_MOTION_AFFINE; } while (0) 24922+ 24923+/* Initialize without altering the 2d projective parameters */ 24924+#define VP_KEEP_PROJECTIVE_2D(m) do {\ 24925+ MXZ(m)=MYZ(m)=(VP_PAR)0.0; MZZ(m)=(VP_PAR)1.0; \ 24926+ MZX(m)=MZY(m)=MZW(m)=MWZ(m)=(VP_PAR)0.0; \ 24927+ (m).type = VP_MOTION_PROJECTIVE; } while (0) 24928+ 24929+/* Warp a 2d point (assuming the z component is zero) */ 24930+#define VP_WARP_POINT_2D(inx,iny,m,outx,outy) do {\ 24931+ VP_PAR vpTmpWarpPnt___= MWX(m)*(inx)+MWY(m)*(iny)+MWW(m); \ 24932+ outx = (MXX(m)*((VP_PAR)inx)+MXY(m)*((VP_PAR)iny)+MXW(m))/vpTmpWarpPnt___; \ 24933+ outy = (MYX(m)*((VP_PAR)inx)+MYY(m)*((VP_PAR)iny)+MYW(m))/vpTmpWarpPnt___; } while (0) 24934+ 24935+/* Warp a 3d point */ 24936+#define VP_WARP_POINT_3D(inx,iny,inz,m,outx,outy,outz) do {\ 24937+ VP_PAR vpTmpWarpPnt___= MWX(m)*(inx)+MWY(m)*(iny)+MWZ(m)*((VP_PAR)inz)+MWW(m); \ 24938+ outx = (MXX(m)*((VP_PAR)inx)+MXY(m)*((VP_PAR)iny)+MXZ(m)*((VP_PAR)inz)+MXW(m))/vpTmpWarpPnt___; \ 24939+ outy = (MYX(m)*((VP_PAR)inx)+MYY(m)*((VP_PAR)iny)+MYZ(m)*((VP_PAR)inz)+MYW(m))/vpTmpWarpPnt___; \ 24940+ outz = MZX(m)*((VP_PAR)inx)+MZY(m)*((VP_PAR)iny)+MZZ(m)*((VP_PAR)inz)+MZW(m); \ 24941+ if ((m).type==VP_MOTION_PROJ_3D) outz/=vpTmpWarpPnt___; } while (0) 24942+ 24943+/* Projections of each component */ 24944+#define VP_PROJW_3D(m,x,y,z,f) ( MWX(m)*(x)+MWY(m)*(y)+MWZ(m)*(z)+MWW(m) ) 24945+#define VP_PROJX_3D(m,x,y,z,f,w) ((MXX(m)*(x)+MXY(m)*(y)+MXZ(m)*(z)+MXW(m))/(w)) 24946+#define VP_PROJY_3D(m,x,y,z,f,w) ((MYX(m)*(x)+MYY(m)*(y)+MYZ(m)*(z)+MYW(m))/(w)) 24947+#define VP_PROJZ_3D(m,x,y,z,f,w) ((MZX(m)*(x)+MZY(m)*(y)+MZZ(m)*(z)+MZW(m))/(w)) 24948+ 24949+/* Scale Down a matrix by Sfactor */ 24950+#define VP_SCALEDOWN(m,Sfactor) do { \ 24951+ MXW(m) /= (VP_PAR)Sfactor; MWX(m) *= (VP_PAR)Sfactor; \ 24952+ MYW(m) /= (VP_PAR)Sfactor; MWY(m) *= (VP_PAR)Sfactor; \ 24953+ MZW(m) /= (VP_PAR)Sfactor; MWZ(m) *= (VP_PAR)Sfactor; } while (0) 24954+ 24955+/* Scale Up a matrix by Sfactor */ 24956+#define VP_SCALEUP(m,Sfactor) do { \ 24957+ MXW(m) *= (VP_PAR)Sfactor; MWX(m) /= (VP_PAR)Sfactor; \ 24958+ MYW(m) *= (VP_PAR)Sfactor; MWY(m) /= (VP_PAR)Sfactor; \ 24959+ MZW(m) *= (VP_PAR)Sfactor; MWZ(m) /= (VP_PAR)Sfactor; } while (0) 24960+ 24961+/* Normalize the transformation matrix so that MWW is 1 */ 24962+#define VP_NORMALIZE(m) if (MWW(m)!=(VP_PAR)0.0) do { \ 24963+ MXX(m)/=MWW(m); MXY(m)/=MWW(m); MXZ(m)/=MWW(m); MXW(m)/= MWW(m); \ 24964+ MYX(m)/=MWW(m); MYY(m)/=MWW(m); MYZ(m)/=MWW(m); MYW(m)/= MWW(m); \ 24965+ MZX(m)/=MWW(m); MZY(m)/=MWW(m); MZZ(m)/=MWW(m); MZW(m)/= MWW(m); \ 24966+ MWX(m)/=MWW(m); MWY(m)/=MWW(m); MWZ(m)/=MWW(m); MWW(m) = (VP_PAR)1.0; } while (0) 24967+ 24968+#define VP_PRINT_TRANS(msg,b) do { \ 24969+ fprintf(stderr, \ 24970+ "%s\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", \ 24971+ msg, \ 24972+ MXX(b),MXY(b),MXZ(b),MXW(b), \ 24973+ MYX(b),MYY(b),MYZ(b),MYW(b), \ 24974+ MZX(b),MZY(b),MZZ(b),MZW(b), \ 24975+ MWX(b),MWY(b),MWZ(b),MWW(b)); \ 24976+} while (0) 24977+ 24978+/* w' projection given a point x,y,0,f */ 24979+#define VP_PROJZ(m,x,y,f) ( \ 24980+ MWX(m)*((VP_PAR)x)+MWY(m)*((VP_PAR)y)+MWW(m)*((VP_PAR)f)) 24981+ 24982+/* X Projection given a point x,y,0,f and w' */ 24983+#define VP_PROJX(m,x,y,w,f) (\ 24984+ (MXX(m)*((VP_PAR)x)+MXY(m)*((VP_PAR)y)+MXW(m)*((VP_PAR)f))/((VP_PAR)w)) 24985+ 24986+/* Y Projection given a point x,y,0,f and the w' */ 24987+#define VP_PROJY(m,x,y,w,f) (\ 24988+ (MYX(m)*((VP_PAR)x)+MYY(m)*((VP_PAR)y)+MYW(m)*((VP_PAR)f))/((VP_PAR)w)) 24989+ 24990+/* Set the reference id for a motion */ 24991+#define VP_SET_REFID(m,id) do { (m).refid=id; } while (0) 24992+ 24993+/* Set the inspection id for a motion */ 24994+#define VP_SET_INSID(m,id) do { (m).insid=id; } while (0) 24995+ 24996+void vp_copy_motion (const VP_MOTION *src, VP_MOTION *dst); 24997+int vp_invert_motion(const VP_MOTION* in,VP_MOTION* out); 24998+int vp_cascade_motion(const VP_MOTION* InAB, const VP_MOTION* InBC,VP_MOTION* OutAC); 24999+int vp_zoom_motion2d(VP_MOTION* in, VP_MOTION* out, 25000+ int n, int w, int h, double zoom); 25001+double vp_motion_cornerdiff(const VP_MOTION *mot_a, const VP_MOTION *mot_b, 25002+ int xo, int yo, int w, int h); 25003+ 25004+#endif /* VP_MOTIONMODEL_H */ 25005+/* =================================================================== */ 25006+/* end vp_motionmodel.h */ 25007diff --git a/benchmark/feature_stab/src/dbregtest/PgmImage.cpp b/benchmark/feature_stab/src/dbregtest/PgmImage.cpp 25008new file mode 100644 25009index 00000000..0891cfda 25010--- /dev/null 25011+++ b/benchmark/feature_stab/src/dbregtest/PgmImage.cpp 25012@@ -0,0 +1,260 @@ 25013+/* 25014+ * Copyright (C) 2011 The Android Open Source Project 25015+ * 25016+ * Licensed under the Apache License, Version 2.0 (the "License"); 25017+ * you may not use this file except in compliance with the License. 25018+ * You may obtain a copy of the License at 25019+ * 25020+ * http://www.apache.org/licenses/LICENSE-2.0 25021+ * 25022+ * Unless required by applicable law or agreed to in writing, software 25023+ * distributed under the License is distributed on an "AS IS" BASIS, 25024+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25025+ * See the License for the specific language governing permissions and 25026+ * limitations under the License. 25027+ */ 25028+ 25029+#include "PgmImage.h" 25030+#include <cassert> 25031+ 25032+using namespace std; 25033+ 25034+PgmImage::PgmImage(std::string filename) : 25035+m_w(0),m_h(0),m_colors(255),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256) 25036+{ 25037+ if ( !ReadPGM(filename) ) 25038+ return; 25039+} 25040+ 25041+PgmImage::PgmImage(int w, int h, int format) : 25042+m_colors(255),m_w(w),m_h(h),m_format(format),m_over_allocation(256) 25043+{ 25044+ SetFormat(format); 25045+} 25046+ 25047+PgmImage::PgmImage(unsigned char *data, int w, int h) : 25048+m_colors(255),m_w(w),m_h(h),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256) 25049+{ 25050+ SetData(data); 25051+} 25052+ 25053+PgmImage::PgmImage(std::vector<unsigned char> &data, int w, int h) : 25054+m_colors(255),m_w(w),m_h(h),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256) 25055+{ 25056+ if ( data.size() == w*h ) 25057+ SetData(&data[0]); 25058+ else 25059+ //throw (std::exception("Size of data is not w*h.")); 25060+ throw (std::exception()); 25061+} 25062+ 25063+PgmImage::PgmImage(const PgmImage &im) : 25064+m_colors(255),m_w(0),m_h(0),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256) 25065+{ 25066+ DeepCopy(im, *this); 25067+} 25068+ 25069+PgmImage& PgmImage::operator= (const PgmImage &im) 25070+{ 25071+ if (this == &im) return *this; 25072+ DeepCopy(im, *this); 25073+ return *this; 25074+} 25075+ 25076+void PgmImage::DeepCopy(const PgmImage& src, PgmImage& dst) 25077+{ 25078+ dst.m_data = src.m_data; 25079+ 25080+ // PGM data 25081+ dst.m_w = src.m_w; 25082+ dst.m_h = src.m_h; 25083+ dst.m_format = src.m_format; 25084+ dst.m_colors = src.m_colors; 25085+ 25086+ dst.m_comment = src.m_comment; 25087+ SetupRowPointers(); 25088+} 25089+ 25090+PgmImage::~PgmImage() 25091+{ 25092+ 25093+} 25094+ 25095+void PgmImage::SetFormat(int format) 25096+{ 25097+ m_format = format; 25098+ 25099+ switch (format) 25100+ { 25101+ case PGM_BINARY_GRAYMAP: 25102+ m_data.resize(m_w*m_h+m_over_allocation); 25103+ break; 25104+ case PGM_BINARY_PIXMAP: 25105+ m_data.resize(m_w*m_h*3+m_over_allocation); 25106+ break; 25107+ default: 25108+ return; 25109+ break; 25110+ } 25111+ SetupRowPointers(); 25112+} 25113+ 25114+void PgmImage::SetData(const unsigned char * data) 25115+{ 25116+ m_data.resize(m_w*m_h+m_over_allocation); 25117+ memcpy(&m_data[0],data,m_w*m_h); 25118+ SetupRowPointers(); 25119+} 25120+ 25121+bool PgmImage::ReadPGM(const std::string filename) 25122+{ 25123+ ifstream in(filename.c_str(),std::ios::in | std::ios::binary); 25124+ if ( !in.is_open() ) 25125+ return false; 25126+ 25127+ // read the header: 25128+ string format_header,size_header,colors_header; 25129+ 25130+ getline(in,format_header); 25131+ stringstream s; 25132+ s << format_header; 25133+ 25134+ s >> format_header >> m_w >> m_h >> m_colors; 25135+ s.clear(); 25136+ 25137+ if ( m_w == 0 ) 25138+ { 25139+ while ( in.peek() == '#' ) 25140+ getline(in,m_comment); 25141+ 25142+ getline(in,size_header); 25143+ 25144+ while ( in.peek() == '#' ) 25145+ getline(in,m_comment); 25146+ 25147+ m_colors = 0; 25148+ 25149+ // parse header 25150+ s << size_header; 25151+ s >> m_w >> m_h >> m_colors; 25152+ s.clear(); 25153+ 25154+ if ( m_colors == 0 ) 25155+ { 25156+ getline(in,colors_header); 25157+ s << colors_header; 25158+ s >> m_colors; 25159+ } 25160+ } 25161+ 25162+ if ( format_header == "P5" ) 25163+ m_format = PGM_BINARY_GRAYMAP; 25164+ else if (format_header == "P6" ) 25165+ m_format = PGM_BINARY_PIXMAP; 25166+ else 25167+ m_format = PGM_FORMAT_INVALID; 25168+ 25169+ switch(m_format) 25170+ { 25171+ case(PGM_BINARY_GRAYMAP): 25172+ m_data.resize(m_w*m_h+m_over_allocation); 25173+ in.read((char *)(&m_data[0]),m_data.size()); 25174+ break; 25175+ case(PGM_BINARY_PIXMAP): 25176+ m_data.resize(m_w*m_h*3+m_over_allocation); 25177+ in.read((char *)(&m_data[0]),m_data.size()); 25178+ break; 25179+ default: 25180+ return false; 25181+ break; 25182+ } 25183+ in.close(); 25184+ 25185+ SetupRowPointers(); 25186+ 25187+ return true; 25188+} 25189+ 25190+bool PgmImage::WritePGM(const std::string filename, const std::string comment) 25191+{ 25192+ string format_header; 25193+ 25194+ switch(m_format) 25195+ { 25196+ case PGM_BINARY_GRAYMAP: 25197+ format_header = "P5\n"; 25198+ break; 25199+ case PGM_BINARY_PIXMAP: 25200+ format_header = "P6\n"; 25201+ break; 25202+ default: 25203+ return false; 25204+ break; 25205+ } 25206+ 25207+ ofstream out(filename.c_str(),std::ios::out |ios::binary); 25208+ out << format_header << "# " << comment << '\n' << m_w << " " << m_h << '\n' << m_colors << '\n'; 25209+ 25210+ out.write((char *)(&m_data[0]), m_data.size()); 25211+ 25212+ out.close(); 25213+ 25214+ return true; 25215+} 25216+ 25217+void PgmImage::SetupRowPointers() 25218+{ 25219+ int i; 25220+ m_rows.resize(m_h); 25221+ 25222+ switch (m_format) 25223+ { 25224+ case PGM_BINARY_GRAYMAP: 25225+ for(i=0;i<m_h;i++) 25226+ { 25227+ m_rows[i]=&m_data[m_w*i]; 25228+ } 25229+ break; 25230+ case PGM_BINARY_PIXMAP: 25231+ for(i=0;i<m_h;i++) 25232+ { 25233+ m_rows[i]=&m_data[(m_w*3)*i]; 25234+ } 25235+ break; 25236+ } 25237+} 25238+ 25239+void PgmImage::ConvertToGray() 25240+{ 25241+ if ( m_format != PGM_BINARY_PIXMAP ) return; 25242+ 25243+ // Y = 0.3*R + 0.59*G + 0.11*B; 25244+ for ( int i = 0; i < m_w*m_h; ++i ) 25245+ m_data[i] = (unsigned char)(0.3*m_data[3*i]+0.59*m_data[3*i+1]+0.11*m_data[3*i+2]); 25246+ 25247+ m_data.resize(m_w*m_h+m_over_allocation); 25248+ m_format = PGM_BINARY_GRAYMAP; 25249+ 25250+ SetupRowPointers(); 25251+} 25252+ 25253+std::ostream& operator<< (std::ostream& o, const PgmImage& im) 25254+{ 25255+ o << "PGM Image Info:\n"; 25256+ o << "Size: " << im.m_w << " x " << im.m_h << "\n"; 25257+ o << "Comment: " << im.m_comment << "\n"; 25258+ switch (im.m_format) 25259+ { 25260+ case PgmImage::PGM_BINARY_PIXMAP: 25261+ o << "Format: RGB binary pixmap"; 25262+ break; 25263+ case PgmImage::PGM_BINARY_GRAYMAP: 25264+ o << "Format: PPM binary graymap"; 25265+ break; 25266+ default: 25267+ o << "Format: Invalid"; 25268+ break; 25269+ } 25270+ o << endl; 25271+ return o; 25272+} 25273diff --git a/benchmark/feature_stab/src/dbregtest/PgmImage.h b/benchmark/feature_stab/src/dbregtest/PgmImage.h 25274new file mode 100644 25275index 00000000..d4d1eebe 25276--- /dev/null 25277+++ b/benchmark/feature_stab/src/dbregtest/PgmImage.h 25278@@ -0,0 +1,95 @@ 25279+/* 25280+ * Copyright (C) 2011 The Android Open Source Project 25281+ * 25282+ * Licensed under the Apache License, Version 2.0 (the "License"); 25283+ * you may not use this file except in compliance with the License. 25284+ * You may obtain a copy of the License at 25285+ * 25286+ * http://www.apache.org/licenses/LICENSE-2.0 25287+ * 25288+ * Unless required by applicable law or agreed to in writing, software 25289+ * distributed under the License is distributed on an "AS IS" BASIS, 25290+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25291+ * See the License for the specific language governing permissions and 25292+ * limitations under the License. 25293+ */ 25294+ 25295+#pragma once 25296+ 25297+#include <vector> 25298+#include <iostream> 25299+#include <fstream> 25300+#include <sstream> 25301+#include <memory.h> 25302+ 25303+/*! 25304+ * Simple class to manipulate PGM/PPM images. Not suitable for heavy lifting. 25305+ */ 25306+class PgmImage 25307+{ 25308+ friend std::ostream& operator<< (std::ostream& o, const PgmImage& im); 25309+public: 25310+ enum {PGM_BINARY_GRAYMAP,PGM_BINARY_PIXMAP,PGM_FORMAT_INVALID}; 25311+ /*! 25312+ * Constructor from a PGM file name. 25313+ */ 25314+ PgmImage(std::string filename); 25315+ /*! 25316+ * Constructor to allocate an image of given size and type. 25317+ */ 25318+ PgmImage(int w, int h, int format = PGM_BINARY_GRAYMAP); 25319+ /*! 25320+ * Constructor to allocate an image of given size and copy the data in. 25321+ */ 25322+ PgmImage(unsigned char *data, int w, int h); 25323+ /*! 25324+ * Constructor to allocate an image of given size and copy the data in. 25325+ */ 25326+ PgmImage(std::vector<unsigned char> &data, int w, int h); 25327+ 25328+ PgmImage(const PgmImage &im); 25329+ 25330+ PgmImage& operator= (const PgmImage &im); 25331+ ~PgmImage(); 25332+ 25333+ int GetHeight() const { return m_h; } 25334+ int GetWidth() const { return m_w; } 25335+ 25336+ //! Copy pixels from data pointer 25337+ void SetData(const unsigned char * data); 25338+ 25339+ //! Get a data pointer to unaligned memory area 25340+ unsigned char * GetDataPointer() { if ( m_data.size() > 0 ) return &m_data[0]; else return NULL; } 25341+ unsigned char ** GetRowPointers() { if ( m_rows.size() == m_h ) return &m_rows[0]; else return NULL; } 25342+ 25343+ //! Read a PGM file from disk 25344+ bool ReadPGM(const std::string filename); 25345+ //! Write a PGM file to disk 25346+ bool WritePGM(const std::string filename, const std::string comment=""); 25347+ 25348+ //! Get image format (returns PGM_BINARY_GRAYMAP, PGM_BINARY_PIXMAP or PGM_FORMAT_INVALID) 25349+ int GetFormat() const { return m_format; } 25350+ 25351+ //! Set image format (returns PGM_BINARY_GRAYMAP, PGM_BINARY_PIXMAP). Image data becomes invalid. 25352+ void SetFormat(int format); 25353+ 25354+ //! If the image is PGM_BINARY_PIXMAP, convert it to PGM_BINARY_GRAYMAP via Y = 0.3*R + 0.59*G + 0.11*B. 25355+ void ConvertToGray(); 25356+protected: 25357+ // Generic functions: 25358+ void DeepCopy(const PgmImage& src, PgmImage& dst); 25359+ void SetupRowPointers(); 25360+ 25361+ // PGM data 25362+ int m_w; 25363+ int m_h; 25364+ int m_format; 25365+ int m_colors; 25366+ int m_over_allocation; 25367+ std::vector<unsigned char> m_data; 25368+ std::string m_comment; 25369+ 25370+ std::vector<unsigned char *> m_rows; 25371+}; 25372+ 25373+std::ostream& operator<< (std::ostream& o, const PgmImage& im); 25374diff --git a/benchmark/feature_stab/src/dbregtest/dbregtest.cpp b/benchmark/feature_stab/src/dbregtest/dbregtest.cpp 25375new file mode 100644 25376index 00000000..50873621 25377--- /dev/null 25378+++ b/benchmark/feature_stab/src/dbregtest/dbregtest.cpp 25379@@ -0,0 +1,399 @@ 25380+/* 25381+ * Copyright (C) 2011 The Android Open Source Project 25382+ * 25383+ * Licensed under the Apache License, Version 2.0 (the "License"); 25384+ * you may not use this file except in compliance with the License. 25385+ * You may obtain a copy of the License at 25386+ * 25387+ * http://www.apache.org/licenses/LICENSE-2.0 25388+ * 25389+ * Unless required by applicable law or agreed to in writing, software 25390+ * distributed under the License is distributed on an "AS IS" BASIS, 25391+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25392+ * See the License for the specific language governing permissions and 25393+ * limitations under the License. 25394+ */ 25395+ 25396+// $Id: dbregtest.cpp,v 1.24 2011/06/17 14:04:33 mbansal Exp $ 25397+#include "stdafx.h" 25398+#include "PgmImage.h" 25399+#include "../dbreg/dbreg.h" 25400+#include "../dbreg/dbstabsmooth.h" 25401+#include <db_utilities_camera.h> 25402+ 25403+#include <iostream> 25404+#include <iomanip> 25405+ 25406+#if PROFILE 25407+ #include <sys/time.h> 25408+#endif 25409+ 25410+ 25411+using namespace std; 25412+ 25413+const int DEFAULT_NR_CORNERS=500; 25414+const double DEFAULT_MAX_DISPARITY=0.2; 25415+const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_AFFINE; 25416+//const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_R_T; 25417+//const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_TRANSLATION; 25418+const bool DEFAULT_QUARTER_RESOLUTION=false; 25419+const unsigned int DEFAULT_REFERENCE_UPDATE_PERIOD=3; 25420+const bool DEFAULT_DO_MOTION_SMOOTHING = false; 25421+const double DEFAULT_MOTION_SMOOTHING_GAIN = 0.75; 25422+const bool DEFAULT_LINEAR_POLISH = false; 25423+const int DEFAULT_MAX_ITERATIONS = 10; 25424+ 25425+void usage(string name) { 25426+ 25427+ const char *helpmsg[] = { 25428+ "Function: point-based frame to reference registration.", 25429+ " -m [rt,a,p] : motion model, rt = rotation+translation, a = affine (default = affine).", 25430+ " -c <int> : number of corners (default 1000).", 25431+ " -d <double>: search disparity as portion of image size (default 0.1).", 25432+ " -q : quarter the image resolution (i.e. half of each dimension) (default on)", 25433+ " -r <int> : the period (in nr of frames) for reference frame updates (default = 5)", 25434+ " -s <0/1> : motion smoothing (1 activates motion smoothing, 0 turns it off - default value = 1)", 25435+ " -g <double>: motion smoothing gain, only used if smoothing is on (default value =0.75)", 25436+ NULL 25437+ }; 25438+ 25439+ cerr << "Usage: " << name << " [options] image_list.txt" << endl; 25440+ 25441+ const char **p = helpmsg; 25442+ 25443+ while (*p) 25444+ { 25445+ cerr << *p++ << endl; 25446+ } 25447+} 25448+ 25449+void parse_cmd_line(stringstream& cmdline, 25450+ const int argc, 25451+ const string& progname, 25452+ string& image_list_file_name, 25453+ int& nr_corners, 25454+ double& max_disparity, 25455+ int& motion_model_type, 25456+ bool& quarter_resolution, 25457+ unsigned int& reference_update_period, 25458+ bool& do_motion_smoothing, 25459+ double& motion_smoothing_gain 25460+ ); 25461+ 25462+int main(int argc, char* argv[]) 25463+{ 25464+ int nr_corners = DEFAULT_NR_CORNERS; 25465+ double max_disparity = DEFAULT_MAX_DISPARITY; 25466+ int motion_model_type = DEFAULT_MOTION_MODEL; 25467+ bool quarter_resolution = DEFAULT_QUARTER_RESOLUTION; 25468+ 25469+ unsigned int reference_update_period = DEFAULT_REFERENCE_UPDATE_PERIOD; 25470+ 25471+ bool do_motion_smoothing = DEFAULT_DO_MOTION_SMOOTHING; 25472+ double motion_smoothing_gain = DEFAULT_MOTION_SMOOTHING_GAIN; 25473+ const bool DEFAULT_USE_SMALLER_MATCHING_WINDOW = true; 25474+ 25475+ int default_nr_samples = DB_DEFAULT_NR_SAMPLES/5; 25476+ 25477+ bool use_smaller_matching_window = DEFAULT_USE_SMALLER_MATCHING_WINDOW; 25478+ 25479+ 25480+ bool linear_polish = DEFAULT_LINEAR_POLISH; 25481+ 25482+ if (argc < 2) { 25483+ usage(argv[0]); 25484+ exit(1); 25485+ } 25486+ 25487+ stringstream cmdline; 25488+ string progname(argv[0]); 25489+ string image_list_file_name; 25490+ 25491+#if PROFILE 25492+ timeval ts1, ts2, ts3, ts4; 25493+#endif 25494+ 25495+ // put the options and image list file name into the cmdline stringstream 25496+ for (int c = 1; c < argc; c++) 25497+ { 25498+ cmdline << argv[c] << " "; 25499+ } 25500+ 25501+ parse_cmd_line(cmdline, argc, progname, image_list_file_name, nr_corners, max_disparity, motion_model_type,quarter_resolution,reference_update_period,do_motion_smoothing,motion_smoothing_gain); 25502+ 25503+ ifstream in(image_list_file_name.c_str(),ios::in); 25504+ 25505+ if ( !in.is_open() ) 25506+ { 25507+ cerr << "Could not open file " << image_list_file_name << ". Exiting" << endl; 25508+ 25509+ return false; 25510+ } 25511+ 25512+ // feature-based image registration class: 25513+ db_FrameToReferenceRegistration reg; 25514+// db_StabilizationSmoother stab_smoother; 25515+ 25516+ // input file name: 25517+ string file_name; 25518+ 25519+ // look-up tables for image warping: 25520+ float ** lut_x = NULL, **lut_y = NULL; 25521+ 25522+ // if the images are color, the input is saved in color_ref: 25523+ PgmImage color_ref(0,0); 25524+ 25525+ // image width, height: 25526+ int w,h; 25527+ 25528+ int frame_number = 0; 25529+ 25530+ while ( !in.eof() ) 25531+ { 25532+ getline(in,file_name); 25533+ 25534+ PgmImage ref(file_name); 25535+ 25536+ if ( ref.GetDataPointer() == NULL ) 25537+ { 25538+ cerr << "Could not open image" << file_name << ". Exiting." << endl; 25539+ return -1; 25540+ } 25541+ 25542+ cout << ref << endl; 25543+ 25544+ // color format: 25545+ int format = ref.GetFormat(); 25546+ 25547+ // is the input image color?: 25548+ bool color = format == PgmImage::PGM_BINARY_PIXMAP; 25549+ 25550+ w = ref.GetWidth(); 25551+ h = ref.GetHeight(); 25552+ 25553+ if ( !reg.Initialized() ) 25554+ { 25555+ reg.Init(w,h,motion_model_type,DEFAULT_MAX_ITERATIONS,linear_polish,quarter_resolution,DB_POINT_STANDARDDEV,reference_update_period,do_motion_smoothing,motion_smoothing_gain,default_nr_samples,DB_DEFAULT_CHUNK_SIZE,nr_corners,max_disparity,use_smaller_matching_window); 25556+ lut_x = db_AllocImage_f(w,h); 25557+ lut_y = db_AllocImage_f(w,h); 25558+ 25559+ } 25560+ 25561+ if ( color ) 25562+ { 25563+ // save the color image: 25564+ color_ref = ref; 25565+ } 25566+ 25567+ // make a grayscale image: 25568+ ref.ConvertToGray(); 25569+ 25570+ // compute the homography: 25571+ double H[9],Hinv[9]; 25572+ db_Identity3x3(Hinv); 25573+ db_Identity3x3(H); 25574+ 25575+ bool force_reference = false; 25576+ 25577+#if PROFILE 25578+ gettimeofday(&ts1, NULL); 25579+#endif 25580+ 25581+ reg.AddFrame(ref.GetRowPointers(),H,false,false); 25582+ cout << reg.profile_string << std::endl; 25583+ 25584+#if PROFILE 25585+ gettimeofday(&ts2, NULL); 25586+ 25587+ double elapsedTime = (ts2.tv_sec - ts1.tv_sec)*1000.0; // sec to ms 25588+ elapsedTime += (ts2.tv_usec - ts1.tv_usec)/1000.0; // us to ms 25589+ cout <<"\nelapsedTime for Reg<< "<<elapsedTime<<" ms >>>>>>>>>>>>>\n"; 25590+#endif 25591+ 25592+ if (frame_number == 0) 25593+ { 25594+ reg.UpdateReference(ref.GetRowPointers()); 25595+ } 25596+ 25597+ 25598+ //std::vector<int> &inlier_indices = reg.GetInliers(); 25599+ int *inlier_indices = reg.GetInliers(); 25600+ int num_inlier_indices = reg.GetNrInliers(); 25601+ printf("[%d] #Inliers = %d\n",frame_number,num_inlier_indices); 25602+ 25603+ reg.Get_H_dref_to_ins(H); 25604+ 25605+ db_GenerateHomographyLut(lut_x,lut_y,w,h,H); 25606+ 25607+ // create a new image and warp: 25608+ PgmImage warped(w,h,format); 25609+ 25610+#if PROFILE 25611+ gettimeofday(&ts3, NULL); 25612+#endif 25613+ 25614+ if ( color ) 25615+ db_WarpImageLutBilinear_rgb(color_ref.GetRowPointers(),warped.GetRowPointers(),w,h,lut_x,lut_y); 25616+ else 25617+ db_WarpImageLut_u(ref.GetRowPointers(),warped.GetRowPointers(),w,h,lut_x,lut_y,DB_WARP_FAST); 25618+ 25619+#if PROFILE 25620+ gettimeofday(&ts4, NULL); 25621+ elapsedTime = (ts4.tv_sec - ts3.tv_sec)*1000.0; // sec to ms 25622+ elapsedTime += (ts4.tv_usec - ts3.tv_usec)/1000.0; // us to ms 25623+ cout <<"\nelapsedTime for Warp <<"<<elapsedTime<<" ms >>>>>>>>>>>>>\n"; 25624+#endif 25625+ 25626+ // write aligned image: name is aligned_<corresponding input file name> 25627+ stringstream s; 25628+ s << "aligned_" << file_name; 25629+ warped.WritePGM(s.str()); 25630+ 25631+ /* 25632+ // Get the reference and inspection corners to write to file 25633+ double *ref_corners = reg.GetRefCorners(); 25634+ double *ins_corners = reg.GetInsCorners(); 25635+ 25636+ // get the image file name (without extension), so we 25637+ // can generate the corresponding filenames for matches 25638+ // and inliers 25639+ string file_name_root(file_name.substr(0,file_name.rfind("."))); 25640+ 25641+ // write matches to file 25642+ s.str(string("")); 25643+ s << "Matches_" << file_name_root << ".txt"; 25644+ 25645+ ofstream match_file(s.str().c_str()); 25646+ 25647+ for (int i = 0; i < reg.GetNrMatches(); i++) 25648+ { 25649+ match_file << ref_corners[3*i] << " " << ref_corners[3*i+1] << " " << ins_corners[3*i] << " " << ins_corners[3*i+1] << endl; 25650+ } 25651+ 25652+ match_file.close(); 25653+ 25654+ // write the inlier matches to file 25655+ s.str(string("")); 25656+ s << "InlierMatches_" << file_name_root << ".txt"; 25657+ 25658+ ofstream inlier_match_file(s.str().c_str()); 25659+ 25660+ for(int i=0; i<num_inlier_indices; i++) 25661+ { 25662+ int k = inlier_indices[i]; 25663+ inlier_match_file << ref_corners[3*k] << " " 25664+ << ref_corners[3*k+1] << " " 25665+ << ins_corners[3*k] << " " 25666+ << ins_corners[3*k+1] << endl; 25667+ } 25668+ inlier_match_file.close(); 25669+ */ 25670+ 25671+ frame_number++; 25672+ } 25673+ 25674+ if ( reg.Initialized() ) 25675+ { 25676+ db_FreeImage_f(lut_x,h); 25677+ db_FreeImage_f(lut_y,h); 25678+ } 25679+ 25680+ return 0; 25681+} 25682+ 25683+void parse_cmd_line(stringstream& cmdline, 25684+ const int argc, 25685+ const string& progname, 25686+ string& image_list_file_name, 25687+ int& nr_corners, 25688+ double& max_disparity, 25689+ int& motion_model_type, 25690+ bool& quarter_resolution, 25691+ unsigned int& reference_update_period, 25692+ bool& do_motion_smoothing, 25693+ double& motion_smoothing_gain) 25694+{ 25695+ // for counting down the parsed arguments. 25696+ int c = argc; 25697+ 25698+ // a holder 25699+ string token; 25700+ 25701+ while (cmdline >> token) 25702+ { 25703+ --c; 25704+ 25705+ int pos = token.find("-"); 25706+ 25707+ if (pos == 0) 25708+ { 25709+ switch (token[1]) 25710+ { 25711+ case 'm': 25712+ --c; cmdline >> token; 25713+ if (token.compare("rt") == 0) 25714+ { 25715+ motion_model_type = DB_HOMOGRAPHY_TYPE_R_T; 25716+ } 25717+ else if (token.compare("a") == 0) 25718+ { 25719+ motion_model_type = DB_HOMOGRAPHY_TYPE_AFFINE; 25720+ } 25721+ else if (token.compare("p") == 0) 25722+ { 25723+ motion_model_type = DB_HOMOGRAPHY_TYPE_PROJECTIVE; 25724+ } 25725+ else 25726+ { 25727+ usage(progname); 25728+ exit(1); 25729+ } 25730+ break; 25731+ case 'c': 25732+ --c; cmdline >> nr_corners; 25733+ break; 25734+ case 'd': 25735+ --c; cmdline >> max_disparity; 25736+ break; 25737+ case 'q': 25738+ quarter_resolution = true; 25739+ break; 25740+ case 'r': 25741+ --c; cmdline >> reference_update_period; 25742+ break; 25743+ case 's': 25744+ --c; cmdline >> do_motion_smoothing; 25745+ break; 25746+ case 'g': 25747+ --c; cmdline >> motion_smoothing_gain; 25748+ break; 25749+ default: 25750+ cerr << progname << "illegal option " << token << endl; 25751+ case 'h': 25752+ usage(progname); 25753+ exit(1); 25754+ break; 25755+ } 25756+ } 25757+ else 25758+ { 25759+ if (c != 1) 25760+ { 25761+ usage(progname); 25762+ exit(1); 25763+ } 25764+ else 25765+ { 25766+ --c; 25767+ image_list_file_name = token; 25768+ } 25769+ } 25770+ } 25771+ 25772+ if (c != 0) 25773+ { 25774+ usage(progname); 25775+ exit(1); 25776+ } 25777+} 25778+ 25779diff --git a/benchmark/feature_stab/src/dbregtest/stdafx.cpp b/benchmark/feature_stab/src/dbregtest/stdafx.cpp 25780new file mode 100644 25781index 00000000..0c703e2d 25782--- /dev/null 25783+++ b/benchmark/feature_stab/src/dbregtest/stdafx.cpp 25784@@ -0,0 +1,24 @@ 25785+/* 25786+ * Copyright (C) 2011 The Android Open Source Project 25787+ * 25788+ * Licensed under the Apache License, Version 2.0 (the "License"); 25789+ * you may not use this file except in compliance with the License. 25790+ * You may obtain a copy of the License at 25791+ * 25792+ * http://www.apache.org/licenses/LICENSE-2.0 25793+ * 25794+ * Unless required by applicable law or agreed to in writing, software 25795+ * distributed under the License is distributed on an "AS IS" BASIS, 25796+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25797+ * See the License for the specific language governing permissions and 25798+ * limitations under the License. 25799+ */ 25800+ 25801+// stdafx.cpp : source file that includes just the standard includes 25802+// dbregtest.pch will be the pre-compiled header 25803+// stdafx.obj will contain the pre-compiled type information 25804+ 25805+#include "stdafx.h" 25806+ 25807+// TODO: reference any additional headers you need in STDAFX.H 25808+// and not in this file 25809diff --git a/benchmark/feature_stab/src/dbregtest/stdafx.h b/benchmark/feature_stab/src/dbregtest/stdafx.h 25810new file mode 100644 25811index 00000000..9bc06ea0 25812--- /dev/null 25813+++ b/benchmark/feature_stab/src/dbregtest/stdafx.h 25814@@ -0,0 +1,28 @@ 25815+/* 25816+ * Copyright (C) 2011 The Android Open Source Project 25817+ * 25818+ * Licensed under the Apache License, Version 2.0 (the "License"); 25819+ * you may not use this file except in compliance with the License. 25820+ * You may obtain a copy of the License at 25821+ * 25822+ * http://www.apache.org/licenses/LICENSE-2.0 25823+ * 25824+ * Unless required by applicable law or agreed to in writing, software 25825+ * distributed under the License is distributed on an "AS IS" BASIS, 25826+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25827+ * See the License for the specific language governing permissions and 25828+ * limitations under the License. 25829+ */ 25830+ 25831+// stdafx.h : include file for standard system include files, 25832+// or project specific include files that are used frequently, but 25833+// are changed infrequently 25834+// 25835+ 25836+#pragma once 25837+ 25838+#include "targetver.h" 25839+ 25840+#include <stdio.h> 25841+ 25842+// TODO: reference additional headers your program requires here 25843diff --git a/benchmark/feature_stab/src/dbregtest/targetver.h b/benchmark/feature_stab/src/dbregtest/targetver.h 25844new file mode 100644 25845index 00000000..9272b0d6 25846--- /dev/null 25847+++ b/benchmark/feature_stab/src/dbregtest/targetver.h 25848@@ -0,0 +1,29 @@ 25849+/* 25850+ * Copyright (C) 2011 The Android Open Source Project 25851+ * 25852+ * Licensed under the Apache License, Version 2.0 (the "License"); 25853+ * you may not use this file except in compliance with the License. 25854+ * You may obtain a copy of the License at 25855+ * 25856+ * http://www.apache.org/licenses/LICENSE-2.0 25857+ * 25858+ * Unless required by applicable law or agreed to in writing, software 25859+ * distributed under the License is distributed on an "AS IS" BASIS, 25860+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25861+ * See the License for the specific language governing permissions and 25862+ * limitations under the License. 25863+ */ 25864+ 25865+#pragma once 25866+ 25867+// The following macros define the minimum required platform. The minimum required platform 25868+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run 25869+// your application. The macros work by enabling all features available on platform versions up to and 25870+// including the version specified. 25871+ 25872+// Modify the following defines if you have to target a platform prior to the ones specified below. 25873+// Refer to MSDN for the latest info on corresponding values for different platforms. 25874+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. 25875+#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. 25876+#endif 25877+ 25878diff --git a/benchmark/mosaic_renderer_jni.cpp b/benchmark/mosaic_renderer_jni.cpp 25879new file mode 100644 25880index 00000000..bb01e7fc 25881--- /dev/null 25882+++ b/benchmark/mosaic_renderer_jni.cpp 25883@@ -0,0 +1,762 @@ 25884+/* 25885+ * Copyright (C) 2011 The Android Open Source Project 25886+ * 25887+ * Licensed under the Apache License, Version 2.0 (the "License"); 25888+ * you may not use this file except in compliance with the License. 25889+ * You may obtain a copy of the License at 25890+ * 25891+ * http://www.apache.org/licenses/LICENSE-2.0 25892+ * 25893+ * Unless required by applicable law or agreed to in writing, software 25894+ * distributed under the License is distributed on an "AS IS" BASIS, 25895+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25896+ * See the License for the specific language governing permissions and 25897+ * limitations under the License. 25898+ */ 25899+ 25900+#include <GLES2/gl2.h> 25901+#include <GLES2/gl2ext.h> 25902+#include <jni.h> 25903+#include <math.h> 25904+#include <stdio.h> 25905+#include <stdlib.h> 25906+#include "db_utilities_camera.h" 25907+#include "mosaic/ImageUtils.h" 25908+#include "mosaic_renderer/FrameBuffer.h" 25909+#include "mosaic_renderer/WarpRenderer.h" 25910+#include "mosaic_renderer/SurfaceTextureRenderer.h" 25911+#include "mosaic_renderer/YVURenderer.h" 25912+ 25913+#include "mosaic/Log.h" 25914+#define LOG_TAG "MosaicRenderer" 25915+ 25916+#include "mosaic_renderer_jni.h" 25917+ 25918+// Texture handle 25919+GLuint gSurfaceTextureID[1]; 25920+ 25921+bool gWarpImage = true; 25922+ 25923+// Low-Res input image frame in YUVA format for preview rendering and processing 25924+// and high-res YUVA input image for processing. 25925+unsigned char* gPreviewImage[NR]; 25926+// Low-Res & high-res preview image width 25927+int gPreviewImageWidth[NR]; 25928+// Low-Res & high-res preview image height 25929+int gPreviewImageHeight[NR]; 25930+ 25931+// Semaphore to protect simultaneous read/writes from gPreviewImage 25932+sem_t gPreviewImage_semaphore; 25933+ 25934+// Off-screen preview FBO width (large enough to store the entire 25935+// preview mosaic). 25936+int gPreviewFBOWidth; 25937+// Off-screen preview FBO height (large enough to store the entire 25938+// preview mosaic). 25939+int gPreviewFBOHeight; 25940+ 25941+// gK is the transformation to map the canonical {-1,1} vertex coordinate system 25942+// to the {0,gPreviewImageWidth[LR]} input image frame coordinate system before 25943+// applying the given affine transformation trs. gKm is the corresponding 25944+// transformation for going to the {0,gPreviewFBOWidth}. 25945+double gK[9]; 25946+double gKinv[9]; 25947+double gKm[9]; 25948+double gKminv[9]; 25949+ 25950+// Shader to copy input SurfaceTexture into and RGBA FBO. The two shaders 25951+// render to the textures with dimensions corresponding to the low-res and 25952+// high-res image frames. 25953+SurfaceTextureRenderer gSurfTexRenderer[NR]; 25954+// Off-screen FBOs to store the low-res and high-res RGBA copied out from 25955+// the SurfaceTexture by the gSurfTexRenderers. 25956+FrameBuffer gBufferInput[NR]; 25957+ 25958+// Shader to convert RGBA textures into YVU textures for processing 25959+YVURenderer gYVURenderer[NR]; 25960+// Off-screen FBOs to store the low-res and high-res YVU textures for processing 25961+FrameBuffer gBufferInputYVU[NR]; 25962+ 25963+// Shader to translate the flip-flop FBO - gBuffer[1-current] -> gBuffer[current] 25964+WarpRenderer gWarper1; 25965+// Shader to add warped current frame to the flip-flop FBO - gBuffer[current] 25966+WarpRenderer gWarper2; 25967+// Off-screen FBOs (flip-flop) to store the result of gWarper1 & gWarper2 25968+FrameBuffer gBuffer[2]; 25969+ 25970+// Shader to warp and render the preview FBO to the screen 25971+WarpRenderer gPreview; 25972+ 25973+// Index of the gBuffer FBO gWarper1 is going to write into 25974+int gCurrentFBOIndex = 0; 25975+ 25976+// 3x3 Matrices holding the transformation of this frame (gThisH1t) and of 25977+// the last frame (gLastH1t) w.r.t the first frame. 25978+double gThisH1t[9]; 25979+double gLastH1t[9]; 25980+ 25981+// Variables to represent the fixed position of the top-left corner of the 25982+// current frame in the previewFBO 25983+double gCenterOffsetX = 0.0f; 25984+double gCenterOffsetY = 0.0f; 25985+ 25986+// X-Offset of the viewfinder (current frame) w.r.t 25987+// (gCenterOffsetX, gCenterOffsetY). This offset varies with time and is 25988+// used to pan the viewfinder across the UI layout. 25989+double gPanOffset = 0.0f; 25990+ 25991+// Variables tracking the translation value for the current frame and the 25992+// last frame (both w.r.t the first frame). The difference between these 25993+// values is used to control the panning speed of the viewfinder display 25994+// on the UI screen. 25995+double gThisTx = 0.0f; 25996+double gLastTx = 0.0f; 25997+ 25998+// These are the scale factors used by the gPreview shader to ensure that 25999+// the image frame is correctly scaled to the full UI layout height while 26000+// maintaining its aspect ratio 26001+double gUILayoutScalingX = 1.0f; 26002+double gUILayoutScalingY = 1.0f; 26003+ 26004+// Whether the view that we will render preview FBO onto is in landscape or portrait 26005+// orientation. 26006+bool gIsLandscapeOrientation = true; 26007+ 26008+// State of the viewfinder. Set to false when the viewfinder hits the UI edge. 26009+bool gPanViewfinder = true; 26010+ 26011+// Affine transformation in GL 4x4 format (column-major) to warp the 26012+// last frame mosaic into the current frame coordinate system. 26013+GLfloat g_dAffinetransGL[16]; 26014+double g_dAffinetrans[16]; 26015+ 26016+// Affine transformation in GL 4x4 format (column-major) to translate the 26017+// preview FBO across the screen (viewfinder panning). 26018+GLfloat g_dAffinetransPanGL[16]; 26019+double g_dAffinetransPan[16]; 26020+ 26021+// XY translation in GL 4x4 format (column-major) to center the current 26022+// preview mosaic in the preview FBO 26023+GLfloat g_dTranslationToFBOCenterGL[16]; 26024+double g_dTranslationToFBOCenter[16]; 26025+ 26026+// GL 4x4 Identity transformation 26027+GLfloat g_dAffinetransIdentGL[] = { 26028+ 1., 0., 0., 0., 26029+ 0., 1., 0., 0., 26030+ 0., 0., 1., 0., 26031+ 0., 0., 0., 1.}; 26032+ 26033+// GL 4x4 Rotation transformation (column-majored): 90 degree 26034+GLfloat g_dAffinetransRotation90GL[] = { 26035+ 0., 1., 0., 0., 26036+ -1., 0., 0., 0., 26037+ 0., 0., 1., 0., 26038+ 0., 0., 0., 1.}; 26039+ 26040+// 3x3 Rotation transformation (row-majored): 90 degree 26041+double gRotation90[] = { 26042+ 0., -1., 0., 26043+ 1., 0., 0., 26044+ 0., 0., 1.,}; 26045+ 26046+ 26047+float g_dIdent3x3[] = { 26048+ 1.0, 0.0, 0.0, 26049+ 0.0, 1.0, 0.0, 26050+ 0.0, 0.0, 1.0}; 26051+ 26052+const int GL_TEXTURE_EXTERNAL_OES_ENUM = 0x8D65; 26053+ 26054+static void printGLString(const char *name, GLenum s) { 26055+ const char *v = (const char *) glGetString(s); 26056+ LOGI("GL %s = %s", name, v); 26057+} 26058+ 26059+// @return false if there was an error 26060+bool checkGlError(const char* op) { 26061+ GLint error = glGetError(); 26062+ if (error != 0) { 26063+ LOGE("after %s() glError (0x%x)", op, error); 26064+ return false; 26065+ } 26066+ return true; 26067+} 26068+ 26069+void bindSurfaceTexture(GLuint texId) 26070+{ 26071+ glBindTexture(GL_TEXTURE_EXTERNAL_OES_ENUM, texId); 26072+ 26073+ // Can't do mipmapping with camera source 26074+ glTexParameterf(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_MIN_FILTER, 26075+ GL_LINEAR); 26076+ glTexParameterf(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_MAG_FILTER, 26077+ GL_LINEAR); 26078+ // Clamp to edge is the only option 26079+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_WRAP_S, 26080+ GL_CLAMP_TO_EDGE); 26081+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_WRAP_T, 26082+ GL_CLAMP_TO_EDGE); 26083+} 26084+ 26085+void ClearPreviewImage(int mID) 26086+{ 26087+ unsigned char* ptr = gPreviewImage[mID]; 26088+ for(int j = 0, i = 0; 26089+ j < gPreviewImageWidth[mID] * gPreviewImageHeight[mID] * 4; 26090+ j += 4) 26091+ { 26092+ ptr[i++] = 0; 26093+ ptr[i++] = 0; 26094+ ptr[i++] = 0; 26095+ ptr[i++] = 255; 26096+ } 26097+ 26098+} 26099+ 26100+void ConvertAffine3x3toGL4x4(double *matGL44, double *mat33) 26101+{ 26102+ matGL44[0] = mat33[0]; 26103+ matGL44[1] = mat33[3]; 26104+ matGL44[2] = 0.0; 26105+ matGL44[3] = mat33[6]; 26106+ 26107+ matGL44[4] = mat33[1]; 26108+ matGL44[5] = mat33[4]; 26109+ matGL44[6] = 0.0; 26110+ matGL44[7] = mat33[7]; 26111+ 26112+ matGL44[8] = 0; 26113+ matGL44[9] = 0; 26114+ matGL44[10] = 1.0; 26115+ matGL44[11] = 0.0; 26116+ 26117+ matGL44[12] = mat33[2]; 26118+ matGL44[13] = mat33[5]; 26119+ matGL44[14] = 0.0; 26120+ matGL44[15] = mat33[8]; 26121+} 26122+ 26123+bool continuePanningFBO(double panOffset) { 26124+ double normalizedScreenLimitLeft = -1.0 + VIEWPORT_BORDER_FACTOR_HORZ * 2.0; 26125+ double normalizedScreenLimitRight = 1.0 - VIEWPORT_BORDER_FACTOR_HORZ * 2.0; 26126+ double normalizedXPositionOnScreenLeft; 26127+ double normalizedXPositionOnScreenRight; 26128+ 26129+ // Compute the position of the current frame in the screen coordinate system 26130+ if (gIsLandscapeOrientation) { 26131+ normalizedXPositionOnScreenLeft = (2.0 * 26132+ (gCenterOffsetX + panOffset) / gPreviewFBOWidth - 1.0) * 26133+ gUILayoutScalingX; 26134+ normalizedXPositionOnScreenRight = (2.0 * 26135+ ((gCenterOffsetX + panOffset) + gPreviewImageWidth[HR]) / 26136+ gPreviewFBOWidth - 1.0) * gUILayoutScalingX; 26137+ } else { 26138+ normalizedXPositionOnScreenLeft = (2.0 * 26139+ (gCenterOffsetX + panOffset) / gPreviewFBOWidth - 1.0) * 26140+ gUILayoutScalingY; 26141+ normalizedXPositionOnScreenRight = (2.0 * 26142+ ((gCenterOffsetX + panOffset) + gPreviewImageWidth[HR]) / 26143+ gPreviewFBOWidth - 1.0) * gUILayoutScalingY; 26144+ } 26145+ 26146+ // Stop the viewfinder panning if we hit the maximum border allowed for 26147+ // this UI layout 26148+ if (normalizedXPositionOnScreenRight > normalizedScreenLimitRight || 26149+ normalizedXPositionOnScreenLeft < normalizedScreenLimitLeft) { 26150+ return false; 26151+ } else { 26152+ return true; 26153+ } 26154+} 26155+ 26156+// This function computes fills the 4x4 matrices g_dAffinetrans, 26157+// and g_dAffinetransPan using the specified 3x3 affine 26158+// transformation between the first captured frame and the current frame. 26159+// The computed g_dAffinetrans is such that it warps the preview mosaic in 26160+// the last frame's coordinate system into the coordinate system of the 26161+// current frame. Thus, applying this transformation will create the current 26162+// frame mosaic but with the current frame missing. This frame will then be 26163+// pasted in by gWarper2 after translating it by g_dTranslationToFBOCenter. 26164+// The computed g_dAffinetransPan is such that it offsets the computed preview 26165+// mosaic horizontally to make the viewfinder pan within the UI layout. 26166+void UpdateWarpTransformation(float *trs) 26167+{ 26168+ double H[9], Hp[9], Htemp1[9], Htemp2[9], T[9]; 26169+ 26170+ for(int i = 0; i < 9; i++) 26171+ { 26172+ gThisH1t[i] = trs[i]; 26173+ } 26174+ 26175+ // Alignment is done based on low-res data. 26176+ // To render the preview mosaic, the translation of the high-res mosaic is estimated to 26177+ // H2L_FACTOR x low-res-based tranlation. 26178+ gThisH1t[2] *= H2L_FACTOR; 26179+ gThisH1t[5] *= H2L_FACTOR; 26180+ 26181+ db_Identity3x3(T); 26182+ T[2] = -gCenterOffsetX; 26183+ T[5] = -gCenterOffsetY; 26184+ 26185+ // H = ( inv(gThisH1t) * gLastH1t ) * T 26186+ db_Identity3x3(Htemp1); 26187+ db_Identity3x3(Htemp2); 26188+ db_Identity3x3(H); 26189+ db_InvertAffineTransform(Htemp1, gThisH1t); 26190+ db_Multiply3x3_3x3(Htemp2, Htemp1, gLastH1t); 26191+ db_Multiply3x3_3x3(H, Htemp2, T); 26192+ 26193+ for(int i = 0; i < 9; i++) 26194+ { 26195+ gLastH1t[i] = gThisH1t[i]; 26196+ } 26197+ 26198+ // Move the origin such that the frame is centered in the previewFBO 26199+ // i.e. H = inv(T) * H 26200+ H[2] += gCenterOffsetX; 26201+ H[5] += gCenterOffsetY; 26202+ 26203+ // Hp = inv(Km) * H * Km 26204+ // Km moves the coordinate system from openGL to image pixels so 26205+ // that the alignment transform H can be applied to them. 26206+ // inv(Km) moves the coordinate system back to openGL normalized 26207+ // coordinates so that the shader can correctly render it. 26208+ db_Identity3x3(Htemp1); 26209+ db_Multiply3x3_3x3(Htemp1, H, gKm); 26210+ db_Multiply3x3_3x3(Hp, gKminv, Htemp1); 26211+ 26212+ ConvertAffine3x3toGL4x4(g_dAffinetrans, Hp); 26213+ 26214+ //////////////////////////////////////////////// 26215+ ////// Compute g_dAffinetransPan now... ////// 26216+ //////////////////////////////////////////////// 26217+ 26218+ gThisTx = trs[2]; 26219+ 26220+ if(gPanViewfinder) 26221+ { 26222+ gPanOffset += (gThisTx - gLastTx) * VIEWFINDER_PAN_FACTOR_HORZ; 26223+ } 26224+ 26225+ gLastTx = gThisTx; 26226+ gPanViewfinder = continuePanningFBO(gPanOffset); 26227+ 26228+ db_Identity3x3(H); 26229+ H[2] = gPanOffset; 26230+ 26231+ // Hp = inv(Km) * H * Km 26232+ db_Identity3x3(Htemp1); 26233+ db_Multiply3x3_3x3(Htemp1, H, gKm); 26234+ db_Multiply3x3_3x3(Hp, gKminv, Htemp1); 26235+ 26236+ if (gIsLandscapeOrientation) { 26237+ ConvertAffine3x3toGL4x4(g_dAffinetransPan, Hp); 26238+ } else { 26239+ // rotate Hp by 90 degress. 26240+ db_Multiply3x3_3x3(Htemp1, gRotation90, Hp); 26241+ ConvertAffine3x3toGL4x4(g_dAffinetransPan, Htemp1); 26242+ } 26243+} 26244+ 26245+void AllocateTextureMemory(int widthHR, int heightHR, int widthLR, int heightLR) 26246+{ 26247+ gPreviewImageWidth[HR] = widthHR; 26248+ gPreviewImageHeight[HR] = heightHR; 26249+ 26250+ gPreviewImageWidth[LR] = widthLR; 26251+ gPreviewImageHeight[LR] = heightLR; 26252+ 26253+ sem_init(&gPreviewImage_semaphore, 0, 1); 26254+ 26255+ sem_wait(&gPreviewImage_semaphore); 26256+ gPreviewImage[LR] = ImageUtils::allocateImage(gPreviewImageWidth[LR], 26257+ gPreviewImageHeight[LR], 4); 26258+ ClearPreviewImage(LR); 26259+ gPreviewImage[HR] = ImageUtils::allocateImage(gPreviewImageWidth[HR], 26260+ gPreviewImageHeight[HR], 4); 26261+ ClearPreviewImage(HR); 26262+ sem_post(&gPreviewImage_semaphore); 26263+ 26264+ gPreviewFBOWidth = PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[HR]; 26265+ gPreviewFBOHeight = PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[HR]; 26266+ 26267+ // The origin is such that the current frame will sit with its center 26268+ // at the center of the previewFBO 26269+ gCenterOffsetX = (gPreviewFBOWidth / 2 - gPreviewImageWidth[HR] / 2); 26270+ gCenterOffsetY = (gPreviewFBOHeight / 2 - gPreviewImageHeight[HR] / 2); 26271+ 26272+ gPanOffset = 0.0f; 26273+ 26274+ db_Identity3x3(gThisH1t); 26275+ db_Identity3x3(gLastH1t); 26276+ 26277+ gPanViewfinder = true; 26278+ 26279+ int w = gPreviewImageWidth[HR]; 26280+ int h = gPreviewImageHeight[HR]; 26281+ 26282+ int wm = gPreviewFBOWidth; 26283+ int hm = gPreviewFBOHeight; 26284+ 26285+ // K is the transformation to map the canonical [-1,1] vertex coordinate 26286+ // system to the [0,w] image coordinate system before applying the given 26287+ // affine transformation trs. 26288+ gKm[0] = wm / 2.0 - 0.5; 26289+ gKm[1] = 0.0; 26290+ gKm[2] = wm / 2.0 - 0.5; 26291+ gKm[3] = 0.0; 26292+ gKm[4] = hm / 2.0 - 0.5; 26293+ gKm[5] = hm / 2.0 - 0.5; 26294+ gKm[6] = 0.0; 26295+ gKm[7] = 0.0; 26296+ gKm[8] = 1.0; 26297+ 26298+ gK[0] = w / 2.0 - 0.5; 26299+ gK[1] = 0.0; 26300+ gK[2] = w / 2.0 - 0.5; 26301+ gK[3] = 0.0; 26302+ gK[4] = h / 2.0 - 0.5; 26303+ gK[5] = h / 2.0 - 0.5; 26304+ gK[6] = 0.0; 26305+ gK[7] = 0.0; 26306+ gK[8] = 1.0; 26307+ 26308+ db_Identity3x3(gKinv); 26309+ db_InvertCalibrationMatrix(gKinv, gK); 26310+ 26311+ db_Identity3x3(gKminv); 26312+ db_InvertCalibrationMatrix(gKminv, gKm); 26313+ 26314+ ////////////////////////////////////////// 26315+ ////// Compute g_Translation now... ////// 26316+ ////////////////////////////////////////// 26317+ double T[9], Tp[9], Ttemp[9]; 26318+ 26319+ db_Identity3x3(T); 26320+ T[2] = gCenterOffsetX; 26321+ T[5] = gCenterOffsetY; 26322+ 26323+ // Tp = inv(K) * T * K 26324+ db_Identity3x3(Ttemp); 26325+ db_Multiply3x3_3x3(Ttemp, T, gK); 26326+ db_Multiply3x3_3x3(Tp, gKinv, Ttemp); 26327+ 26328+ ConvertAffine3x3toGL4x4(g_dTranslationToFBOCenter, Tp); 26329+ 26330+ UpdateWarpTransformation(g_dIdent3x3); 26331+} 26332+ 26333+void FreeTextureMemory() 26334+{ 26335+ sem_wait(&gPreviewImage_semaphore); 26336+ ImageUtils::freeImage(gPreviewImage[LR]); 26337+ ImageUtils::freeImage(gPreviewImage[HR]); 26338+ sem_post(&gPreviewImage_semaphore); 26339+ 26340+ sem_destroy(&gPreviewImage_semaphore); 26341+} 26342+ 26343+extern "C" 26344+{ 26345+ JNIEXPORT jint JNICALL Java_com_android_camera_panorama_MosaicRenderer_init( 26346+ JNIEnv * env, jobject obj); 26347+ JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_reset( 26348+ JNIEnv * env, jobject obj, jint width, jint height, 26349+ jboolean isLandscapeOrientation); 26350+ JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_preprocess( 26351+ JNIEnv * env, jobject obj, jfloatArray stMatrix); 26352+ JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_transferGPUtoCPU( 26353+ JNIEnv * env, jobject obj); 26354+ JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_step( 26355+ JNIEnv * env, jobject obj); 26356+ JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_ready( 26357+ JNIEnv * env, jobject obj); 26358+ JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_setWarping( 26359+ JNIEnv * env, jobject obj, jboolean flag); 26360+}; 26361+ 26362+JNIEXPORT jint JNICALL Java_com_android_camera_panorama_MosaicRenderer_init( 26363+ JNIEnv * env, jobject obj) 26364+{ 26365+ gSurfTexRenderer[LR].InitializeGLProgram(); 26366+ gSurfTexRenderer[HR].InitializeGLProgram(); 26367+ gYVURenderer[LR].InitializeGLProgram(); 26368+ gYVURenderer[HR].InitializeGLProgram(); 26369+ gWarper1.InitializeGLProgram(); 26370+ gWarper2.InitializeGLProgram(); 26371+ gPreview.InitializeGLProgram(); 26372+ gBuffer[0].InitializeGLContext(); 26373+ gBuffer[1].InitializeGLContext(); 26374+ gBufferInput[LR].InitializeGLContext(); 26375+ gBufferInput[HR].InitializeGLContext(); 26376+ gBufferInputYVU[LR].InitializeGLContext(); 26377+ gBufferInputYVU[HR].InitializeGLContext(); 26378+ 26379+ glBindFramebuffer(GL_FRAMEBUFFER, 0); 26380+ 26381+ glGenTextures(1, gSurfaceTextureID); 26382+ // bind the surface texture 26383+ bindSurfaceTexture(gSurfaceTextureID[0]); 26384+ 26385+ return (jint) gSurfaceTextureID[0]; 26386+} 26387+ 26388+ 26389+void calculateUILayoutScaling(int width, int height, bool isLandscape) { 26390+ if (isLandscape) { 26391+ // __________ ______ 26392+ // |__________| => |______| 26393+ // (Preview FBO) (View) 26394+ // 26395+ // Scale the preview FBO's height to the height of view and 26396+ // maintain the aspect ratio of the current frame on the screen. 26397+ gUILayoutScalingY = PREVIEW_FBO_HEIGHT_SCALE; 26398+ 26399+ // Note that OpenGL scales a texture to view's width and height automatically. 26400+ // The "width / height" inverts the scaling, so as to maintain the aspect ratio 26401+ // of the current frame. 26402+ gUILayoutScalingX = ((float) (PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[LR]) 26403+ / (PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[LR]) * PREVIEW_FBO_HEIGHT_SCALE) 26404+ / ((float) width / height); 26405+ } else { 26406+ // __ 26407+ // __________ | | 26408+ // |__________| => | | 26409+ // (Preview FBO) | | 26410+ // |__| 26411+ // (View) 26412+ // Scale the preview FBO's height to the width of view and 26413+ // maintain the aspect ratio of the current frame on the screen. 26414+ gUILayoutScalingX = PREVIEW_FBO_HEIGHT_SCALE; 26415+ 26416+ // Note that OpenGL scales a texture to view's width and height automatically. 26417+ // The "height / width" inverts the scaling, so as to maintain the aspect ratio 26418+ // of the current frame. 26419+ gUILayoutScalingY = ((float) (PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[LR]) 26420+ / (PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[LR]) * PREVIEW_FBO_HEIGHT_SCALE) 26421+ / ((float) height / width); 26422+ 26423+ } 26424+} 26425+ 26426+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_reset( 26427+ JNIEnv * env, jobject obj, jint width, jint height, jboolean isLandscapeOrientation) 26428+{ 26429+ gIsLandscapeOrientation = isLandscapeOrientation; 26430+ calculateUILayoutScaling(width, height, gIsLandscapeOrientation); 26431+ 26432+ gBuffer[0].Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA); 26433+ gBuffer[1].Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA); 26434+ 26435+ gBufferInput[LR].Init(gPreviewImageWidth[LR], 26436+ gPreviewImageHeight[LR], GL_RGBA); 26437+ 26438+ gBufferInput[HR].Init(gPreviewImageWidth[HR], 26439+ gPreviewImageHeight[HR], GL_RGBA); 26440+ 26441+ gBufferInputYVU[LR].Init(gPreviewImageWidth[LR], 26442+ gPreviewImageHeight[LR], GL_RGBA); 26443+ 26444+ gBufferInputYVU[HR].Init(gPreviewImageWidth[HR], 26445+ gPreviewImageHeight[HR], GL_RGBA); 26446+ 26447+ sem_wait(&gPreviewImage_semaphore); 26448+ ClearPreviewImage(LR); 26449+ ClearPreviewImage(HR); 26450+ sem_post(&gPreviewImage_semaphore); 26451+ 26452+ // bind the surface texture 26453+ bindSurfaceTexture(gSurfaceTextureID[0]); 26454+ 26455+ gSurfTexRenderer[LR].SetupGraphics(&gBufferInput[LR]); 26456+ gSurfTexRenderer[LR].Clear(0.0, 0.0, 0.0, 1.0); 26457+ gSurfTexRenderer[LR].SetViewportMatrix(1, 1, 1, 1); 26458+ gSurfTexRenderer[LR].SetScalingMatrix(1.0f, -1.0f); 26459+ gSurfTexRenderer[LR].SetInputTextureName(gSurfaceTextureID[0]); 26460+ gSurfTexRenderer[LR].SetInputTextureType(GL_TEXTURE_EXTERNAL_OES_ENUM); 26461+ 26462+ gSurfTexRenderer[HR].SetupGraphics(&gBufferInput[HR]); 26463+ gSurfTexRenderer[HR].Clear(0.0, 0.0, 0.0, 1.0); 26464+ gSurfTexRenderer[HR].SetViewportMatrix(1, 1, 1, 1); 26465+ gSurfTexRenderer[HR].SetScalingMatrix(1.0f, -1.0f); 26466+ gSurfTexRenderer[HR].SetInputTextureName(gSurfaceTextureID[0]); 26467+ gSurfTexRenderer[HR].SetInputTextureType(GL_TEXTURE_EXTERNAL_OES_ENUM); 26468+ 26469+ gYVURenderer[LR].SetupGraphics(&gBufferInputYVU[LR]); 26470+ gYVURenderer[LR].Clear(0.0, 0.0, 0.0, 1.0); 26471+ gYVURenderer[LR].SetInputTextureName(gBufferInput[LR].GetTextureName()); 26472+ gYVURenderer[LR].SetInputTextureType(GL_TEXTURE_2D); 26473+ 26474+ gYVURenderer[HR].SetupGraphics(&gBufferInputYVU[HR]); 26475+ gYVURenderer[HR].Clear(0.0, 0.0, 0.0, 1.0); 26476+ gYVURenderer[HR].SetInputTextureName(gBufferInput[HR].GetTextureName()); 26477+ gYVURenderer[HR].SetInputTextureType(GL_TEXTURE_2D); 26478+ 26479+ // gBuffer[1-gCurrentFBOIndex] --> gWarper1 --> gBuffer[gCurrentFBOIndex] 26480+ gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]); 26481+ gWarper1.Clear(0.0, 0.0, 0.0, 1.0); 26482+ gWarper1.SetViewportMatrix(1, 1, 1, 1); 26483+ gWarper1.SetScalingMatrix(1.0f, 1.0f); 26484+ gWarper1.SetInputTextureName(gBuffer[1 - gCurrentFBOIndex].GetTextureName()); 26485+ gWarper1.SetInputTextureType(GL_TEXTURE_2D); 26486+ 26487+ // gBufferInput[HR] --> gWarper2 --> gBuffer[gCurrentFBOIndex] 26488+ gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]); 26489+ gWarper2.Clear(0.0, 0.0, 0.0, 1.0); 26490+ gWarper2.SetViewportMatrix(gPreviewImageWidth[HR], 26491+ gPreviewImageHeight[HR], gBuffer[gCurrentFBOIndex].GetWidth(), 26492+ gBuffer[gCurrentFBOIndex].GetHeight()); 26493+ gWarper2.SetScalingMatrix(1.0f, 1.0f); 26494+ gWarper2.SetInputTextureName(gBufferInput[HR].GetTextureName()); 26495+ gWarper2.SetInputTextureType(GL_TEXTURE_2D); 26496+ 26497+ gPreview.SetupGraphics(width, height); 26498+ gPreview.Clear(0.0, 0.0, 0.0, 1.0); 26499+ gPreview.SetViewportMatrix(1, 1, 1, 1); 26500+ 26501+ // Scale the previewFBO so that the viewfinder window fills the layout height 26502+ // while maintaining the image aspect ratio 26503+ gPreview.SetScalingMatrix(gUILayoutScalingX, -1.0f * gUILayoutScalingY); 26504+ gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName()); 26505+ gPreview.SetInputTextureType(GL_TEXTURE_2D); 26506+} 26507+ 26508+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_preprocess( 26509+ JNIEnv * env, jobject obj, jfloatArray stMatrix) 26510+{ 26511+ jfloat *stmat = env->GetFloatArrayElements(stMatrix, 0); 26512+ 26513+ gSurfTexRenderer[LR].SetSTMatrix((float*) stmat); 26514+ gSurfTexRenderer[HR].SetSTMatrix((float*) stmat); 26515+ 26516+ env->ReleaseFloatArrayElements(stMatrix, stmat, 0); 26517+ 26518+ gSurfTexRenderer[LR].DrawTexture(g_dAffinetransIdentGL); 26519+ gSurfTexRenderer[HR].DrawTexture(g_dAffinetransIdentGL); 26520+} 26521+ 26522+#ifndef now_ms 26523+#include <time.h> 26524+static double 26525+now_ms(void) 26526+{ 26527+ //struct timespec res; 26528+ struct timeval res; 26529+ //clock_gettime(CLOCK_REALTIME, &res); 26530+ gettimeofday(&res, NULL); 26531+ return 1000.0*res.tv_sec + (double)res.tv_usec/1e3; 26532+} 26533+#endif 26534+ 26535+ 26536+ 26537+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_transferGPUtoCPU( 26538+ JNIEnv * env, jobject obj) 26539+{ 26540+ double t0, t1, time_c; 26541+ 26542+ gYVURenderer[LR].DrawTexture(); 26543+ gYVURenderer[HR].DrawTexture(); 26544+ 26545+ sem_wait(&gPreviewImage_semaphore); 26546+ // Bind to the input LR FBO and read the Low-Res data from there... 26547+ glBindFramebuffer(GL_FRAMEBUFFER, gBufferInputYVU[LR].GetFrameBufferName()); 26548+ t0 = now_ms(); 26549+ glReadPixels(0, 26550+ 0, 26551+ gBufferInput[LR].GetWidth(), 26552+ gBufferInput[LR].GetHeight(), 26553+ GL_RGBA, 26554+ GL_UNSIGNED_BYTE, 26555+ gPreviewImage[LR]); 26556+ 26557+ checkGlError("glReadPixels LR"); 26558+ 26559+ // Bind to the input HR FBO and read the high-res data from there... 26560+ glBindFramebuffer(GL_FRAMEBUFFER, gBufferInputYVU[HR].GetFrameBufferName()); 26561+ t0 = now_ms(); 26562+ glReadPixels(0, 26563+ 0, 26564+ gBufferInput[HR].GetWidth(), 26565+ gBufferInput[HR].GetHeight(), 26566+ GL_RGBA, 26567+ GL_UNSIGNED_BYTE, 26568+ gPreviewImage[HR]); 26569+ 26570+ checkGlError("glReadPixels HR"); 26571+ 26572+ sem_post(&gPreviewImage_semaphore); 26573+} 26574+ 26575+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_step( 26576+ JNIEnv * env, jobject obj) 26577+{ 26578+ if(!gWarpImage) // ViewFinder 26579+ { 26580+ gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]); 26581+ gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName()); 26582+ 26583+ gWarper2.DrawTexture(g_dTranslationToFBOCenterGL); 26584+ 26585+ if (gIsLandscapeOrientation) { 26586+ gPreview.DrawTexture(g_dAffinetransIdentGL); 26587+ } else { 26588+ gPreview.DrawTexture(g_dAffinetransRotation90GL); 26589+ } 26590+ } 26591+ else 26592+ { 26593+ gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]); 26594+ // Clear the destination so that we can paint on it afresh 26595+ gWarper1.Clear(0.0, 0.0, 0.0, 1.0); 26596+ gWarper1.SetInputTextureName( 26597+ gBuffer[1 - gCurrentFBOIndex].GetTextureName()); 26598+ gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]); 26599+ gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName()); 26600+ 26601+ gWarper1.DrawTexture(g_dAffinetransGL); 26602+ gWarper2.DrawTexture(g_dTranslationToFBOCenterGL); 26603+ gPreview.DrawTexture(g_dAffinetransPanGL); 26604+ 26605+ gCurrentFBOIndex = 1 - gCurrentFBOIndex; 26606+ } 26607+} 26608+ 26609+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_setWarping( 26610+ JNIEnv * env, jobject obj, jboolean flag) 26611+{ 26612+ // TODO: Review this logic 26613+ if(gWarpImage != (bool) flag) //switching from viewfinder to capture or vice-versa 26614+ { 26615+ // Clear gBuffer[0] 26616+ gWarper1.SetupGraphics(&gBuffer[0]); 26617+ gWarper1.Clear(0.0, 0.0, 0.0, 1.0); 26618+ // Clear gBuffer[1] 26619+ gWarper1.SetupGraphics(&gBuffer[1]); 26620+ gWarper1.Clear(0.0, 0.0, 0.0, 1.0); 26621+ // Clear the screen to black. 26622+ gPreview.Clear(0.0, 0.0, 0.0, 1.0); 26623+ 26624+ gLastTx = 0.0f; 26625+ gPanOffset = 0.0f; 26626+ gPanViewfinder = true; 26627+ 26628+ db_Identity3x3(gThisH1t); 26629+ db_Identity3x3(gLastH1t); 26630+ } 26631+ 26632+ gWarpImage = (bool)flag; 26633+} 26634+ 26635+ 26636+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_ready( 26637+ JNIEnv * env, jobject obj) 26638+{ 26639+ for(int i=0; i<16; i++) 26640+ { 26641+ g_dAffinetransGL[i] = g_dAffinetrans[i]; 26642+ g_dAffinetransPanGL[i] = g_dAffinetransPan[i]; 26643+ g_dTranslationToFBOCenterGL[i] = g_dTranslationToFBOCenter[i]; 26644+ } 26645+} 26646diff --git a/benchmark/mosaic_renderer_jni.h b/benchmark/mosaic_renderer_jni.h 26647new file mode 100644 26648index 00000000..f9b85df8 26649--- /dev/null 26650+++ b/benchmark/mosaic_renderer_jni.h 26651@@ -0,0 +1,35 @@ 26652+#pragma once 26653+#include <semaphore.h> 26654+ 26655+// The Preview FBO dimensions are determined from the high-res 26656+// frame dimensions (gPreviewImageWidth, gPreviewImageHeight) 26657+// using the scale factors below. 26658+const int PREVIEW_FBO_WIDTH_SCALE = 2; 26659+const int PREVIEW_FBO_HEIGHT_SCALE = 1; 26660+ 26661+// The factor below determines the (horizontal) speed at which the viewfinder 26662+// will pan across the UI during capture. A value of 0.0 will keep the viewfinder 26663+// static in the center of the screen and 1.0f will make it pan at the 26664+// same speed as the device. 26665+const float VIEWFINDER_PAN_FACTOR_HORZ = 0.3f; 26666+ 26667+// What fraction of the screen viewport width has been allocated to show the 26668+// arrows on the direction of motion side. 26669+const float VIEWPORT_BORDER_FACTOR_HORZ = 0.1f; 26670+ 26671+const int LR = 0; // Low-resolution mode 26672+const int HR = 1; // High-resolution mode 26673+const int NR = 2; // Number of resolution modes 26674+ 26675+const int H2L_FACTOR = 4; // Can be 2 26676+ 26677+extern "C" void AllocateTextureMemory(int widthHR, int heightHR, 26678+ int widthLR, int heightLR); 26679+extern "C" void FreeTextureMemory(); 26680+extern "C" void UpdateWarpTransformation(float *trs); 26681+ 26682+extern unsigned char* gPreviewImage[NR]; 26683+extern int gPreviewImageWidth[NR]; 26684+extern int gPreviewImageHeight[NR]; 26685+ 26686+extern sem_t gPreviewImage_semaphore; 26687