├── .gitignore ├── LICENSE ├── README.md ├── figures ├── abund-nfindr-1.png ├── endmmbrs-nfindr.png ├── sampleSlice.png ├── targets_spectra.png └── truecolor.png ├── functions ├── README.md ├── fnnls.m ├── hyperAce.m ├── hyperAmsd.m ├── hyperAtgp.m ├── hyperCem.m ├── hyperConvert2Colormap.m ├── hyperConvert2d.m ├── hyperConvert3d.m ├── hyperConvexHullRemoval.m ├── hyperCorr.m ├── hyperCov.m ├── hyperDemo.m ├── hyperDemo_ASD_reader.m ├── hyperDemo_RIT_data.m ├── hyperDemo_detectors.m ├── hyperDemo_mams_RIT_data.m ├── hyperDestreak.m ├── hyperFcls.m ├── hyperFclsMatlab.m ├── hyperFileFind.m ├── hyperGetEnviSignature.m ├── hyperGetHymapWavelengthsNm.m ├── hyperGlrt.m ├── hyperHfcVd.m ├── hyperHud.m ├── hyperIcaComponentScores.m ├── hyperIcaEea.m ├── hyperImagesc.m ├── hyperImshow.m ├── hyperMatchedFilter.m ├── hyperMax2d.m ├── hyperMnf.m ├── hyperNapc.m ├── hyperNnls.m ├── hyperNormXCorr.m ├── hyperNormalize.m ├── hyperOrthorectify.m ├── hyperOsp.m ├── hyperPct.m ├── hyperPlmf.m ├── hyperPpi.m ├── hyperReadAsd.m ├── hyperReadAvirisRfl.m ├── hyperReadAvirisSpc.m ├── hyperReadSpecpr.m ├── hyperResample.m ├── hyperRmf.m ├── hyperRoc.m ├── hyperRxDetector.m ├── hyperSam.m ├── hyperSaveFigure.m ├── hyperSid.m ├── hyperSignedAce.m ├── hyperUcls.m ├── hyperVca.m └── hyperWhiten.m └── newFunctions ├── README.md ├── hyperAmee.m ├── hyperAvmax.m ├── hyperDemo2.m ├── hyperNfindr.m ├── hyperRnfindr.m └── hyperTruecolor.m /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .DS_Store 3 | *.sublime-workspace 4 | *.sublime-project 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### HyperSpectral Toolbox ### 2 | 3 | For better viewing, visit 4 | 5 | Originally created by [Isaac Gerg](http://www.gergltd.com/home/) and maintained by him [here](https://github.com/isaacgerg/matlabHyperspectralToolbox). 6 | 7 | # Note # 8 | 9 | **This repository is no longer being maintained or updated.** 10 | 11 | Isaac (the original creator of 99% of this work) has [his own GitHub repository](https://github.com/isaacgerg/matlabHyperspectralToolbox) with this work and intends to actively maintain / update it there. 12 | 13 | _Please use that repository and see his BibTeX citation for correctly referencing the software in your research._ 14 | 15 | **Dependencies** 16 | FastICA -- [from Aalto University](http://research.ics.aalto.fi/ica/fastica/code/dlcode.shtml)) 17 | 18 | ## Setup ## 19 | 20 | In the terminal type: 21 | 22 | cd ~/path-to-directory 23 | git clone https://github.com/davidkun/HyperSpectralToolbox.git 24 | git clone https://github.com/davidkun/FastICA.git 25 | 26 | Open Matlab. The default directory should contain a file `startup.m`. If not, create it: 27 | 28 | % in Matlab command window 29 | uPath = userpath; 30 | cd(uPath(1:end-1)); % removes trailing colon 31 | edit startup.m % may ask if you'd like to create it; click Yes 32 | 33 | Add the following code to it (make sure to modify `path-to-directory` so it matches the actual path): 34 | 35 | addtopath('~/path-to-directory/FastICA', ... 36 | '~/path-to-directory/HyperSpectralToolbox/functions', ... 37 | '~/path-to-directory/HyperSpectralToolbox/newFunctions'); 38 | 39 | You're ready to go now! Check out the demo files `hyperDemo.m` in `functions/` and `hyperDemo2.m` in `newFunctions/` to learn how to use the toolbox, or see the examples further down this page. 40 | 41 | *** 42 | [Back to top](https://github.com/davidkun/HyperSpectralToolbox#welcome-to-my-project) 43 | *** 44 | 45 | ## Description ## 46 | 47 | The open source Matlab Hyperspectral Toolbox is a Matlab toolbox containing various hyperspectral exploitation algorithms. The toolbox is meant to be a concise repository of current state-of-the-art exploitation algorithms for learning and research purposes. The toolbox includes functions for: 48 | 49 | * **Target detection** 50 | * Constrained Energy Minimization (CEM) 51 | * Orthogonal Subspace Projection (OSP) 52 | * Generalized Likelihood Ratio Test (GLRT) 53 | * Adaptive Cosine/Coherent Estimator (ACE) 54 | * Adaptive Matched Subspace Detector (AMSD) 55 | * **Endmember Finders** 56 | * Automatic Target Generation Procedure (ATGP) 57 | * Independent component analysis - endmember extraction algorithm (ICA-EEA) 58 | * **Material abundance map (MAM) generation** 59 | * **Spectral Comparison** 60 | * Spectral angle mapper (SAM) 61 | * Spectral information divergence (SID) 62 | * Normalize cross correlation 63 | * **Anomaly Detectors** 64 | * Reed-Xiaoli Detector (RX) 65 | * **Least Square Solvers** (for abundance map estimation) 66 | * Fully-constrained least squares (FCLS) 67 | * Non negative least squares (NNLS) 68 | * **Material Count Estimation** 69 | * HFC virtual dimensionality (VD) for material count estimate 70 | * **Automated processing** 71 | * **Change detection** 72 | * **Visualization** 73 | * **Reading / writing files** (.rfl, .asd, ect) 74 | 75 | *** 76 | [Back to top](https://github.com/davidkun/HyperSpectralToolbox#welcome-to-my-project) 77 | *** 78 | 79 | ## Examples ## 80 | 81 | Download the Cuprite, Nevada hyperspectral image (HSI) from [here](http://aviris.jpl.nasa.gov/data/free_data.html). This will contain reflectance data and a .spc file with the spectral bands. The following samples of code are from `hyperDemo2.m`. 82 | 83 | Show a 'slice' of the HSI: 84 | 85 | slice = hyperReadAvirisRfl(rflFile, [1 512], [1 614], [bndnum bndnum]); 86 | figure; imagesc(slice); axis image; colormap(gray); 87 | 88 | ![Figure 1: 1997 AVIRIS flight over Cuprite, NV](https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/master/figures/sampleSlice.png) 89 | _Figure 1: 1997 AVIRIS flight over Cuprite, NV_ 90 | 91 | View an enhanced truecolor composite of the HSI: 92 | 93 | tColor = hyperTruecolor(rflFile, 512, 614, 224, rgbBands, 'stretchlim'); 94 | figure; imagesc(tColor); axis image 95 | 96 | ![Figure 2: Truecolor composite from RGB bands](https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/master/figures/truecolor.png) 97 | _Figure 2: Truecolor composite from RGB bands_ 98 | 99 | Plot the spectral signatures of 20 random pixels in order to determine which bands are greatly affected by water absorption and/or have a low signal-to-noise ratio (SNR): 100 | 101 | ![Figure 3: Pre-processing: removal of poor spectral bands from original HSI](https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/master/figures/targets_spectra.png) 102 | _Figure 3: Pre-processing: removal of poor spectral bands from original HSI_ 103 | 104 | Using the resampled HSI cube, perform an endmember extraction algorithm, for example, the N-FINDR algorithm: 105 | 106 | Unfindr = hyperNfindr(M2d, q); 107 | figure; plot(lambdasNm, Unfindr, '.'); grid on; 108 | 109 | ![Figure 4: Endmember signatures estimated by PPI](https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/master/figures/endmmbrs-nfindr.png) 110 | _Figure 4: Endmember signatures estimated by PPI_ 111 | 112 | Generate abundance maps using the non-negative constrained least squares method for each extracted endmember signature, for example: 113 | 114 | abundanceMaps = hyperNnls(M2d, Uppi); 115 | abundanceMaps = hyperConvert3d(abundanceMaps, h, w, q); 116 | figure; imagesc(abundanceMaps(:,:,1)); colorbar; axis image; 117 | 118 | ![Figure 5: Abundance map from first N-FINDR-recovered endmember](https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/master/figures/abund-nfindr-1.png) 119 | _Figure 5: Abundance map from first N-FINDR-recovered endmember_ 120 | 121 | These are just a few features of the Hyperspectral Toolbox. 122 | 123 | *** 124 | [Back to top](https://github.com/davidkun/HyperSpectralToolbox#welcome-to-my-project) 125 | *** 126 | 127 | ### Algorithms to be added (requested by Dr. Gerg): ### 128 | 129 | (Joint) Affine Matched filter 130 | Generalization of matched filter which includes signature statistics 131 | RAF-SAM, an improvement to SAM from: Improving the Classification Precision of Spectral Angle Mapper 132 | ELM for radiance to reflectance conversion - http://www.cis.rit.edu/files/197_SPIE_2005_Grimm.pdf 133 | Covariance matrix inversion methods (e.g. Dominant Mode Rejection) 134 | Quadratic Detector 135 | SMACC - http://proceedings.spiedigitallibrary.org/proceeding.aspx?articleid=844250 136 | ~~AMEE - http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1046852~~ 137 | ~~N-FINDR - http://proceedings.spiedigitallibrary.org/proceeding.aspx?articleid=994814~~ 138 | Fast PPI - http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1576691 139 | ~~Joshua Broaderwater's hybrid detectors (HUD, etc)~~ 140 | Variations on ACE - e.g. adaptive covariance estimated ACE, etc 141 | 142 | 143 | *** 144 | [Back to top](https://github.com/davidkun/HyperSpectralToolbox#welcome-to-my-project) 145 | *** 146 | -------------------------------------------------------------------------------- /figures/abund-nfindr-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/figures/abund-nfindr-1.png -------------------------------------------------------------------------------- /figures/endmmbrs-nfindr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/figures/endmmbrs-nfindr.png -------------------------------------------------------------------------------- /figures/sampleSlice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/figures/sampleSlice.png -------------------------------------------------------------------------------- /figures/targets_spectra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/figures/targets_spectra.png -------------------------------------------------------------------------------- /figures/truecolor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/figures/truecolor.png -------------------------------------------------------------------------------- /functions/README.md: -------------------------------------------------------------------------------- 1 | Matlab Hyperspectral Toolbox 2 | 3 | Copyright 2008-2012 Isaac Gerg 4 | 5 | ------------------------------------------------------------------------- 6 | 7 | A Note on Notation 8 | 9 | Hyperspectral data is often expressed many ways to better describe the 10 | mathematical handling of the data; mainly as a vector of pixels when 11 | referring to the data in a space or a matrix of pixels when referring to 12 | data as an image. 13 | 14 | For consistency, a common notation is defined to 15 | differentiate these concepts clearly. Hyperspectral data examined like an 16 | image will be defined as a matrix Mm x n x p of dimension m x n x p where m 17 | is defined as the number of rows in the image, n is defined as the 18 | number of columns in the image, and p is defined as the number of bands 19 | in the image. Therefore, a single element of such an image will be 20 | accessed using Mi,j,k and a single pixel of an image will be accessed 21 | using Mi,j,: Hyperspectral data formed as a vector of vectors 22 | (i.e. 2D matrix) is defined as M(mn) x p of dimension (mn) x p 23 | 24 | A single element is accessed using Mi,j and a single pixel is 25 | accessed using M:,j . Notice the multi-element notation is consistent 26 | with MatlabTM this is intentional. 27 | 28 | The list below provides a summary of the notation convention used 29 | throughout this code. 30 | 31 | M Data matrix. Defined as an image of spectral signatures or vectors: 32 | Mmxnxp. Or, defined as a long vector of spectral signatures: 33 | M(mn) x p 34 | 35 | N The total number of pixels. For example N = m x n. 36 | 37 | m Number of rows in the image. 38 | 39 | n Number of columns in the image. 40 | 41 | p Number of bands. 42 | 43 | q Number of classes / endmembers. 44 | 45 | U Matrix of endmembers. Each column of the matrix represents an 46 | endmember vector. 47 | 48 | b Observation vector; a single pixel. 49 | 50 | x Weight vector. A matrix of weight vectors forms an abundance 51 | map. 52 | 53 | ------------------------------------------------------------------------- 54 | Dependencies 55 | FastICA - http://www.cis.hut.fi/projects/ica/fastica/code/dlcode.shtml 56 | 57 | ------------------------------------------------------------------------- 58 | Functions 59 | 60 | Reading/Writing Data Files 61 | 62 | - hyperReadAvirisRfl - Reads AVIRIS .rfl files 63 | - hyperReadAvirisSpc - Read AVIRIS .spc files 64 | - hyperReadAsd - Reads ASD Fieldspec files. (.asd, .000, etc) 65 | 66 | Data Formatting 67 | 68 | - hyperConvert2D - Converts data from a 3D HSI data cube to a 2D matrix 69 | - hyperConvert3D - Converts data from a 2D matrix to a 3D HSI data cube 70 | - hyperNormalize - Normalizes data to be in range of [0,1] 71 | - hyperConvert2Jet - Converts a 2D matrix to jet colormap values 72 | - hyperResample - Resamples hyperspectral data to new wavelength set 73 | 74 | Unmixing 75 | 76 | - hyperAtgp - ATGP algorithm 77 | - hyperIcaEea - ICA-Endmember Extraction Algorithm 78 | - hyperIcaComponentScores - Computes ICA component scores for relevance 79 | - hyperVca - Vertex Component Analysis 80 | - hyperPPI - Pixel Purity Index 81 | 82 | Target Detection 83 | 84 | - hyperACE - Adaptive cosine/coherent estimator 85 | - hyperGLRT - Generalized liklihood ratio test 86 | - hyperHUD - Hybrid instructured detector 87 | - hyperAMSD - Adaptive matched subspace detector 88 | - hyperMatchedFilter - Matched filter 89 | - hyperOsp - Orthogonal subspace projection 90 | - hyperCem - Constrained energy minimization 91 | - hyperPlmf - PCA local matched filter 92 | - hyperRmf - Regularized match filter 93 | 94 | Material Count Estimation 95 | 96 | - hyperHfcVd - Computes virtual dimensionality (VD) using HFC method 97 | 98 | Data Conditioning 99 | 100 | - hyperPct - Pricipal component transform 101 | - hyperMnf - Minimum noise fraction 102 | - hyperDestreak - Destreaking algorithm 103 | 104 | Abundance Map Generation 105 | 106 | - hyperUcls - Unconstrained least squares 107 | - hyperNnls - Non-negative least squares 108 | - hyperFcls - Fully constrains least squares 109 | 110 | Spectral Measuring 111 | 112 | - hyperSam - Spectral Angle Mapper 113 | - hyperSid - Spectral Information Divergence 114 | - hyperNormXCorr - Normalized Cross Correlation 115 | 116 | Miscellaneous 117 | 118 | - hyperMax2d - Finds the max value and corresonding position in a matrx 119 | 120 | Sensor Specific 121 | 122 | - hyperGetHymapWavelengthsNm - Returns list of Hymap wavelengths 123 | 124 | Statistics 125 | 126 | - hyperCov - Sample covariance matrix estimator 127 | - hyperCorr - Sample autocorrelation matrix estimator 128 | 129 | Demos 130 | 131 | - hyperDemo - General toolbox usage 132 | - hyperDemo_detectors - Target detection algorithms 133 | - hyperDemo_RIT_data - RIT target detection blind test 134 | - hyperDemo_ASD_reader - Reads ASD Fieldspec files 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /functions/fnnls.m: -------------------------------------------------------------------------------- 1 | function [x,w] = fnnls(XtX,Xty,tol) 2 | %FNNLS Non-negative least-squares. 3 | % 4 | % Adapted from NNLS of Mathworks, Inc. 5 | % 6 | % x = fnnls(XtX,Xty) returns the vector X that solves x = pinv(XtX)*Xty 7 | % in a least squares sense, subject to x >= 0. 8 | % Differently stated it solves the problem min ||y - Xx|| if 9 | % XtX = X'*X and Xty = X'*y. 10 | % 11 | % A default tolerance of TOL = MAX(SIZE(XtX)) * NORM(XtX,1) * EPS 12 | % is used for deciding when elements of x are less than zero. 13 | % This can be overridden with x = fnnls(XtX,Xty,TOL). 14 | % 15 | % [x,w] = fnnls(XtX,Xty) also returns dual vector w where 16 | % w(i) < 0 where x(i) = 0 and w(i) = 0 where x(i) > 0. 17 | % 18 | % See also NNLS and FNNLSb 19 | 20 | % L. Shure 5-8-87 21 | % Revised, 12-15-88,8-31-89 LS. 22 | % (Partly) Copyright (c) 1984-94 by The MathWorks, Inc. 23 | 24 | % Modified by R. Bro 5-7-96 according to 25 | % Bro R., de Jong S., Journal of Chemometrics, 1997, 11, 393-401 26 | % Corresponds to the FNNLSa algorithm in the paper 27 | % 28 | % 29 | % Rasmus bro 30 | % Chemometrics Group, Food Technology 31 | % Dept. Dairy and Food Science 32 | % Royal Vet. & Agricultural 33 | % DK-1958 Frederiksberg C 34 | % Denmark 35 | % rb@kvl.dk 36 | % http://newton.foodsci.kvl.dk/rasmus.html 37 | 38 | 39 | % Reference: 40 | % Lawson and Hanson, "Solving Least Squares Problems", Prentice-Hall, 1974. 41 | 42 | % Copyright (c) 1999, Rasmus Bro 43 | % All rights reserved. 44 | % 45 | % Redistribution and use in source and binary forms, with or without 46 | % modification, are permitted provided that the following conditions are 47 | % met: 48 | % 49 | % * Redistributions of source code must retain the above copyright 50 | % notice, this list of conditions and the following disclaimer. 51 | % * Redistributions in binary form must reproduce the above copyright 52 | % notice, this list of conditions and the following disclaimer in 53 | % the documentation and/or other materials provided with the distribution 54 | % 55 | % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 56 | % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 57 | % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 58 | % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 59 | % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 60 | % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 61 | % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 62 | % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 63 | % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 64 | % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 65 | % POSSIBILITY OF SUCH DAMAGE. 66 | 67 | % initialize variables 68 | if nargin < 3 69 | tol = 10*eps*norm(XtX,1)*max(size(XtX)); 70 | end 71 | [m,n] = size(XtX); 72 | P = zeros(1,n); 73 | Z = 1:n; 74 | x = P'; 75 | ZZ=Z; 76 | w = Xty-XtX*x; 77 | 78 | % set up iteration criterion 79 | iter = 0; 80 | itmax = 30*n; 81 | 82 | % outer loop to put variables into set to hold positive coefficients 83 | while any(Z) & any(w(ZZ) > tol) 84 | [wt,t] = max(w(ZZ)); 85 | t = ZZ(t); 86 | P(1,t) = t; 87 | Z(t) = 0; 88 | PP = find(P); 89 | ZZ = find(Z); 90 | nzz = size(ZZ); 91 | z(PP')=(Xty(PP)'/XtX(PP,PP)'); 92 | z(ZZ) = zeros(nzz(2),nzz(1))'; 93 | z=z(:); 94 | % inner loop to remove elements from the positive set which no longer belong 95 | 96 | while any((z(PP) <= tol)) & iter < itmax 97 | 98 | iter = iter + 1; 99 | QQ = find((z <= tol) & P'); 100 | alpha = min(x(QQ)./(x(QQ) - z(QQ))); 101 | x = x + alpha*(z - x); 102 | ij = find(abs(x) < tol & P' ~= 0); 103 | Z(ij)=ij'; 104 | P(ij)=zeros(1,max(size(ij))); 105 | PP = find(P); 106 | ZZ = find(Z); 107 | nzz = size(ZZ); 108 | z(PP)=(Xty(PP)'/XtX(PP,PP)'); 109 | z(ZZ) = zeros(nzz(2),nzz(1)); 110 | z=z(:); 111 | end 112 | x = z; 113 | w = Xty-XtX*x; 114 | end 115 | 116 | -------------------------------------------------------------------------------- /functions/hyperAce.m: -------------------------------------------------------------------------------- 1 | function [results] = hyperAce(M, S) 2 | % HYPERACE Performs the adaptive cosin/coherent estimator algorithm 3 | % Performs the adaptive cosin/coherent estimator algorithm for target 4 | % detection. 5 | % 6 | % Usage 7 | % [results] = hyperAce(M, S) 8 | % Inputs 9 | % M - 2d matrix of HSI data (p x N) 10 | % S - 2d matrix of target endmembers (p x q) 11 | % Outputs 12 | % results - vector of detector output (N x 1) 13 | % 14 | % References 15 | % X Jin, S Paswater, H Cline. "A Comparative Study of Target Detection 16 | % Algorithms for Hyperspectral Imagery." SPIE Algorithms and Technologies 17 | % for Multispectral, Hyperspectral, and Ultraspectral Imagery XV. Vol 18 | % 7334. 2009. 19 | 20 | 21 | [p, N] = size(M); 22 | % Remove mean from data 23 | u = mean(M.').'; 24 | M = M - repmat(u, 1, N); 25 | S = S - repmat(u, 1, size(S,2)); 26 | 27 | R_hat = hyperCov(M); 28 | G = inv(R_hat); 29 | 30 | results = zeros(1, N); 31 | % From Broadwater's paper 32 | %tmp = G*S*inv(S.'*G*S)*S.'*G; 33 | tmp = (S.'*G*S); 34 | for k=1:N 35 | x = M(:,k); 36 | % From Broadwater's paper 37 | %results(k) = (x.'*tmp*x) / (x.'*G*x); 38 | results(k) = (S.'*G*x)^2 / (tmp*(x.'*G*x)); 39 | end 40 | -------------------------------------------------------------------------------- /functions/hyperAmsd.m: -------------------------------------------------------------------------------- 1 | function [results] = hyperAmsd(M, B, target) 2 | % HYPERAMSD Adaptive matched subspace detector (AMSD) algorithm 3 | % Performs the adaptive matched subspace detector (AMSD) algorithm for 4 | % target detection 5 | % 6 | % Usage 7 | % [results] = hyperAmsd(M, U, target) 8 | % Inputs 9 | % M - 2d matrix of HSI data (p x N) 10 | % B - 2d matrix of background endmebers (p x q) 11 | % target - target of interest (p x 1) 12 | % Outputs 13 | % results - vector of detector output (N x 1) 14 | % 15 | % References 16 | % Joshua Broadwater, Reuven Meth, Rama Chellappa. "A Hybrid Algorithms 17 | % for Subpixel Detection in Hyperspectral Imagery." IGARSS 004. Vol 3. 18 | % September 2004. 19 | 20 | [p, N] = size(M); 21 | I = eye(p); 22 | 23 | E = [B target]; 24 | P_B = I - (B * pinv(B)); 25 | P_Z = I - (E * pinv(E)); 26 | 27 | results = zeros(N, 1); 28 | tmp = P_B - P_Z; 29 | for k=1:N 30 | x = M(:,k); 31 | % Equation 16 32 | results(k) = (x.'*tmp*x) / (x.'*P_Z*x); 33 | end -------------------------------------------------------------------------------- /functions/hyperAtgp.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/functions/hyperAtgp.m -------------------------------------------------------------------------------- /functions/hyperCem.m: -------------------------------------------------------------------------------- 1 | function [results] = hyperCem(M, target) 2 | % HYPERCEM Performs constrained energy minimization (CEM) algorithm 3 | % Performs the constrained energy minimization algorithm for target 4 | % detection. 5 | % 6 | % Usage 7 | % [results] = hyperCem(M, target) 8 | % Inputs 9 | % M - 2d matrix of HSI data (p x N) 10 | % target - target of interest (p x 1) 11 | % Outputs 12 | % results - vector of detector output (N x 1) 13 | % 14 | % References 15 | % Qian Du, Hsuan Ren, and Chein-I Cheng. A Comparative Study of 16 | % Orthogonal Subspace Projection and Constrained Energy Minimization. 17 | % IEEE TGRS. Volume 41. Number 6. June 2003. 18 | 19 | % Check dimensions 20 | if ndims(M) ~= 2 21 | error('Input image must be p x N.'); 22 | end 23 | 24 | p = size(M,1); 25 | 26 | if ~isequal(size(target), [p,1]) 27 | error('Input target must be p x 1.'); 28 | end 29 | 30 | % CEM uses the correlation matrix, NOT the covariance matrix. Therefore, 31 | % don't remove the mean from the data. 32 | R_hat = hyperCorr(M); 33 | 34 | % Equation 6 : w = inv( target'*inv(R)*target ) * inv(R)*target 35 | invRtarget = R_hat\target; % inv(R)*target 36 | weights = ( target'*invRtarget ) \ invRtarget; 37 | 38 | results = weights'*M; 39 | -------------------------------------------------------------------------------- /functions/hyperConvert2Colormap.m: -------------------------------------------------------------------------------- 1 | function [imgOut] = hyperConvert2Colormap(imgIn, cmap) 2 | %HYPERCONVERT2COLORMap Converts a matrix to a specified colormap 3 | % Converts a matrix into the specified colormap values. Useful 4 | % for writing float data to a color image (e.g. .png) file. 5 | % 6 | % Usage 7 | % [imgOut] = hyperConvert2Colormap(imgIn, cmap) 8 | % Inputs 9 | % imgIn - input matrix, must be 2D 10 | % cmap - (optional) Colormap to use. If not specified, jet is used. 11 | % Outputs 12 | % imgOut - 3D matrix containing corresponding jet colormap values 13 | 14 | if (ndims(imgIn) ~= 2) 15 | fprintf('Need a two dimensional image.'); 16 | return; 17 | end 18 | if (nargin == 1) 19 | tmpJet = jet; 20 | end 21 | tmpJet = cmap; 22 | s = size(tmpJet, 1); 23 | imgIn = hyperNormalize(imgIn); 24 | [h, w] = size(imgIn); 25 | imgOut = zeros(h, w, 3); 26 | for j=1:h 27 | for i=1:w 28 | v = tmpJet(round(imgIn(j, i)*(s-1))+1, :); 29 | imgOut(j, i, :) = v; 30 | end 31 | end -------------------------------------------------------------------------------- /functions/hyperConvert2d.m: -------------------------------------------------------------------------------- 1 | function [M] = hyperConvert2d(M) 2 | % HYPERCONVERT2D Converts an HSI cube to a 2D matrix 3 | % Converts a 3D HSI cube (m x n x p) to a 2D matrix of points (p X N) 4 | % where N = mn 5 | % 6 | % Usage 7 | % [M] = hyperConvert2d(M) 8 | % Inputs 9 | % M - 3D HSI cube (m x n x p) 10 | % Outputs 11 | % M - 2D data matrix (p x N) 12 | 13 | if (ndims(M)>3 || ndims(M)<2) 14 | error('Input image must be m x n x p or m x n'); 15 | end 16 | if (ndims(M) == 2) 17 | numBands = 1; 18 | [h, w] = size(M); 19 | else 20 | [h, w, numBands] = size(M); 21 | end 22 | 23 | M = reshape(M, w*h, numBands).'; 24 | 25 | return; -------------------------------------------------------------------------------- /functions/hyperConvert3d.m: -------------------------------------------------------------------------------- 1 | function [img] = hyperConvert3d(img, h, w, numBands) 2 | % HYPERCONVERT2D Converts an 2D matrix to a 3D data cube 3 | % Converts a 2D matrix (p x N) to a 3D data cube (m x n x p) 4 | % where N = m * n 5 | % 6 | % Usage 7 | % [M] = hyperConvert3d(M) 8 | % Inputs 9 | % M - 2D data matrix (p x N) 10 | % Outputs 11 | % M - 3D data cube (m x n x p) 12 | 13 | 14 | if (ndims(img) ~= 2) 15 | error('Input image must be p x N.'); 16 | end 17 | 18 | [numBands, N] = size(img); 19 | 20 | if (1 == N) 21 | img = reshape(img, h, w); 22 | else 23 | img = reshape(img.', h, w, numBands); 24 | end 25 | 26 | return; -------------------------------------------------------------------------------- /functions/hyperConvexHullRemoval.m: -------------------------------------------------------------------------------- 1 | function normalizedU = hyperConvexHullRemoval(U,wavelengths) 2 | %HYPERCONVEXHULLREMOVAL Performs spectral normalization via convex hull removal 3 | % 4 | % Usage 5 | % [ normalizedU ] = hyperConvexHullRemoval( U, wavelengths ) 6 | % 7 | % Inputs 8 | % U - 2D HSI data (p x q) 9 | % wavelengths - Wavelength of each band (p x 1) 10 | % 11 | % Outputs 12 | % normalizedU - Data with convex hull removed (p x q) 13 | % 14 | % Author 15 | % Luca Innocenti 16 | % 17 | % References 18 | % Clark, R.N. and T.L. Roush (1984) Reflectance Spectroscopy: Quantitative 19 | % Analysis Techniques for Remote Sensing Applications, J. Geophys. Res., 89, 20 | % 6329-6340. 21 | 22 | % Metadata and formatting 23 | wavelengths = wavelengths(:); 24 | p = length(wavelengths); 25 | q = size(U,2); 26 | U = U.'; 27 | 28 | U(:,1) = 0; 29 | U(:,420) = 0; 30 | 31 | normalizedU = zeros(q,420); 32 | 33 | % The algorithm 34 | for s = 1:q, 35 | rifl = U(s,:); 36 | k = convhull(wavelengths,rifl'); 37 | c = [rifl(k); wavelengths(k)']; 38 | d = sortrows(c',2); 39 | 40 | xs = d(:,2); 41 | ys = d(:,1); 42 | [xsp, idx] = unique(xs); 43 | ysp = ys(idx); 44 | rifl_i = interp1(xsp,ysp,wavelengths'); 45 | 46 | for t = 1:420, 47 | if rifl_i(t) ~= 0 48 | normalizedU(s,t) = rifl(t)/rifl_i(t); 49 | else 50 | normalizedU(s,t) = 1; 51 | end 52 | end 53 | end 54 | 55 | normalizedU = normalizedU.'; 56 | -------------------------------------------------------------------------------- /functions/hyperCorr.m: -------------------------------------------------------------------------------- 1 | function [R] = hyperCorr(M) 2 | % HYPERCORR Computes the sample autocorrelation matrix 3 | % hyperCorr compute the sample autocorrelation matrix of a 2D matrix. 4 | % 5 | % Usage 6 | % [R] = hyperCorr(M) 7 | % 8 | % Inputs 9 | % M - 2D matrix 10 | % Outputs 11 | % R - Sample autocorrelation matrix 12 | 13 | 14 | [p, N] = size(M); 15 | 16 | R = (M*M.')/N; 17 | -------------------------------------------------------------------------------- /functions/hyperCov.m: -------------------------------------------------------------------------------- 1 | function [C] = hyperCov(M) 2 | % HYPERCOV Computes the covariance matrix 3 | % hyperCorr compute the sample covariance matrix of a 2D matrix. 4 | % 5 | % Usage 6 | % [C] = hyperCorr(M) 7 | % 8 | % Inputs 9 | % M - 2D matrix 10 | % Outputs 11 | % C - Sample covariance matrix 12 | 13 | [p, N] = size(M); 14 | % Remove mean from data 15 | u = mean(M.').'; 16 | for k=1:N 17 | M(:,k) = M(:,k) - u; 18 | end 19 | 20 | C = (M*M.')/(N-1); 21 | -------------------------------------------------------------------------------- /functions/hyperDemo.m: -------------------------------------------------------------------------------- 1 | function hyperDemo 2 | % HYPERDEMO Demonstrates the hyperspectral toolbox 3 | clear; clc; dbstop if error; close all; 4 | %-------------------------------------------------------------------------- 5 | % Parameters 6 | % resultsDir = 'results\\'; 7 | % dataDir = 'data\\AVIRIS\\'; 8 | % fastIcaDir = 'FastICA_25\\'; 9 | resultsDir = '~/Downloads/data/results/'; 10 | dataDir = '~/Downloads/data'; 11 | %-------------------------------------------------------------------------- 12 | 13 | fprintf('Storing results in %s directory.\n', resultsDir); 14 | mkdir(resultsDir); 15 | % addpath(fastIcaDir); 16 | 17 | %% Read in an HSI image and display one band 18 | slice = hyperReadAvirisRfl(sprintf('%s/f970620t01p02_r03_sc02.a.rfl', dataDir), [1 100], [1 614], [132 132]); 19 | figure; imagesc(slice); axis image; colormap(gray); 20 | title('Band 132'); 21 | 22 | %% Read part of AVIRIS data file that we will further process 23 | M = hyperReadAvirisRfl(sprintf('%s/f970620t01p02_r03_sc02.a.rfl', dataDir), [1 100], [1 614], [1 224]); 24 | 25 | % Read AVIRIS .spc file 26 | lambdasNm = hyperReadAvirisSpc(sprintf('%s/f970620t01p02_r03.a.spc', dataDir)); 27 | figure; plot(lambdasNm, 1:length(lambdasNm)); title('Band Number Vs Wavelengths'); grid on; 28 | xlabel('Wavelength [nm]'); ylabel('Band Number'); 29 | 30 | %% NDVI - I believe this should ideally be done with radiance data and not 31 | % reflectance as we are doing here. 32 | nir = M(:,:,59); 33 | vis = M(:,:,27); 34 | ndvi = (nir - vis) ./ (nir + vis); 35 | figure; imagesc(ndvi); title('NDVI of Image'); axis image; colorbar; 36 | 37 | %% Isomorph 38 | [h, w, p] = size(M); 39 | M = hyperConvert2d(M); 40 | 41 | %% Resample AVIRIS image. 42 | desiredLambdasNm = 400:(2400-400)/(224-1):2400; 43 | M = hyperResample(M, lambdasNm, desiredLambdasNm); 44 | 45 | %% Remove low SNR bands. 46 | goodBands = [10:100 116:150 180:216]; 47 | M = M(goodBands, :); 48 | p = length(goodBands); 49 | 50 | %% Demonstrate difference spectral similarity measurements 51 | M = hyperConvert3d(M, h, w, p); 52 | target = squeeze(M(32, 257, :)); 53 | figure; plot(desiredLambdasNm(goodBands), target); grid on; 54 | title('Target Signature; Pixel (32, 257)'); 55 | 56 | %% Spectral Angle Mapper 57 | r = zeros(h, w); 58 | for i=1:h 59 | for j=1:w 60 | r(i, j) = abs(hyperSam(squeeze(M(i,j,:)), target)); 61 | end 62 | end 63 | figure; imagesc(r); title('Spectral Angle Mapper Result [radians]'); axis image; 64 | colorbar; 65 | 66 | %% Spectral Information Divergence 67 | r = zeros(h, w); 68 | for i=1:h 69 | for j=1:w 70 | r(i, j) = abs(hyperSid(squeeze(M(i,j,:)), target)); 71 | end 72 | end 73 | figure; imagesc(r); title('Spectral Information Divergence Result'); axis image; 74 | colorbar; 75 | 76 | %% Normalized Cross Correlation 77 | r = zeros(h, w); 78 | for i=1:h 79 | for j=1:w 80 | r(i, j) = abs((hyperNormXCorr(squeeze(M(i,j,:)), target))); 81 | end 82 | end 83 | figure; imagesc(r); title('Normalized Cross Correlation [0, 1]'); axis image; 84 | colorbar; 85 | 86 | %% PPI 87 | U = hyperPpi(hyperConvert2d(M), 50, 1000); 88 | figure; plot(U); title('PPI Recovered Endmembers'); grid on; 89 | 90 | 91 | %-------------------------------------------------------------------------- 92 | %% Perform a fully unsupervised exploitation chain using HFC, ATGP, and NNLS 93 | fprintf('Performing fully unsupervised exploitation using HFC, ATGP, and NNLS...\n'); 94 | M = hyperConvert2d(M); 95 | 96 | %% Estimate number of endmembers in image. 97 | q = hyperHfcVd(M, [10^-3]); 98 | %q = 50; 99 | 100 | %% PCA the data to remove noise 101 | %hyperWhiten(M) 102 | M = hyperPct(M, q); 103 | %p = q; 104 | 105 | %% Unmix AVIRIS image. 106 | %U = hyperVca(M, q); 107 | U = hyperAtgp(M, q); 108 | figure; plot(U); title('ATGP Recovered Endmembers'); grid on; 109 | 110 | %% Create abundance maps from unmixed endmembers. 111 | %abundanceMaps = hyperUcls(M, U); 112 | abundanceMaps = hyperNnls(M, U); 113 | %abundanceMaps = hyperFcls(M, U); 114 | % abundanceMaps = hyperNormXCorr(M, U); 115 | abundanceMaps = hyperConvert3d(abundanceMaps, h, w, q); 116 | 117 | for i=1:q 118 | tmp = hyperOrthorectify(abundanceMaps(:,:,i), 21399.6, 0.53418); 119 | figure; imagesc(tmp); colorbar; axis image; 120 | title(sprintf('Abundance Map %d', i)); 121 | hyperSaveFigure(gcf, sprintf('%s/chain1-mam-%d.png', resultsDir, i)); 122 | close(gcf); 123 | end 124 | fprintf('Done.\n'); 125 | %-------------------------------------------------------------------------- 126 | %% Perform another fully unsupervised exploitation chain using ICA 127 | fprintf('Performing fully unsupervised exploitation using ICA...'); 128 | [U, abundanceMaps] = hyperIcaEea(M, q); 129 | abundanceMaps = hyperConvert3d(abundanceMaps, h, w, q); 130 | for i=1:q 131 | tmp = hyperOrthorectify(abundanceMaps(:,:,i), 21399.6, 0.53418); 132 | figure; imagesc(tmp); colorbar; axis image; 133 | title(sprintf('Abundance Map %d', i)); 134 | hyperSaveFigure(gcf, sprintf('%s/chain2-mam-%d.png', resultsDir, i)); 135 | close(gcf); 136 | end 137 | fprintf('Done.\n'); 138 | 139 | 140 | -------------------------------------------------------------------------------- /functions/hyperDemo_ASD_reader.m: -------------------------------------------------------------------------------- 1 | clear; close all; clc; dbstop if error; 2 | 3 | %-------------------------------------------------------------------------- 4 | % This file demonstrates how to read data from an ASD Fieldspec 5 | % spectrometer. 6 | %-------------------------------------------------------------------------- 7 | % Parameters 8 | inputFilename1 = 'data\spectra\sample00000.asd'; 9 | inputFilename2 = 'data\spectra\gypsum.000'; 10 | %-------------------------------------------------------------------------- 11 | 12 | % Read from a file containing a reflectance signature 13 | [spectraReflectance, lambda] = hyperReadAsd(inputFilename2); 14 | % Display results 15 | figure; plot(lambda,spectraReflectance); grid on; 16 | title('Signature'); xlabel('Lambda [nm]'); ylabel('Reflectance [0,1]'); 17 | axis([350,2500,0,1]); 18 | 19 | % Read from a file containing digital number (DN) signature 20 | [measuredSpectra, lambda, referenceSpectra] = hyperReadAsd(inputFilename1); 21 | % Display results 22 | figure; plot(lambda,measuredSpectra); grid on; 23 | title('Measured Signature'); xlabel('Lambda [nm]'); 24 | ylabel('Digital Number'); 25 | figure; plot(lambda,referenceSpectra); grid on; 26 | title('Reference Signature'); xlabel('Lambda [nm]'); 27 | ylabel('Digital Number'); 28 | reflectance = measuredSpectra./referenceSpectra; 29 | figure; plot(lambda,reflectance); grid on; 30 | title('Dervied Reflectance'); xlabel('Lambda [nm]'); 31 | ylabel('Reflectance [0,1]'); 32 | axis([350,2500,0,1]); -------------------------------------------------------------------------------- /functions/hyperDemo_RIT_data.m: -------------------------------------------------------------------------------- 1 | clear; close all; clc; dbstop if error; 2 | 3 | %-------------------------------------------------------------------------- 4 | % This demo process the data from the RIT Target Detection Blind Test 5 | % contest which is located at: http://dirsapps.cis.rit.edu/blindtest/ 6 | % To use this file, you select a target detection algorithm and a target to 7 | % find and then the script runs the algorithm and outputs the data into the 8 | % outputDir. Two files are outputted, a .img and a .hdr. You upload these 9 | % files to the RIT website and they are automatically scored. 10 | %-------------------------------------------------------------------------- 11 | % Parameters 12 | inputFilename = 'data\blind_test\HyMap\blind_test_refl.img'; 13 | fasticaToolboxPath = '..\matlab_hyperspectral_toolbox\trunk\FastICA_25'; 14 | targetFilenames = {'data\blind_test\SPL\F5\F5_f.txt'}; 15 | outputDir = 'RIT Data Results'; 16 | % See switch statement for algorithm choices 17 | algorithm = 'ace' 18 | %algorithm = 'rmf-sum'; 19 | %algorithm = 'plmf' 20 | %algorithm = 'matchedFilter'; 21 | %algorithm = 'sam' 22 | %-------------------------------------------------------------------------- 23 | 24 | addpath('gmm'); 25 | 26 | addpath(fasticaToolboxPath); 27 | mkdir(outputDir); 28 | 29 | % Read in the data 30 | w = 280; 31 | h = 800; 32 | p = 126; 33 | M = multibandread(inputFilename, [w h p], 'int16', 0, 'bil', 'ieee-le')/1e4; 34 | lData = hyperGetHymapWavelengthsNm(); 35 | 36 | % Read in target signatures 37 | [sig1, lSig] = hyperGetEnviSignature(targetFilenames{1}); 38 | 39 | % Get signature from data for comparison 40 | fsig1 = squeeze(M(122,495,:)); 41 | %sig1 = fsig1; 42 | 43 | % Resample data to commone wavelength set 44 | desiredLambdas = lData; 45 | sig1 = squeeze(hyperResample(sig1, lSig, desiredLambdas)); 46 | figure; plot(sig1); grid on; title('Signature 1'); 47 | xlabel('Wavelength [nm]'); ylabel('Reflectance [%]'); 48 | hold on; plot(fsig1, '--'); 49 | legend('Recorded', 'From Image'); 50 | 51 | goodBands = 1:p; %[3:63 69:93 98:123]; 52 | 53 | % Image sharpening 54 | if 0 55 | ff = fspecial('unsharp',0.2); 56 | for k=1:p 57 | M(:,:,k) = imfilter(M(:,:,k),ff,'same'); 58 | M(:,:,k) = imfilter(M(:,:,k),ff,'same'); 59 | %M(:,:,k) = imfilter(M(:,:,k),ff,'same'); 60 | end 61 | end 62 | 63 | figure; imagesc(M(:,:,40)); axis image; colormap(gray); 64 | 65 | % Try to discover in-situ to lab kernel. 66 | % TODO 67 | % sub(:,1) = M(144,515,:); 68 | % sub(:,2) = M(144,516,:); 69 | % sub(:,3) = M(144,517,:); 70 | % sub(:,4) = M(145,515,:); 71 | % sub(:,5) = M(145,516,:); 72 | % sub(:,6) = M(145,517,:); 73 | % sub(:,7) = M(146,515,:); 74 | % sub(:,8) = M(146,516,:); 75 | % sub(:,9) = M(146,517,:); 76 | % 77 | % alpha = pinv(sub)*sig1; %alpha = alpha ./ sum(alpha(:)); 78 | % err = sub*alpha - sig1; err = err - mean(err); badBands = find(abs(err)>0.02); 79 | % goodBands = setxor(1:p,badBands); 80 | % figure; plot(err); hold on; plot(sig1,'.'); plot(fsig1,'.-'); hold off; grid on; 81 | % legend({'err','lab sig','in situ sig'}) 82 | % alpha = reshape(alpha,3,3); 83 | % figure; imagesc(alpha); 84 | % 85 | % for k=1:p 86 | % %M(:,:,p) = conv2(M(:,:,p),alpha,'same'); 87 | % end 88 | 89 | % Emperical dervied 90 | goodBands = [3 4 5 6 7 8 9 10 11 12 14 15 16 17 18 ... 91 | 19 20 22 23 24 26 28 29 31 32 33 34 35 36 37 ... 92 | 38 39 40 41 42 43 44 45 46 49 51 52 53 54 55 ... 93 | 56 57 58 59 60 61 62 66 69 70 71 72 86 87 88 ... 94 | 89 90 91 92 93 96 97 98 99 100 101 102 103 104 105 ... 95 | 106 107 108 109 110 111 112 113 115 116 117 119 120 121 122]; 96 | %sig1 = squeeze(hyperResample(sig1, lSig, desiredLambdas)); 97 | figure; plot(sig1(goodBands)); grid on; title('Signature 1 - good bands only'); 98 | xlabel('Wavelength [nm]'); ylabel('Reflectance [%]'); 99 | hold on; plot(fsig1(goodBands), '--'); 100 | legend('Recorded', 'From Image'); 101 | 102 | 103 | % Display data 104 | M = hyperConvert2d(M); 105 | %[M, H, snr] = hyperMnf(M, w, h); 106 | M_pct = hyperPct(M, 3); 107 | M_pct = hyperNormalize(hyperConvert3d(M_pct,w,h,3)); 108 | figure; imagesc(M_pct); axis image; title('Scene'); 109 | 110 | % Data conditioning 111 | M = M(goodBands, :); 112 | sig1 = sig1(goodBands); 113 | %fsig1 = fsig1(goodBands); 114 | %sig1 = fsig1; 115 | 116 | %q = hyperHfcVd(M); 117 | 118 | % Do PCT 119 | if 0 120 | M = [M sig1]; 121 | %[M,V] = hyperPct(M,size(M,1)); 122 | [M,V] = hyperPct(M,55); 123 | sig1 = M(:,end); 124 | M = M(:,1:end-1); 125 | p = size(M,1); 126 | goodBands = 1:p; 127 | end 128 | 129 | %q = hyperHfcVd(M); 130 | q = 39; 131 | 132 | algorithm = lower(algorithm); 133 | tic 134 | switch algorithm 135 | case 'ica-eea' 136 | [U, X] = hyperIcaEea(M, 50, sig1); 137 | r = X(1,:); 138 | r = hyperConvert3d(r, w, h, 1); 139 | case 'rx' 140 | r = hyperConvert3d(hyperRxDetector(M), w, h, 1); 141 | case 'matchedfilter' 142 | r = hyperConvert3d(hyperMatchedFilter(M, sig1), w, h, 1); 143 | case 'ace' 144 | r = hyperConvert3d(hyperAce(M, sig1), w, h, 1); 145 | case 'mace' 146 | r = hyperConvert3d(hyperMace(M, sig1), w, h, 1); 147 | case 'sid' 148 | r = hyperConvert3d(hyperSid(M, sig1), w, h, 1); 149 | case 'cem' 150 | r = hyperConvert3d(hyperCem(M, sig1), w, h, 1); 151 | case 'plmf' 152 | r = hyperPlmf(hyperConvert3d(M,w,h,p),sig1,9); 153 | case 'rmf-sum' 154 | r = hyperRmf(hyperConvert3d(M,w,h,p),sig1,11,'sum'); 155 | case 'rmf-meanlocal' 156 | r = hyperRmf(hyperConvert3d(M,w,h,p),sig1,11,'meanLocal'); 157 | case 'rmf-meangloballocal' 158 | r = hyperRmf(hyperConvert3d(M,w,h,p),sig1,11,'meanGlobalLocal'); 159 | case 'glrt' 160 | r = hyperConvert3d(hyperGlrt(M, sig1), w, h, 1); 161 | case 'osp' 162 | U = hyperAtgp(M, q, sig1); 163 | r = hyperConvert3d(hyperOsp(M, U, sig1), w, h, 1); 164 | case 'amsd' 165 | r = hyperConvert3d(hyperAmsd(M, U, sig1), w, h, 1); 166 | case 'hud' 167 | U = hyperAtgp(M, q, sig1); 168 | r = hyperConvert3d(hyperHud(M, U, sig1), w, h, 1); 169 | case 'nnls' 170 | U = hyperAtgp(M, q, sig1); 171 | r = hyperConvert3d(hyperNnls(M,U),w,h,q); 172 | r = r(:,:,1); 173 | case 'fcls' 174 | U = hyperAtgp(M, q, sig1); 175 | r = hyperConvert3d(hyperFcls(M,U),w,h,q); 176 | r = r(:,:,1); 177 | case 'ucls' 178 | U = hyperAtgp(M, q, sig1); 179 | r = hyperConvert3d(hyperUcls(M,U),w,h,q); 180 | r = r(:,:,1); 181 | case 'sam' 182 | r = (1./(eps+hyperConvert3d(hyperSam(M, sig1), w, h, 1))); 183 | otherwise 184 | error('Incorrect algorithm name specified!\n'); 185 | end 186 | toc 187 | 188 | % Display results and write to file 189 | figure; imagesc(r); axis image; colorbar; 190 | title(algorithm); 191 | 192 | [a,b]=sort(r(:),'descend'); 193 | tmp = a(1:20); 194 | figure; plot(tmp./tmp(1)); grid on; 195 | [x, y, val] = hyperMax2d(r); 196 | 197 | % d1 = r(122,494) 198 | % d2 = r(127,490) 199 | % N = prod(size(r)); 200 | % [v] = sort(r(:),'ascend'); 201 | % idx = find(v==d2); 202 | % N-idx 203 | % figure; hist(r(:),100); 204 | 205 | tmp = (hyperNormalize(r)*2^10); 206 | multibandwrite(tmp, sprintf('%s\\results.img', outputDir), 'bil', 'PRECISION', 'int16', 'MACHFMT', 'ieee-le'); 207 | 208 | [pd,fa] = hyperRoc(r); 209 | figure; plot(fa,pd,'.'); grid on; title(sprintf('%s\n%s',algorithm, targetFilenames{1})); 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /functions/hyperDemo_detectors.m: -------------------------------------------------------------------------------- 1 | function hyperDemo_detectors 2 | % HYPERDEMO_DETECTORS Demonstrates target detector algorithms 3 | clear; clc; dbstop if error; close all; 4 | %-------------------------------------------------------------------------- 5 | % Parameters 6 | resultsDir = 'results\\'; 7 | dataDir = 'data\\AVIRIS\\'; 8 | %-------------------------------------------------------------------------- 9 | 10 | mkdir(resultsDir); 11 | 12 | % Read part of AVIRIS data file that we will further process 13 | M = hyperReadAvirisRfl(sprintf('%s\\f970620t01p02_r03_sc02.a.rfl', dataDir), [1 100], [1 614], [1 224]); 14 | M = hyperNormalize(M); 15 | 16 | % Read AVIRIS .spc file 17 | lambdasNm = hyperReadAvirisSpc(sprintf('%s\\f970620t01p02_r03.a.spc', dataDir)); 18 | 19 | % Isomorph 20 | [h, w, p] = size(M); 21 | M = hyperConvert2d(M); 22 | 23 | % Resample AVIRIS image. 24 | desiredLambdasNm = 400:(2400-400)/(224-1):2400; 25 | M = hyperResample(M, lambdasNm, desiredLambdasNm); 26 | 27 | % Remove low SNR bands. 28 | goodBands = [10:100 116:150 180:216]; 29 | M = M(goodBands, :); 30 | p = length(goodBands); 31 | 32 | % Demonstrate difference spectral similarity measurements 33 | M = hyperConvert3d(M, h, w, p); 34 | target = squeeze(M(11, 77, :)); 35 | figure; plot(desiredLambdasNm(goodBands), target); grid on; 36 | title('Target Signature; Pixel (32, 257)'); 37 | 38 | M = hyperConvert2d(M); 39 | 40 | % RX Anomly Detector 41 | r = hyperRxDetector(M); 42 | r = hyperConvert3d(r.', h, w, 1); 43 | figure; imagesc(r); title('RX Detector Results'); axis image; 44 | colorbar; 45 | hyperSaveFigure(gcf, sprintf('%s\\rx detector.png', resultsDir)); 46 | 47 | % Constrained Energy Minimization (CEM) 48 | r = hyperCem(M, target); 49 | r = hyperConvert3d(r, h, w, 1); 50 | figure; imagesc(abs(r)); title('CEM Detector Results'); axis image; 51 | colorbar; 52 | hyperSaveFigure(gcf, sprintf('%s\\cem detector.png', resultsDir)); 53 | 54 | % Adaptive Cosine Estimator (ACE) 55 | r = hyperAce(M, target); 56 | r = hyperConvert3d(r, h, w, 1); 57 | figure; imagesc(r); title('ACE Detector Results'); axis image; 58 | colorbar; 59 | hyperSaveFigure(gcf, sprintf('%s\\ace detector.png', resultsDir)); 60 | 61 | % Signed Adaptive Cosine Estimator (S-ACE) 62 | r = hyperSignedAce(M, target); 63 | r = hyperConvert3d(r, h, w, 1); 64 | figure; imagesc(r); title('Signed ACE Detector Results'); axis image; 65 | colorbar; 66 | hyperSaveFigure(gcf, sprintf('%s\\signed ace detector.png', resultsDir)); 67 | 68 | % Matched Filter 69 | r = hyperMatchedFilter(M, target); 70 | r = hyperConvert3d(r, h, w, 1); 71 | figure; imagesc(r); title('MF Detector Results'); axis image; 72 | colorbar; 73 | hyperSaveFigure(gcf, sprintf('%s\\mf detector.png', resultsDir)); 74 | 75 | % Generalized Likehood Ratio Test (GLRT) detector 76 | r = hyperGlrt(M, target); 77 | r = hyperConvert3d(r, h, w, 1); 78 | figure; imagesc(r); title('GLRT Detector Results'); axis image; 79 | colorbar; 80 | hyperSaveFigure(gcf, sprintf('%s\\cem detector.png', resultsDir)); 81 | 82 | 83 | % Estimate background endmembers 84 | U = hyperAtgp(M, 5); 85 | 86 | % Hybrid Unstructured Detector (HUD) 87 | r = hyperHud(M, U, target); 88 | r = hyperConvert3d(r, h, w, 1); 89 | figure; imagesc(abs(r)); title('HUD Detector Results'); axis image; 90 | colorbar; 91 | hyperSaveFigure(gcf, sprintf('%s\\hud detector.png', resultsDir)); 92 | 93 | % Adaptive Matched Subspace Detector (AMSD) 94 | r = hyperAmsd(M, U, target); 95 | r = hyperConvert3d(r, h, w, 1); 96 | figure; imagesc(abs(r)); title('AMSD Detector Results'); axis image; 97 | colorbar; 98 | hyperSaveFigure(gcf, sprintf('%s\\amsd detector.png', resultsDir)); 99 | figure; mesh(r); title('AMSD Detector Results'); 100 | 101 | % Orthogonal Subspace Projection (OSP) 102 | r = hyperOsp(M, U, target); 103 | r = hyperConvert3d(r, h, w, 1); 104 | figure; imagesc(abs(r)); title('OSP Detector Results'); axis image; 105 | colorbar; 106 | hyperSaveFigure(gcf, sprintf('%s\\osp detector.png', resultsDir)); 107 | 108 | -------------------------------------------------------------------------------- /functions/hyperDemo_mams_RIT_data.m: -------------------------------------------------------------------------------- 1 | clear; close all; clc; dbstop if error; 2 | 3 | %-------------------------------------------------------------------------- 4 | % This demo process the data from the RIT Target Detection Blind Test 5 | % contest which is located at: http://dirsapps.cis.rit.edu/blindtest/ 6 | %-------------------------------------------------------------------------- 7 | % Parameters 8 | inputFilename = 'data\self_test\HyMap\self_test_rad.img'; 9 | fasticaToolboxPath = '..\matlab_hyperspectral_toolbox\trunk\FastICA_25'; 10 | outputDir = 'RIT MAMS\'; 11 | %-------------------------------------------------------------------------- 12 | 13 | addpath(fasticaToolboxPath); 14 | mkdir(outputDir); 15 | 16 | % Read in the data 17 | h = 280; 18 | w = 800; 19 | p = 126; 20 | N = w*h; 21 | M = multibandread(inputFilename, [h w p], 'int16', 0, 'bil', 'ieee-le')/1e4; 22 | lData = hyperGetHymapWavelengthsNm(); 23 | 24 | % Select good bands. In this case, all bands are okay to use. 25 | goodBands = 1:p; 26 | 27 | % Display data 28 | M = hyperConvert2d(M); 29 | M_pct = hyperPct(M, 3); 30 | M_pct = hyperNormalize(hyperConvert3d(M_pct, h, w, 3)); 31 | figure; imagesc(M_pct); axis image; title('Scene'); 32 | 33 | % Data conditioning 34 | M = M(goodBands, :); 35 | 36 | % Compute the number of endmembers/materials in the scene. 37 | %q = hyperHfcVd(M); 38 | q = 53; 39 | 40 | modelErr = []; 41 | for q = 1:p 42 | % Find the endmembers/materials in the scene. 43 | fprintf('Searching for fundemental endmembers...\n'); 44 | [U,idx] = hyperAtgp(M, q); 45 | idx 46 | figure; plot(U); title('ATGP Recovered Endmembers'); grid on; 47 | 48 | % Create abundance maps from unmixed endmembers. 49 | fprintf('Generating material abundance maps (MAMs)...\n'); 50 | %abundanceMaps = hyperUcls(M, U); 51 | %abundanceMaps = hyperNnls(M, U); 52 | abundanceMaps = hyperFcls(M, U); 53 | % abundanceMaps = hyperNormXCorr(M, U); 54 | abundanceMaps = hyperConvert3d(abundanceMaps, h, w, q); 55 | 56 | % Display results and save figures to disk. 57 | for i=1:q 58 | figure; imagesc(abundanceMaps(:,:,i)); colorbar; axis image; 59 | title(sprintf('Abundance Map %d', i)); 60 | hyperSaveFigure(gcf, sprintf('%s\\chain1 - mam - %d.png', outputDir, i), 'wysiwyp'); 61 | close(gcf); 62 | end 63 | 64 | % Compute abundance fraction sums for each pixel. 65 | abundanceMaps = hyperConvert2d(abundanceMaps); 66 | tmpMap = zeros(h*w,1); 67 | for k=1:N 68 | tmpMap(k) = sum(abundanceMaps(:,k)); 69 | end 70 | tmpMap = hyperConvert3d(tmpMap, h, w, 1); 71 | figure; imagesc(tmpMap); colorbar; axis image; 72 | title('Sum of Each Pixel Abundance'); 73 | 74 | % Compute error between decomposed signature and real signature 75 | tmpMap = zeros(h*w,1); 76 | reconstructedM = U*abundanceMaps; 77 | for k=1:N 78 | tmpMap(k) = norm(reconstructedM(:,k)-M(:,k)); 79 | end 80 | tmpMap = hyperConvert3d(tmpMap, h, w, 1); 81 | figure; imagesc(tmpMap); colorbar; axis image; 82 | title('Model Error'); 83 | close all; 84 | 85 | modelErr(q) = sum(tmpMap(:)); 86 | end 87 | 88 | figure; plot(1:p,modelErr(1:p)); grid on; 89 | title('Model Error'); 90 | 91 | fprintf('Done.\n'); 92 | 93 | 94 | %--------------- 95 | t = tmpMap(:); 96 | [~,tMaxIdx]=max(t); 97 | figure;plot(M(:,tMaxIdx)); 98 | 99 | [a,b]=sort(t,'descend'); 100 | b(1:100) 101 | figure; plot(a); 102 | figure; hist(a,100); 103 | 104 | figure; plot(M(:,b(1:100))); 105 | title('100 worst model fits') 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /functions/hyperDestreak.m: -------------------------------------------------------------------------------- 1 | function [M, alpha, beta] = hyperDestreak(M) 2 | % HYPERDESTREAK Destreaks a hyperspectral data cube. 3 | % hyperDestreak removes vertical streaking artifacts from an HSI image. 4 | % 5 | % Usage 6 | % [M, alpha, beta] = hyperDestreak(M) 7 | % Inputs 8 | % M - 3D cube of HSI data. 9 | % Outputs 10 | % M - Destreaked data 11 | % alpha - mean value of column and band 12 | % beta - offset value of column and band 13 | % 14 | % References 15 | % Data, et al. "Processing E)-1 Hyperion Hypespectral Data to Support 16 | % the Application of Agricultural Index." IEEE TGRS. Vol 41. No 6. June 17 | % 2003. 18 | 19 | [h, w, p] = size(M); 20 | m = zeros(p,1); 21 | for k=1:p 22 | tmp = M(:,:,k); 23 | tmp = tmp(:); 24 | m(k) = mean(tmp); 25 | s(k) = std(tmp); 26 | for kk=1:w 27 | tmp = squeeze(M(:,kk,k)); 28 | ml = mean(tmp); 29 | sl = std(tmp); 30 | alpha(k,kk) = s(k) / sl; 31 | beta(k,kk) = m(k) - alpha(k,kk)*ml; 32 | tmp = alpha(k,kk)*tmp + beta(k,kk); 33 | M(:,kk,k) = tmp; 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /functions/hyperFcls.m: -------------------------------------------------------------------------------- 1 | function [ X ] = hyperFcls( M, U ) 2 | %HYPERFCLS Performs fully constrained least squares on pixels of M. 3 | % hyperFcls performs fully constrained least squares of each pixel in M 4 | % using the endmember signatures of U. Fully constrained least squares 5 | % is least squares with the abundance sum-to-one constraint (ASC) and the 6 | % abundance nonnegative constraint (ANC). 7 | % 8 | % Usage 9 | % [ X ] = hyperFcls( M, U ) 10 | % Inputs 11 | % M - HSI data matrix (p x N) 12 | % U - Matrix of endmembers (p x q) 13 | % Outputs 14 | % X - Abundance maps (q x N) 15 | % 16 | % References 17 | % "Fully Constrained Least-Squares Based Linear Unmixing." Daniel Heinz, 18 | % Chein-I Chang, and Mark L.G. Althouse. IEEE. 1999. 19 | 20 | if (ndims(U) ~= 2) 21 | error('M must be a p x q matrix.'); 22 | end 23 | 24 | [p1, N] = size(M); 25 | [p2, q] = size(U); 26 | if (p1 ~= p2) 27 | error('M and U must have the same number of spectral bands.'); 28 | end 29 | 30 | p = p1; 31 | X = zeros(q, N); 32 | Mbckp = U; 33 | for n1 = 1:N 34 | count = q; 35 | done = 0; 36 | ref = 1:q; 37 | r = M(:, n1); 38 | U = Mbckp; 39 | while not(done) 40 | als_hat = inv(U.'*U)*U.'*r; 41 | s = inv(U.'*U)*ones(count, 1); 42 | 43 | % IEEE Magazine method (http://www.planetary.brown.edu/pdfs/3096.pdf) 44 | % Contains correction to sign. Error in original paper. 45 | afcls_hat = als_hat - inv(U.'*U)*ones(count, 1)*inv(ones(1, count)*inv(U.'*U)*ones(count, 1))*(ones(1, count)*als_hat-1); 46 | 47 | % See if all components are positive. If so, then stop. 48 | if (sum(afcls_hat>0) == count) 49 | alpha = zeros(q, 1); 50 | alpha(ref) = afcls_hat; 51 | break; 52 | end 53 | % Multiply negative elements by their counterpart in the s vector. 54 | % Find largest abs(a_ij, s_ij) and remove entry from alpha. 55 | idx = find(afcls_hat<0); 56 | afcls_hat(idx) = afcls_hat(idx) ./ s(idx); 57 | [val, maxIdx] = max(abs(afcls_hat(idx))); 58 | maxIdx = idx(maxIdx); 59 | alpha(maxIdx) = 0; 60 | keep = setdiff(1:size(U, 2), maxIdx); 61 | U = U(:, keep); 62 | count = count - 1; 63 | ref = ref(keep); 64 | end 65 | X(:, n1) = alpha; 66 | end 67 | 68 | return; 69 | -------------------------------------------------------------------------------- /functions/hyperFclsMatlab.m: -------------------------------------------------------------------------------- 1 | function [ X ] = hyperFclsMatlab( M, U ) 2 | %HYPERFCLSMATLAB Performs fully constrained least squares on pixels of M. 3 | % hyperFclsMatlab performs fully constrained least squares of each pixel 4 | % in M using the endmember signatures of U. Fully constrained least s 5 | % quares is least squares with the abundance sum-to-one constraint (ASC) 6 | % and the abundance nonnegative constraint (ANC). 7 | % This method utilizes Matlab's built-in solver to compute the answer. 8 | % 9 | % Usage 10 | % [ X ] = hyperFclsMatlab( M, U ) 11 | % Inputs 12 | % M - HSI data matrix (p x N) 13 | % U - Matrix of endmembers (p x q) 14 | % Outputs 15 | % X - Abundance maps (q x N) 16 | 17 | if (ndims(U) ~= 2) 18 | error('M must be a p x q matrix.'); 19 | end 20 | 21 | [p1, N] = size(M); 22 | [p2, q] = size(U); 23 | if (p1 ~= p2) 24 | error('M and U must have the same number of spectral bands.'); 25 | end 26 | 27 | Minv = pinv(U); 28 | X = zeros(q, N); 29 | for n1 = 1:N 30 | %X(:, n1) = Minv*M(:, n1); 31 | X(:, n1) = lsqlin(U, M(:, n1), [], [], ones(1,q), 1, zeros(q,1),[], []); 32 | end 33 | 34 | return; 35 | 36 | 37 | -------------------------------------------------------------------------------- /functions/hyperFileFind.m: -------------------------------------------------------------------------------- 1 | function listOfMatchingFiles = hyperFileFind(startingDirectory, nameTemplate) 2 | % HYPERFILEFIND Searches through directories for files with specified name 3 | % Searches through the specified directory and sub-directories looking 4 | % for files matching the specified template. Returns the full, partial 5 | % path for each file matching the template 6 | % 7 | % Usage 8 | % [listOfMatchingFiles] = hyperFileFind(startingDirectory, nameTemplate) 9 | % Inputs 10 | % startingDirectory - Directory to begin search 11 | % nameTemplate - Template for file nameTemplate matching 12 | % Outputs 13 | % listOfMatchingFiles - Cell array with each element containing a string of a 14 | % file matching the name template. 15 | 16 | 17 | % Find all directories 18 | tmp = dir(startingDirectory); 19 | dTmp = []; 20 | for i=3:length(tmp) 21 | if (tmp(i).isdir == 1) 22 | dTmp = [dTmp; tmp(i)]; 23 | end 24 | end 25 | 26 | dTmp = [dTmp; dir(fullfile(startingDirectory, nameTemplate))]; 27 | listOfMatchingFiles = {}; 28 | for i=1:length(dTmp) 29 | if (dTmp(i).isdir == 1) 30 | listOfMatchingFiles = [listOfMatchingFiles; hyperFileFind(fullfile(startingDirectory, dTmp(i).name), nameTemplate)]; 31 | else 32 | listOfMatchingFiles = [listOfMatchingFiles; fullfile(startingDirectory, dTmp(i).name)]; 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /functions/hyperGetEnviSignature.m: -------------------------------------------------------------------------------- 1 | function [refl, lambdaNm] = hyperGetEnviSignature(filename) 2 | % HYPERGETENVISIGNATURE Reads an ENVI hyperspectral reflectance signature 3 | % hyperGetEnviSignature reads the RIT Target Detection Blind Test 4 | % signature files. 5 | % 6 | % Usage 7 | % [refl, lambdaNm] = hyperGetEnviSignature(filename) 8 | % 9 | % Input 10 | % filename - Filename of signature. 11 | % Output 12 | % refl - Reflectance values [0, 1]. 13 | % lambdaNm - corresponding wavelengths in nanometers 14 | 15 | fid = fopen(filename); 16 | 17 | for k=1:3 18 | dummy = fgetl(fid); 19 | end 20 | 21 | num = 1; 22 | while 1 23 | tmp = fgetl(fid); 24 | if (tmp == -1), break, end; 25 | v = sscanf(tmp, '%f'); 26 | refl(num) = v(2); 27 | lambdaNm(num) = v(1); 28 | num = num + 1; 29 | end 30 | 31 | refl = refl / 100; -------------------------------------------------------------------------------- /functions/hyperGetHymapWavelengthsNm.m: -------------------------------------------------------------------------------- 1 | function lambdaNm = hyperGetHymapWavelengthsNm() 2 | % HYPERGETHYMAPWAVELENGTHSNM Returns list of wavelengths for Hymap Sensor 3 | % 4 | % Usage 5 | % lambdaNm = hyperGetHymapWavelengthsNm() 6 | % 7 | % Inputs 8 | % None 9 | % Outputs 10 | % lambdaNm - Hymap instrument wavelengths in nanometers 11 | 12 | lambdaNm = [... 13 | 453.799988, 467.399994, 481.899994, 496.899994, 511.700012, 526.500000, ... 14 | 541.599976, 556.500000, 571.200012, 585.900024, 600.700012, 615.500000,... 15 | 630.000000, 644.299988, 658.900024, 673.599976, 688.000000, 702.400024,... 16 | 716.900024, 731.299988, 745.400024, 759.599976, 773.900024, 788.099976,... 17 | 802.200012, 816.299988, 830.700012, 844.900024, 858.900024, 872.500000,... 18 | 874.799988, 891.900024, 907.299988, 922.799988, 938.599976, 954.099976,... 19 | 969.200012, 984.400024, 999.900024, 1014.900024, 1029.900024, 1045.099976,... 20 | 1060.099976, 1074.599976, 1089.199951, 1104.099976, 1118.599976, 1133.000000,... 21 | 1147.400024, 1161.800049, 1176.000000, 1190.199951, 1204.300049, 1218.300049,... 22 | 1232.099976, 1246.099976, 1260.199951, 1274.099976, 1287.599976, 1301.199951,... 23 | 1315.199951, 1328.900024, 1389.300049, 1404.199951, 1419.300049, 1433.500000,... 24 | 1448.000000, 1462.400024, 1477.000000, 1490.900024, 1504.800049, 1518.599976,... 25 | 1532.500000, 1546.099976, 1559.800049, 1573.199951, 1586.400024, 1599.500000,... 26 | 1612.800049, 1626.000000, 1638.800049, 1651.699951, 1664.500000, 1677.199951,... 27 | 1689.699951, 1702.300049, 1714.900024, 1727.300049, 1739.500000, 1751.800049,... 28 | 1764.000000, 1776.000000, 1788.000000, 1799.900024, 1952.400024, 1971.699951,... 29 | 1991.000000, 2010.099976, 2029.000000, 2048.000000, 2067.199951, 2086.199951,... 30 | 2104.800049, 2123.000000, 2141.000000, 2159.100098, 2177.000000, 2194.600098,... 31 | 2213.399902, 2231.000000, 2248.199951, 2265.699951, 2283.100098, 2300.600098,... 32 | 2317.600098, 2334.500000, 2351.100098, 2367.600098, 2384.399902, 2401.100098,... 33 | 2417.699951, 2433.699951, 2449.600098, 2465.300049, 2480.899902, 2496.300049]; 34 | -------------------------------------------------------------------------------- /functions/hyperGlrt.m: -------------------------------------------------------------------------------- 1 | function [results] = hyperGlrt(M, t) 2 | % HYPERGLRT Performs the generalized liklihood test ratio algorithm 3 | % Performs the generalized liklihood test ratio algorithm for target 4 | % detection. 5 | % 6 | % Usage 7 | % [results] = hyperGlrt(M, U, target) 8 | % Inputs 9 | % M - 2d matrix of HSI data (p x N) 10 | % t - target of interest (p x 1) 11 | % Outputs 12 | % results - vector of detector output (N x 1) 13 | % 14 | % References 15 | % T F AyouB, "Modified GLRT Signal Detection Algorithm," IEEE 16 | % Transactions on Aerospace and Electronic Systems, Vol 36, No 3, July 17 | % 2000. 18 | 19 | [p, N] = size(M); 20 | 21 | % Remove mean from data 22 | u = mean(M.').'; 23 | M = M - repmat(u, 1, N); 24 | t = t - u; 25 | 26 | R = inv(hyperCov(M)); 27 | 28 | results = zeros(1, N); 29 | for k=1:N 30 | x = M(:,k); 31 | results(k) = ((t'*R*x)^2) / ((t'*R*t)*(1 + x'*R*x)); 32 | end -------------------------------------------------------------------------------- /functions/hyperHfcVd.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/functions/hyperHfcVd.m -------------------------------------------------------------------------------- /functions/hyperHud.m: -------------------------------------------------------------------------------- 1 | function [results] = hyperHud(M, B, S) 2 | % HYPERHUD Performs the hybrid unstructured detector (HUD) algorithm 3 | % Performs the hybrid unstructured detector algorithm for target 4 | % detection. 5 | % 6 | % Usage 7 | % [results] = hyperHud(M, B, S) 8 | % Inputs 9 | % M - 2d matrix of HSI data (p x N) 10 | % B - 2d matrix of background endmembers (p x q) 11 | % S - 2d matrix of target endmembers (p x #target_sigs) 12 | % Outputs 13 | % results - vector of detector output (N x 1) 14 | % 15 | % References 16 | % J Broadwater & R Chellappa. "Hybrid Detectors for Subpixel Targets." 17 | % IEEE PAMI. Vol 29. No 11. November 2007. 18 | 19 | 20 | [p, N] = size(M); 21 | % Remove mean from data 22 | u = mean(M.').'; 23 | M = M - repmat(u, 1, N); 24 | S = S - repmat(u, 1, size(S,2)); 25 | 26 | numTargets = size(S,2); 27 | %sigma = 1e-5; 28 | E = [S B]; 29 | %E = [sigma*E; ones(1,size(E,2))]; 30 | q = size(E, 2); 31 | 32 | R_hat = (M*M.')/N; 33 | G = inv(R_hat); 34 | 35 | results = zeros(1, N); 36 | 37 | R = ones(q,1); 38 | P = R - 1; 39 | % TODO - put in the whitened version of fcls 40 | a_hat_tmp = hyperNnls(M, E); 41 | %a_hat_tmp = hyperFcls(M, E); 42 | for k=1:N 43 | x = M(:,k); 44 | a_hat = a_hat_tmp(:,k); 45 | % Take the top r values from a_hat where r is number of targets. We 46 | % are only interested in the abundances for the targets. From J 47 | % Broadwater email 11/17/09. 48 | a_hat = a_hat(1:numTargets); 49 | % % x = [sigma*x; 1]; 50 | % % FCLS optimzation 51 | % lambda = zeros(q,1); 52 | % aPrev = lambda; 53 | % for kk=1:100 54 | % a_hat = inv(E.'*G*E)*E.'*G*x - inv(E.'*G*E)*lambda; 55 | % norm(a_hat-aPrev) 56 | % lambda = E.'*G*(x-E*a_hat); 57 | % idx = find(a_hat>0); 58 | % P(idx) = 1; 59 | % R(idx) = 0; 60 | % aPrev = a_hat; 61 | % end 62 | % a_hat = a_hat(1:numTargets); 63 | results(k) = (x.'*G*S*a_hat) / (x.'*G*x); 64 | end -------------------------------------------------------------------------------- /functions/hyperIcaComponentScores.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/functions/hyperIcaComponentScores.m -------------------------------------------------------------------------------- /functions/hyperIcaEea.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/functions/hyperIcaEea.m -------------------------------------------------------------------------------- /functions/hyperImagesc.m: -------------------------------------------------------------------------------- 1 | function [rgb] = hyperImagesc(img, bands) 2 | %UNTITLED1 Summary of this function goes here 3 | % Usage: plotAvirisRgb(img, bands) 4 | 5 | [h, w, p] = size(img); 6 | 7 | if (nargin == 1) 8 | bands = [1 round(p/2) p]; 9 | end 10 | blue = img(:,:,bands(1)); 11 | green = img(:,:,bands(2)); 12 | red = img(:,:,bands(3)); 13 | 14 | rgb = zeros(size(img, 1), size(img, 2), 3); 15 | rgb(:,:,1) = hyperNormalize(red); 16 | rgb(:,:,2) = hyperNormalize(green); 17 | rgb(:,:,3) = hyperNormalize(blue); 18 | 19 | rgb = decorrstretch(rgb); 20 | red = rgb(:,:,1); 21 | green = rgb(:,:,2); 22 | blue = rgb(:,:,3); 23 | rgb(:,:,1) = adapthisteq(red); 24 | rgb(:,:,2) = adapthisteq(green); 25 | rgb(:,:,3) = adapthisteq(blue); 26 | 27 | imshow(rgb); axis image; 28 | -------------------------------------------------------------------------------- /functions/hyperImshow.m: -------------------------------------------------------------------------------- 1 | function [rgb] = hyperImshow( img, bands ) 2 | %UNTITLED1 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | 6 | [h, w, p] = size(img); 7 | 8 | if (nargin == 1) 9 | bands = [p round(p/2) 1]; 10 | end 11 | red = img(:,:,bands(1)); 12 | green = img(:,:,bands(2)); 13 | blue = img(:,:,bands(3)); 14 | 15 | rgb = zeros(size(img, 1), size(img, 2), 3); 16 | rgb(:,:,1) = adapthisteq(red); 17 | rgb(:,:,2) = adapthisteq(green); 18 | rgb(:,:,3) = adapthisteq(blue); 19 | 20 | imshow(rgb); axis image; 21 | 22 | 23 | 24 | % tmp = zeros(100, 614, 3); 25 | % tmp(:,:,1) = histeq((img(:,:, [36]))); 26 | % tmp(:,:,2) = histeq((img(:,:, [24]))); 27 | % tmp(:,:,3) = histeq((img(:,:, [12]))); 28 | % image(tmp); -------------------------------------------------------------------------------- /functions/hyperMatchedFilter.m: -------------------------------------------------------------------------------- 1 | function [results] = hyperMatchedFilter(M, t) 2 | % TODO Fix this 3 | % HYPERACE Performs the adaptive cosin/coherent estimator algorithm 4 | % Performs the adaptive cosin/coherent estimator algorithm for target 5 | % detection. 6 | % 7 | % Usage 8 | % [results] = hyperAce(M, S) 9 | % Inputs 10 | % M - 2d matrix of HSI data (p x N) 11 | % S - 2d matrix of target endmembers (p x q) 12 | % Outputs 13 | % results - vector of detector output (N x 1) 14 | % 15 | % References 16 | % X Jin, S Paswater, H Cline. "A Comparative Study of Target Detection 17 | % Algorithms for Hyperspectral Imagery." SPIE Algorithms and Technologies 18 | % for Multispectral, Hyperspectral, and Ultraspectral Imagery XV. Vol 19 | % 7334. 2009. 20 | 21 | 22 | [p, N] = size(M); 23 | % Remove mean from data 24 | u = mean(M.').'; 25 | M = M - repmat(u, 1, N); 26 | t = t - u; 27 | 28 | R_hat = hyperCov(M); 29 | G = inv(R_hat); 30 | 31 | results = zeros(1, N); 32 | tmp = t.'*G*t; 33 | for k=1:N 34 | x = M(:,k); 35 | results(k) = (x.'*G*t)/tmp; 36 | end 37 | -------------------------------------------------------------------------------- /functions/hyperMax2d.m: -------------------------------------------------------------------------------- 1 | function [x, y, val] = hyperMax2d(mat) 2 | % HYPERMAX2D Finds the max value and position in a matrix 3 | % 4 | % Usage 5 | % [x, y, val] = hyperMax2d(mat) 6 | % Inputs 7 | % mat - Input matrix 8 | % Outputs 9 | % x - X position of maximum value 10 | % y - Y position of maximum value 11 | % val - Maximum value in matrix 12 | 13 | [dum, y] = max(mat); 14 | [val, y] = max(dum); 15 | [dum, x] = max(mat(:,y)); -------------------------------------------------------------------------------- /functions/hyperMnf.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/functions/hyperMnf.m -------------------------------------------------------------------------------- /functions/hyperNapc.m: -------------------------------------------------------------------------------- 1 | function [M, H, noiseFractions] = hyperNacp(M, h, w) 2 | % HYPERNAPC Performs the noise adjusted principal component transform (NACP) 3 | % hyperNacp performs the noise adjust principal component transform on the 4 | % data and uses spatial (row) offsets of the data to estimate the 5 | % covariance matrix of the data. 6 | % 7 | % Usage 8 | % M = hyperNacp(M, h, w) 9 | % Inputs 10 | % M - 2D matrix (p x N) 11 | % h - height of image in pixels 12 | % w - width of image in pixels 13 | % Outputs 14 | % M - 2D transformed data 15 | % H - 2D transformation matrix 16 | % noiseFractions - Estimates of the noise fraction for each band 17 | % 18 | % References 19 | % C-I Change and Q Du, "Interference and Noise-Adjusted Principal 20 | % Components Analysis," IEEE TGRS, Vol 36, No 5, September 1999. 21 | 22 | [p, N] = size(M); 23 | 24 | % Remove mean from data 25 | u = mean(M.').'; 26 | for k=1:N 27 | M(:,k) = M(:,k) - u; 28 | end 29 | 30 | % Compute to rotation of the signal+noise 31 | sigmaZ = hyperCov(M); 32 | M = hyperConvert3d(M, h, w, p); 33 | 34 | % Estimate the covariance of the noise. 35 | dX = zeros(h-1, w, p); 36 | for i=1:(h-1) 37 | dX(i, :, :) = M(i, :, :) - M(i+1, :, :); 38 | end 39 | dX = hyperConvert2d(dX); 40 | 41 | % Compute the covariance of the noise signal estimate. 42 | sigmaN = hyperCov(dX); 43 | 44 | % Orthonormalize the noise subspace. 45 | [U,deltaN,E] = svd(sigmaN); 46 | F = E*inv(sqrt(deltaN)); % Rotation components of noise orthonormalized 47 | % F now whitens the noise. 48 | 49 | % Rotates the signal+noise cov so that the noise is whitened (all noise 50 | % powers are equal) 51 | sigmaAdj = F'*sigmaZ*F; 52 | 53 | [U,gammaAdj,G] = svd(sigmaAdj); 54 | H = G*F; 55 | 56 | % Compute noise fractions 57 | noiseFractions = diag(gammaAdj); 58 | 59 | % Perform transform 60 | M = H*hyperConvert2d(M); 61 | 62 | -------------------------------------------------------------------------------- /functions/hyperNnls.m: -------------------------------------------------------------------------------- 1 | function [ X ] = hyperNnls( M, U ) 2 | %HYPERNNLS Performs non-negative constrained least squares on pixels of M. 3 | % hyperFcls performs non-negative constrained least squares of each pixel 4 | % in M using the endmember signatures of U. Non-negative constrained least 5 | % squares with the abundance nonnegative constraint (ANC). 6 | % Utilizes the method of Bro. 7 | % 8 | % Usage 9 | % [ X ] = hyperNnls( M, U ) 10 | % Inputs 11 | % M - HSI data matrix (p x N) 12 | % U - Matrix of endmembers (p x q) 13 | % Outputs 14 | % X - Abundance maps (q x N) 15 | % 16 | % References 17 | % Bro R., de Jong S., Journal of Chemometrics, 1997, 11, 393-401 18 | 19 | if (ndims(M) ~= 2) 20 | error('M must be a p x N matrix.'); 21 | end 22 | if (ndims(U) ~= 2) 23 | error('U must be a p x q matrix.'); 24 | end 25 | 26 | [p1, N] = size(M); 27 | [p2, q] = size(U); 28 | if (p1 ~= p2) 29 | error('M and U must have the same number of spectral bands.'); 30 | end 31 | 32 | Minv = pinv(U); 33 | X = zeros(q, N); 34 | MtM = U.'*U; 35 | for n1 = 1:N 36 | drawnow; 37 | %X(:, n1) = Minv*M(:, n1); 38 | %X(:, n1) = lsqlin(U, M(:, n1), [], [], ones(1,q), 1, zeros(q,1),[], []); 39 | X(:, n1) = fnnls(MtM, U.' * M(:,n1)); 40 | %X(:, n1) = lsqnonneg(U, M(:, n1)); 41 | end 42 | 43 | return; -------------------------------------------------------------------------------- /functions/hyperNormXCorr.m: -------------------------------------------------------------------------------- 1 | function [ result ] = hyperNormXCorr( a, b ) 2 | % HYPERNORMXCORR Computes the normalized cross correlation 3 | % hyperNormXCorr computes the normalized cross correlation between two 4 | % vectors. The value returned is in [-1. 1] 5 | % 6 | % Usage 7 | % [ result ] = hyperNormXCorr( a, b ) 8 | % Inputs 9 | % a - Vector 1. 10 | % b - Vector 2. 11 | % Outputs 12 | % result - Normalized cross-correlation result. 13 | 14 | if (size(a, 2) ~= 1) 15 | N = size(a, 2); 16 | q = size(b, 2); 17 | result = zeros(q, N); 18 | for x=1:N 19 | for y=1:q 20 | result(y, x) = abs(hyperNormXCorr(a(:, x), b(:, y))); 21 | end 22 | end 23 | else 24 | a = a(:); b = b(:); 25 | s = length(a); 26 | %err = normxcorr2(a, b); 27 | err = sum((a-mean(a)).*(b-mean(b))) / (std(a)*std(b)); 28 | err = err * (1/(s-1)); 29 | result = err; 30 | end 31 | return; -------------------------------------------------------------------------------- /functions/hyperNormalize.m: -------------------------------------------------------------------------------- 1 | function [ normalizedM ] = hyperNormalize( M ) 2 | %HYPERNORMALIZE Normalized data to be in range [0, 1] 3 | % hyperNormalize Normalizes data to be in range [0, 1] 4 | % 5 | % Usage 6 | % hyperNormalize(M) 7 | % Inputs 8 | % M - Input data 9 | % Outputs 10 | % normalizedM - Normalized data 11 | 12 | minVal = min(M(:)); 13 | maxVal = max(M(:)); 14 | 15 | normalizedM = M - minVal; 16 | if (maxVal == minVal) 17 | normalizeData = zeros(size(M)); 18 | else 19 | normalizedM = normalizedM ./ (maxVal-minVal); 20 | end 21 | -------------------------------------------------------------------------------- /functions/hyperOrthorectify.m: -------------------------------------------------------------------------------- 1 | function [ imgOut ] = hyperOrthorectify( imgIn, altitude, hpbw ) 2 | %HYPERORTHORECTIFY Orthorectifies areal observed data. 3 | % Orthorectifies areal observed data using nearest neighbor interpolation. 4 | % 5 | % Inputs 6 | % imgIn Input image (m x n) or (m x n x p) 7 | % altitude Sensor altitude (meters) 8 | % hpbw Half power beam width (radians). 9 | % Outputs 10 | % imgOut Orthorectified image. 11 | 12 | % Input parameters 13 | if (ndims(imgIn) == 2) 14 | [h, w] = size(imgIn); 15 | p = 1; 16 | elseif (ndims(imgIn) == 3) 17 | [h, w, p] = size(imgIn); 18 | end 19 | 20 | radPerPix = hpbw/w; 21 | x = tan(hpbw/2)*altitude; % m 22 | gsd = altitude*radPerPix; % m 23 | n = x/gsd; 24 | 25 | imgOut = zeros(h, floor(n)*2, p); 26 | for k=1:p 27 | for j=1:h 28 | for i=-floor(n):1:floor(n)-1 29 | boresiteDistance = gsd*i; 30 | theta = atan(boresiteDistance/altitude); 31 | imagePix = round(theta / radPerPix); 32 | imgOut(j, floor(n)+i+1, k) = imgIn(j, (w/2)+imagePix+1, k); 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /functions/hyperOsp.m: -------------------------------------------------------------------------------- 1 | function [nu] = hyperOsp(M, U, target) 2 | % HYPEROSP Performs the othogonal subspace projection (OSP) algorithm 3 | % Performs the othogonal subspace projection algorithm for target 4 | % detection. 5 | % 6 | % Usage 7 | % [results] = hyperOsp(M, U, target) 8 | % Inputs 9 | % M - 2d matrix of HSI data (p x N) 10 | % U - 2d matrix of background endmebers (p x q) 11 | % target - target of interest (p x 1) 12 | % Outputs 13 | % results - vector of detector output (N x 1) 14 | % 15 | % References 16 | % Qian Du, Hsuan Ren, and Chein-I Cheng. "A Comparative Study of 17 | % Orthogonal Subspace Projection and Constrained Energy Minimization." 18 | % IEEE TGRS. Volume 41. Number 6. June 2003. 19 | 20 | [p, N] = size(M); 21 | 22 | % Equation 3 23 | P_U = eye(p) - U * pinv(U); 24 | 25 | % For abundance estimation 26 | % Equation 4 27 | %w_osp = inv(target.'*P_U*target) * P_U * target; 28 | 29 | tmp = target'*P_U*target; 30 | nu = zeros(N, 1); 31 | for k=1:N 32 | nu(k) = (target'*P_U*M(:,k))/tmp; 33 | end -------------------------------------------------------------------------------- /functions/hyperPct.m: -------------------------------------------------------------------------------- 1 | function [M_pct, V, lambda] = hyperPct(M, q) 2 | %HYPERPCA Performs the principal components transform (PCT) 3 | % hyperPct performs the principal components transform on a data matrix. 4 | % 5 | % Usage 6 | % [M_pct, V] = hyperPct(M, q) 7 | % Inputs 8 | % M - 2D matrix (p x N) 9 | % q - number of components to keep 10 | % Outputs 11 | % M_pct - 2D matrix (q x N) which is result of transform 12 | % V - Transformation matrix. 13 | % lambda - eigenvalues 14 | % 15 | % References 16 | % http://en.wikipedia.org/wiki/Principal_component_analysis 17 | 18 | [p, N] = size(M); 19 | 20 | % Remove the data mean 21 | u = mean(M.').'; 22 | %M = M - repmat(u, 1, N); 23 | M_orig=M; 24 | M = M - (u*ones(1,N)); 25 | 26 | % Compute covariance matrix 27 | C = (M*M.')/(N-1); 28 | 29 | % Find eigenvalues of covariance matrix 30 | [V, D] = eigs(C, q); 31 | 32 | % Transform data 33 | M_pct = V'*M_orig; 34 | 35 | lambda = diag(D); 36 | 37 | return; 38 | -------------------------------------------------------------------------------- /functions/hyperPlmf.m: -------------------------------------------------------------------------------- 1 | function [results] = hyperPlmf(M, t, windowSize) 2 | % HYPERPLMF Performs the PCA local matched filter (PLMF) target detection algorithm 3 | % Performs the PCA local matched filter (PLMF) target detection algorithm. 4 | % 5 | % Usage 6 | % [results] = hyperPlmf(M, target, windodwSize) 7 | % Inputs 8 | % M - dd matrix of HSI data (m x n x p) 9 | % t - target of interest (p x 1) 10 | % Outputs 11 | % results - vector of detector output (m x n) 12 | % 13 | % References 14 | % Sofa, Geva, Rotman. "Improved covariance matrices for point target detection in hyperspectral 15 | % data." IEEE International Conference on Microwaves, Communications, Antennas and Electronics 16 | % Systems, 2009. COMCAS 2009. 17 | 18 | % windowSize must be odd number 19 | if ~mod(windowSize,2) 20 | error('windowSize must be an odd number.') 21 | end 22 | 23 | if (length(size(M)) ~= 3) 24 | error('M must be 3-dimensional matrix.') 25 | end 26 | 27 | [h,w,p] = size(M); 28 | N = h*w; 29 | 30 | % Remove mean from the target 31 | M = hyperConvert2d(M); 32 | u = mean(M.').'; 33 | 34 | [Mpca,V,lambda] = hyperPct(M,p); 35 | t_pct = V.'*(t-u); 36 | 37 | % Create map to get neighbors 38 | map = 1:N; 39 | map = reshape(map,h,w); 40 | 41 | R_hat = hyperCov(Mpca); 42 | G = inv(R_hat); 43 | 44 | results = zeros(h,w); 45 | s = floor(windowSize/2)+1; 46 | for k=s:(h-s) 47 | for kk=s:(w-s) 48 | midIdx = map(k,kk); 49 | neighborhoodIdx = map((k-s+1):(k+s-1),(kk-s+1):(kk+s-1)); 50 | 51 | Mlocal = M(:,neighborhoodIdx(:)); 52 | [~,~,lambdaLocal] = hyperPct(Mlocal,p); 53 | 54 | y = Mpca(:,midIdx); 55 | results(k,kk) = sum((t_pct.*y)./max(lambdaLocal,lambda)); 56 | end 57 | end 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /functions/hyperPpi.m: -------------------------------------------------------------------------------- 1 | function [U] = hyperPpi(M, q, numSkewers) 2 | % HYPERPPI Performs the pixel purity index (PPI) algorithm 3 | % Performs the pixel purity index algorithm for endmember finding. 4 | % 5 | % Usage 6 | % [U] = hyperPpi(M, q, numSkewers) 7 | % Inputs 8 | % M - 2d matrix of HSI data (p x N) 9 | % q - Number of endmembers to find 10 | % numSkewers - Number of "skewer" vectors to project data onto. 11 | % Outputs 12 | % U - Recovered endmembers (p x N) 13 | 14 | [p, N] = size(M); 15 | M_orig = M; 16 | 17 | % Remove data mean 18 | u = mean(M,2); 19 | M = M - repmat(u, 1, N); 20 | 21 | % Generate skewers 22 | skewers = randn(p, numSkewers); 23 | 24 | votes = zeros(N, 1); 25 | for kk=1:numSkewers 26 | % Project all the data onto a skewer 27 | tmp = abs(skewers(:,kk).'*M); 28 | [val, idx] = max(tmp); 29 | votes(idx) = votes(idx) + 1; 30 | end 31 | 32 | [val, idx] = sort(votes, 'descend'); 33 | U = M_orig(:, idx(1:q)); 34 | 35 | 36 | -------------------------------------------------------------------------------- /functions/hyperReadAsd.m: -------------------------------------------------------------------------------- 1 | function [measuredSpectrum, lambda, referenceSpectrum] = hyperReadAsd(filename) 2 | % HYPERREADASD Reads spectra from an ASD Fieldspec spectrometer (e.g. .asd) 3 | % Reads in the measured and reference spectra from an ASD Fieldspec 4 | % spectrometer. If two output arguments are specified, hyperReadAsd assumes 5 | % the file contains reflectance. If three output arguments are specified, 6 | % hyperReadAsd assumes the file contains measured and reference spectra 7 | % in units of digital number (DN). 8 | % 9 | % Usage 10 | % [measuredSpectrum, lambda] = hyperReadAsd(filename) 11 | % [measuredSpectrum, lambda, referenceSpectrum] = hyperReadAsd(filename) 12 | % Inputs 13 | % filename - input filename (.asd) 14 | % Outputs 15 | % measuredSpectrum - measured spectrum of material (2151 x 1) 16 | % lambda - wavelenghts of spectra (2151 x 1) 17 | % referenceSpectrum (optional) - reference spectrum ("white" spectrum) 18 | % 19 | % Notes 20 | % Reflectance can be obtained by: 21 | % reflectance = measuredSpectrum./referenceSpectrum; 22 | % 23 | % Author 24 | % Luca Innocenti 25 | % 26 | % References 27 | % None 28 | 29 | % Open the file 30 | fid = fopen(filename, 'r'); 31 | 32 | if (2 == nargout) 33 | fseek(fid,484,'bof'); 34 | measuredSpectrum = zeros(2151,1); 35 | lambda = zeros(2151,1); 36 | for i=1:2151, 37 | lambda(i) = 349 + i; 38 | measuredSpectrum(i) = fread(fid,1,'single'); 39 | end 40 | fclose(fid); 41 | return; 42 | end 43 | 44 | lungh_nota = 0; 45 | fseek(fid, 0, 'bof'); 46 | % Get factory name 47 | nome_ditta = char(fread(fid, 3, 'uint8')); %Factory Name 48 | % Get note 49 | note = char(fread(fid,157,'uint8')); 50 | 51 | % count the note length string 52 | tt = isstrprop(note,'alphanum'); 53 | for f=1:157, 54 | if tt(f) == 1 55 | lungh_nota = f; 56 | f = 157; 57 | end 58 | end 59 | 60 | %Extract Metadata from header file 61 | %Not needed for spectrum 62 | 63 | %Time of acquisition 64 | fseek(fid, 160, 'bof'); 65 | sec_acq = fread(fid,1,'uint8'); %seconds 66 | fseek(fid, 162, 'bof'); 67 | minsec_acq = fread(fid,1,'uint8'); %minutes 68 | fseek(fid, 164, 'bof'); 69 | ora_acq = fread(fid,1,'uint8'); %hours 70 | fseek(fid, 166, 'bof'); 71 | giorno_acq = fread(fid,1,'uint8'); %day 72 | fseek(fid, 168, 'bof'); 73 | mese_acq = fread(fid,1,'uint8'); %month 74 | fseek(fid, 170, 'bof'); 75 | anno_acq = fread(fid,1,'uint8'); %years from 1900 76 | fseek(fid, 172, 'bof'); 77 | wday_acq = fread(fid,1,'uint8'); 78 | fseek(fid, 174, 'bof'); 79 | wdayy_acq = fread(fid,1,'uint16'); 80 | fseek(fid, 178, 'bof'); 81 | ver_programma = fread(fid,1,'uint8'); %software version 82 | fseek(fid, 179, 'bof'); 83 | ver_file = fread(fid,1,'uint8'); %file version 84 | 85 | %Data acquisition metadata 86 | fseek(fid, 180, 'bof'); 87 | itime = fread(fid,1,'uint8'); 88 | fseek(fid, 181, 'bof'); 89 | dc_corr = fread(fid,1,'uint8'); 90 | fseek(fid, 182, 'bof'); 91 | dc_time = fread(fid,1,'uint32'); 92 | data_type = fread(fid,1,'uint8'); 93 | ref_time = fread(fid,1,'uint32'); 94 | ch1_wavel = fread(fid,1,'uint8'); 95 | wavel_step = fread(fid,1,'uint8'); 96 | data_format = fread(fid,1,'uint8'); 97 | old_dc_count = fread(fid,1,'uint8'); 98 | old_ref_count = fread(fid,1,'uint8'); 99 | old_sample_count = fread(fid,1,'uint8'); 100 | application = fread(fid,1,'uint8'); 101 | channels = fread(fid,1,'uint8'); 102 | fseek(fid, 425, 'bof'); 103 | dc_count = fread(fid,1,'uint16'); 104 | white_count = fread(fid,1,'uint16'); 105 | fseek(fid, 431, 'bof'); 106 | instrument_type = fread(fid,1,'uint8'); 107 | fseek(fid, 390, 'bof'); 108 | integration_time = fread(fid,1,'uint16'); 109 | fo = fread(fid,1,'uint16'); 110 | dc_correction_value = fread(fid,1,'uint16'); 111 | fseek(fid, 398, 'bof'); 112 | calibration = fread(fid,1,'uint16'); 113 | 114 | %Spectrum 115 | referenceSpectrum = zeros(2151,1); 116 | measuredSpectrum = zeros(2151,1); 117 | lambda = zeros(2151,1); 118 | 119 | for x=1:2151, 120 | lambda(x) = 349 + x; 121 | end 122 | 123 | fseek(fid, 484, 'bof'); 124 | for i = 1:2151, 125 | measuredSpectrum(i) = fread(fid,1,'double'); 126 | 127 | end 128 | 129 | fseek(fid, 17712+lungh_nota, 'bof'); 130 | for i = 1:2151, 131 | referenceSpectrum(i) = fread(fid,1,'double'); 132 | end 133 | 134 | % Test Fixture 135 | % plot(lambda,referenceSpectrum) 136 | % title ('Digital Number White Reference'); 137 | % xlabel('Lambda (nm)'); 138 | % ylabel('Digital Number'); 139 | % axis([350,2500,0,max(referenceSpectrum)]) 140 | % 141 | % 142 | % figure 143 | % plot(lambda,measuredSpectrum) 144 | % title ('Digital Number Sample'); 145 | % xlabel('Lambda (nm)'); 146 | % ylabel('Digital Number'); 147 | % 148 | % axis([350,2500,0,max(measuredSpectrum)]) 149 | % 150 | % reflectance = measuredSpectrum./referenceSpectrum; 151 | % 152 | % figure 153 | % plot(lambda, reflectance) 154 | % title ('Reflectance'); 155 | % xlabel('Lambda (nm)'); 156 | % ylabel('Reflectance'); 157 | % 158 | % axis([350,2500,0,1]); 159 | 160 | fclose(fid); 161 | -------------------------------------------------------------------------------- /functions/hyperReadAvirisRfl.m: -------------------------------------------------------------------------------- 1 | function [ M, wavelengths_nm ] = hyperReadAvirisRfl(filename, height, width, bands ) 2 | %HYPERREADAVIRISRFL Reads AVIRIS generated reflectance and .spc files. 3 | % This function reads AVIRIS .rfl, refelctance data, files. Optionally, it 4 | % reads in the corresponding .spc file to obtain the the wavelengths observed 5 | % by the sensor. 6 | % 7 | % Usage 8 | % [M, wavelengths_nm] = hyperReadAvirisRfl(filename, height, width, bands) 9 | % Intput 10 | % filename - filename image filename 11 | % height - vector of height range 12 | % width - vector of width range 13 | % bands - vector of band range 14 | % Output 15 | % M - reflectance data 16 | % wavelengths_nm - Wavelengths of reflectance data in nm. 17 | % 18 | % Format of the .rfl is below. Taken from the AVIRIS readme file. 19 | % 20 | % *.rfl AVIRIS INVERTED REFLECTANCE IMAGE DATA 21 | % 22 | % Contents: AVIRIS inverted reflectance data multipled by 10000 and stored as 23 | % 16-bit integers. 24 | % File type: BINARY 16-bit signed integer IEEE. 25 | % Units: 10000 times reflectance factor 26 | % Format: Band interleaved by pixel (channel, sample, line) with dimensions 27 | % (224, 614, 512). The last scene may be less than 512. To 28 | % calculate the number of lines divide the file size by 275,072 29 | % bytes per line. 30 | % 31 | % Example: 32 | % [img, lambda]= readAvirisRfl('f970620t01p02_r03_sc02.a.rfl', [1 100], [1 614], [1 224]); 33 | % Reads in all bands and rows of reflectance data from scanlines 1 to 100. 34 | % 35 | % Copyright (C) 2007 Isaac Gerg. All rights reserved. 36 | 37 | % Extract root filename. 38 | [shortFilename, pth] = findLast(filename, filesep); 39 | if (pth > 1) 40 | filePath = filename(1:pth); 41 | else 42 | filePath = ''; 43 | end 44 | [tmp, pos] = findLast(shortFilename, '.'); 45 | if (pos > 1) 46 | rootFilename = shortFilename(1:pos-1); 47 | else 48 | rootFilename = shortFilename; 49 | end 50 | [tmp, pth] = findLast(rootFilename, '_'); 51 | rootFilename = rootFilename(1:pth-1); 52 | 53 | % Parse .spc file 54 | if (nargout==2) 55 | spcFilename = sprintf('%s%s%s', filePath, rootFilename, '.a.spc'); 56 | wavelengths_nm = hyperReadAvirisSpc(spcFilename); 57 | end 58 | 59 | % Read in the reflectance data. 60 | fid = fopen(filename, 'r', 'ieee-be'); 61 | data_type = 'int16'; 62 | interleave = 'bip'; 63 | M = multibandread(filename, [512 614 224], data_type, 0, interleave, 'ieee-be',... 64 | {'Row', 'Range', [height]}, {'Column', 'Range', [width]}, ... 65 | {'Band', 'Range', [bands]} ); 66 | 67 | % Normalize to proper reflectance units. 68 | M = M ./ 10e3; 69 | 70 | return; 71 | 72 | 73 | %------------------------------------------------------------------------------- 74 | function [answer, pos] = findLast(str, char) 75 | slashes = find(str == char); 76 | if (length(slashes) > 0) 77 | lastSlash = slashes(end); 78 | else 79 | lastSlash = 0; 80 | end 81 | pos = lastSlash; 82 | answer = str(lastSlash+1:end); 83 | return; 84 | %------------------------------------------------------------------------------- 85 | -------------------------------------------------------------------------------- /functions/hyperReadAvirisSpc.m: -------------------------------------------------------------------------------- 1 | function [lambda] = hyperReadAvirisSpc(filename) 2 | %HYPERREADAVIRISSPC Reads AVIRIS .spc files. 3 | % hyperReadAvirisSpc reads AVIRIS files containing information about the 4 | % wavelengths sampled during a collect with the AVIRIS sensor. 5 | % 6 | % Usage 7 | % [lambda] = hyperReadAvirisSpc(filename) 8 | % Input 9 | % filename - input filename of .spc file. 10 | % Output 11 | % lambda - wavelengths contained in .spc file. 12 | 13 | 14 | fid = fopen(filename, 'r'); 15 | 16 | i = 1; 17 | done = false; 18 | while not(done) 19 | txt = fgetl(fid); 20 | if (txt == -1) 21 | break; 22 | end 23 | a = sscanf(txt, '%g %g %g %g %g'); 24 | lambda(i) = a(1); 25 | i = i+1; 26 | end 27 | return; 28 | -------------------------------------------------------------------------------- /functions/hyperReadSpecpr.m: -------------------------------------------------------------------------------- 1 | function [ records, spectra, rawSpectra ] = hyperReadSpecpr( filename ) 2 | %HYPERREADSPECPR Reads USGS Specpr files. 3 | % hyperReadSpecpr reads USGS Specpr files. 4 | % 5 | % Usage 6 | % [ records, spectra, rawSpectra ] = hyperReadSpecpr( filename ) 7 | % Inputs 8 | % filename - Input filename 9 | % Outputs 10 | % records - Individual records 11 | % spectra - The spectra post-processed 12 | % rawSpectra - The raw spectra 13 | % 14 | % References 15 | % http://speclab.cr.usgs.gov/specpr-format.html. 16 | dbstop if error; 17 | f = fopen(filename, 'r'); 18 | if (f == -1) 19 | error(sprintf('Failed to open file: %s'), filename); 20 | end 21 | 22 | % Ignore the first record. 23 | r = uint32(fread(f, 1536, 'uint8')); 24 | 25 | firstTime = 1; 26 | records = {}; 27 | spectra = []; 28 | rawSpectra = {}; 29 | numRawSpectra = 0; 30 | numRecords = 0; 31 | 32 | done = 0; 33 | while (not(done)) 34 | r = uint32(fread(f, 1536/4, 'uint32', 'ieee-be')); 35 | if (length(r) == 0) 36 | break; 37 | end 38 | numRecords 39 | r = swapbytes(r); 40 | r = typecast(r, 'uint8'); 41 | % First two bits of file. I am making this verbose here so it is clear what I 42 | % am doing. 43 | firstTwoBits = dec2bin(bitand(r(4), 3)); 44 | 45 | % Parse first two bits. 46 | if (firstTwoBits == '10') 47 | % This is a text record. Skip. 48 | numRecords = numRecords + 1; 49 | elseif (firstTwoBits == '0') 50 | % This is an actual (initial) data record. 51 | if (not(firstTime)) 52 | numRecords = numRecords+1; 53 | records{record.irecno} = record; 54 | end 55 | record = []; 56 | data = []; 57 | firstTime = 0; 58 | iband = int32(zeros(2, 1)); 59 | record.ititl = char(r(5:44)).'; 60 | record.usernm = char(r(45:52)).'; 61 | iscta = typecast(r(53:56), 'int32'); 62 | isctb = typecast(r(57:60), 'int32'); 63 | jdatea = typecast(r(61:64), 'int32'); 64 | jdateb = typecast(r(65:68), 'int32'); 65 | istb = typecast(r(69:72), 'int32'); 66 | isra = typecast(r(73:76), 'int32'); 67 | isdec = typecast(r(77:80), 'int32'); 68 | record.itchan = swapbytes(typecast(r(81:84), 'int32')); 69 | irmas = typecast(r(85:88), 'int32'); 70 | revs = typecast(r(89:92), 'int32'); 71 | iband(1) = typecast(r(93:96), 'int32'); 72 | iband(2) = typecast(r(97:100), 'int32'); 73 | record.irwav = swapbytes(typecast(r(101:104), 'int32')); 74 | record.irespt = swapbytes(typecast(r(105:108), 'int32')); 75 | record.irecno = swapbytes(typecast(r(109:112), 'int32')); 76 | itpntr = typecast(r(113:116), 'int32'); 77 | ihist = char(r(117:176)).'; 78 | mhist = char(r(177:472)).'; 79 | nruns = typecast(r(473:476), 'int32'); 80 | siangl = typecast(r(477:480), 'int32'); 81 | seangl = typecast(r(481:484), 'int32'); 82 | sphase = typecast(r(485:488), 'int32'); 83 | iwtrns = typecast(r(489:492), 'int32'); 84 | itimch = typecast(r(493:496), 'int32'); 85 | xnrm = typecast(r(497:500), 'int32'); 86 | scatim = typecast(r(501:504), 'int32'); 87 | timint = typecast(r(505:508), 'int32'); 88 | tempd = typecast(r(509:512), 'int32'); 89 | data = swapbytes(typecast(r(513:1536), 'single')); 90 | % Remove null data samples. Set to zero instead of -1.23e34. 91 | data(find(data < -1e34)) = 0; 92 | record.data = data; 93 | elseif (firstTwoBits == '1') 94 | % Continuation of data values. 95 | cData = swapbytes(typecast(r(5:1536), 'single')); 96 | cData(find(cData < -1e34)) = 0; 97 | data = [data; cData]; 98 | record.data = data; 99 | else 100 | numRecords = numRecords + 1; 101 | end 102 | end 103 | 104 | % Convert to an array of signatures. 105 | % Resample to model AVIRIS sensor 106 | high = 2.40; 107 | low = 0.4; 108 | numBands = 224; 109 | %d.data = sortrows(d.data, 1); 110 | %[q, w, r ]= unique(d.data(:,1)); 111 | %d.data = d.data(w, :); 112 | %lambda = d.data(:, 1); 113 | %reflectance = d.data(:, 2); 114 | s = length(records); 115 | numSpectra = 0; 116 | for q=1:s 117 | if (isempty(records{q})) 118 | continue; 119 | end 120 | if (records{q}.irwav == 0) 121 | continue; 122 | end 123 | 124 | if (not(isempty(strfind(records{q}.ititl, 'error')))) 125 | continue; 126 | end 127 | if (not(isempty(strfind(records{q}.ititl, 'Error')))) 128 | continue; 129 | end 130 | if (not(isempty(strfind(records{q}.ititl, 'Bandpass')))) 131 | continue; 132 | end 133 | if (not(isempty(strfind(records{q}.ititl, 'Wavelengths')))) 134 | continue; 135 | end 136 | % Find wavelengths 137 | if (isempty(records{records{q}.irwav})) 138 | continue; 139 | end 140 | lambdas = records{records{q}.irwav}.data; 141 | spectrum = records{q}.data; 142 | if (length(lambdas) ~= length(spectrum)) 143 | fprintf('Error %d !!!\n', q); 144 | continue; 145 | end 146 | numRawSpectra = numRawSpectra + 1; 147 | rawSpectra{numRawSpectra}.name = records{q}.ititl; 148 | rawSpectra{numRawSpectra}.wavelengths = lambdas; 149 | rawSpectra{numRawSpectra}.reflectance = spectrum; 150 | goodIdx = find(lambdas > 0); 151 | lambdas = lambdas(goodIdx); 152 | spectrum = spectrum(goodIdx); 153 | % Ensure we have proper lower and upper bounds. 154 | if (lambdas(1) > low) 155 | %fprintf('Bad file: Lower wavelength value missing.'); 156 | lambdas = [low; lambdas]; 157 | spectrum = [spectrum(1); spectrum]; 158 | end 159 | if (lambdas(end) < high) 160 | %fprintf('Bad file: Upper wavelength value missing.\n'); 161 | %d.data = []; 162 | %fclose(fid); 163 | %return; 164 | lambdas = [lambdas; high]; 165 | spectrum = [spectrum; spectrum(end)]; 166 | end 167 | % Resample 168 | records{q}.ititl 169 | ts = timeseries(spectrum, lambdas); 170 | inc = (high-low) / (numBands-1); 171 | c = resample(ts, [low:inc:high], 'zoh'); 172 | numSpectra = numSpectra + 1; 173 | spectra(numSpectra).data = [c.time c.data [1:numBands].']; 174 | spectra(numSpectra).name = records{q}.ititl; 175 | end 176 | 177 | return; -------------------------------------------------------------------------------- /functions/hyperResample.m: -------------------------------------------------------------------------------- 1 | function [ M_resampled ] = hyperResample( M, currentWaveLengths, desiredWaveLengths ) 2 | %HYPERRESAMPLE Resamples hyperspectral data to specified wavelenghts 3 | % hyperResample resamples hyperspectral data with specified wavelengths 4 | % to a new set of wavelengths. 5 | % 6 | % Usage 7 | % [ output ] = hyperResample( M, currentWaveLengths, desiredWaveLengths ) 8 | % Inputs 9 | % M - HSI data (p x N) 10 | % currentWavelengths - Wavelengths of M. (p x 1) 11 | % desiredWavelengths - Desired wavelengths of M. 12 | % Output 13 | % M_resampled - Resampled version of M 14 | 15 | 16 | numDim = ndims(M); 17 | 18 | if (numDim == 3) 19 | h = size(M, 1); 20 | w = size(M, 2); 21 | numBands = size(M, 3); 22 | %M = reshape(M, w*h, numBands).'; 23 | M = hyperConvert2d(M); 24 | elseif (numDim == 2) 25 | w = size(M, 2); 26 | numBands = size(M, 1); 27 | end 28 | 29 | % Determine if desiredWaveLengths is a subrage of currentWaveLengths 30 | if (min(desiredWaveLengths) < min(currentWaveLengths)) 31 | sprintf('Desired wavelenths outside of lower range.\n'); 32 | return; 33 | end 34 | if (max(desiredWaveLengths) > max(currentWaveLengths)) 35 | sprintf('Desired wavelenths outside of upper range.\n'); 36 | return; 37 | end 38 | 39 | % Resample to desired bands. 40 | ts = timeseries(M, currentWaveLengths); 41 | ts = resample(ts, desiredWaveLengths, 'linear'); 42 | M_resampled = ts.data; 43 | clear tmp; 44 | clear M; 45 | 46 | if (numDim == 3) 47 | %output = reshape(output, h, w, length(desiredWaveLengths)); 48 | M_resampled = hyperConvert3d(M, w, h, length(desiredWaveLengths)); 49 | end 50 | -------------------------------------------------------------------------------- /functions/hyperRmf.m: -------------------------------------------------------------------------------- 1 | function [results] = hyperRmf(M, t, windowSize, algorithm) 2 | % HYPERPLMF Performs the regularlzed matched filter (RMF) target detection algorithm 3 | % Performs the regularized matched filter (PLMF) target detection algorithm. 4 | % 5 | % Usage 6 | % [results] = hyperRmf(M, target, windodwSize) 7 | % Inputs 8 | % M - dd matrix of HSI data (m x n x p) 9 | % t - target of interest (p x 1) 10 | % windowSize - window size designating local pixel region (scalar) 11 | % algorithm - 'sum' designates sum of local and global eigenvalues. 12 | % 'meanLocal' desiginates to use the mean of the local 13 | % eigenvalues. 14 | % 'meanGlobalLocal' designates to use the mean of the local 15 | % and global eigenvalues. 16 | % Outputs 17 | % results - vector of detector output (m x n) 18 | % 19 | % References 20 | % Sofa, Geva, Rotman. "Improved covariance matrices for point target detection in hyperspectral 21 | % data." IEEE International Conference on Microwaves, Communications, Antennas and Electronics 22 | % Systems, 2009. COMCAS 2009. 23 | 24 | % windowSize must be odd number 25 | if ~mod(windowSize,2) 26 | error('windowSize must be an odd number.') 27 | end 28 | 29 | if (length(size(M)) ~= 3) 30 | error('M must be 3-dimensional matrix.') 31 | end 32 | 33 | if (nargin ~= 4) 34 | error('Not enough input arguments'); 35 | end 36 | 37 | [h,w,p] = size(M); 38 | N = h*w; 39 | 40 | % Remove mean from the target 41 | M = hyperConvert2d(M); 42 | u = mean(M.').'; 43 | 44 | [Mpca,V,lambdaGlobal] = hyperPct(M,p); 45 | t_pct = V.'*(t-u); 46 | 47 | % Create map to get neighbors 48 | map = 1:N; 49 | map = reshape(map,h,w); 50 | 51 | R_hat = hyperCov(Mpca); 52 | G = inv(R_hat); 53 | 54 | results = zeros(h,w); 55 | s = floor(windowSize/2)+1; 56 | for k=s:(h-s) 57 | for kk=s:(w-s) 58 | midIdx = map(k,kk); 59 | neighborhoodIdx = map((k-s+1):(k+s-1),(kk-s+1):(kk+s-1)); 60 | 61 | Mlocal = M(:,neighborhoodIdx(:)); 62 | [~,~,lambdaLocal] = hyperPct(Mlocal,p); 63 | 64 | y = Mpca(:,midIdx); 65 | 66 | switch algorithm 67 | case 'sum' 68 | results(k,kk) = sum((t_pct.*y)./(lambdaLocal+lambdaGlobal)); 69 | case 'meanLocal' 70 | results(k,kk) = sum((t_pct.*y)/mean(lambdaLocal(:))); 71 | case 'meanGlobalLocal' 72 | results(k,kk) = sum((t_pct.*y)./((lambdaLocal+lambdaGlobal)/2)); 73 | otherwise 74 | error('Algorithm option unknown.'); 75 | end 76 | end 77 | end 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /functions/hyperRoc.m: -------------------------------------------------------------------------------- 1 | function [pd,fa] = hyperRoc(x) 2 | 3 | x = x(:); 4 | 5 | numTs = 100; 6 | pd = linspace(0,1,numTs); 7 | for k=1:numTs 8 | fa(k) = sum(x>=pd(k)); 9 | end 10 | 11 | N = length(x); 12 | fa = fa./N; 13 | pd = 1-pd; -------------------------------------------------------------------------------- /functions/hyperRxDetector.m: -------------------------------------------------------------------------------- 1 | function [result, sigma, sigmaInv] = hyperRxDetector(M) 2 | %HYPERRX RX anomaly detector 3 | % hyperRxDetector performs the RX anomaly detector 4 | % 5 | % Usage 6 | % [result] = hyperRxDetector(M) 7 | % Inputs 8 | % M - 2D data matrix (p x N) 9 | % Outputs 10 | % result - Detector output (1 x N) 11 | % sigma - Covariance matrix (p x p) 12 | % sigmaInv - Inverse of covariance matrix (p x p) 13 | 14 | % Remove the data mean 15 | [p, N] = size(M); 16 | mMean = mean(M, 2); 17 | M = M - repmat(mMean, 1, N); 18 | 19 | % Compute covariance matrix 20 | sigma = hyperCov(M); 21 | sigmaInv = inv(sigma); 22 | 23 | result = zeros(N, 1); 24 | for i=1:N 25 | result(i) = M(:,i).'*sigmaInv*M(:,i); 26 | end 27 | result = abs(result); 28 | 29 | return; -------------------------------------------------------------------------------- /functions/hyperSam.m: -------------------------------------------------------------------------------- 1 | function [errRadians] = hyperSam(a, b) 2 | % HYPERSAM Computes the spectral angle error (in radians) between two 3 | % vectors, or between a vector and every column or row of a matrix 4 | % 5 | % Usage 6 | % [errRadians] = hyperSam(a, b) 7 | % [errRadians] = hyperSam(A, b) 8 | % [errRadians] = hyperSam(a, B) 9 | % Inputs 10 | % a - vector, (px1) 11 | % b - vector, (px1) 12 | % A - matrix, (pxN) 13 | % B - matrix, (pxN) 14 | % Outputs 15 | % errRadians - angle between vectors a and b in radians, (1xN) 16 | 17 | % Check dimensions 18 | if ~any(size(a)==size(b)), 19 | error('Incorrect dimensions provided.'); 20 | elseif ~any([isvector(a),isvector(b)]), 21 | error('Incorrect inputs. At least one input must be a vector.'); 22 | end 23 | 24 | % Turn row vectors to column vectors if necessary 25 | if isrow(a), a=a'; end 26 | if isrow(b), b=b'; end 27 | 28 | % Get dimensions 29 | p1 = size(a,1); 30 | p2 = size(b,1); 31 | 32 | % Transpose matrix if necessary 33 | if ~isvector(a), % a is a matrix, b is a vector 34 | if p1~=p2, a=a'; end 35 | errRadians = getSam(a,b); 36 | return 37 | 38 | elseif ~isvector(b) % b is a matrix, a is a vector 39 | if p2~=p1, b=b'; end 40 | errRadians = getSam(b,a); 41 | return 42 | 43 | elseif all([isvector(a),isvector(b)]) % a and b are both vectors 44 | errRadians = getSam(a,b); 45 | return 46 | 47 | else 48 | error('Unknown error. See help hyperSam.') 49 | end 50 | 51 | 52 | function errRadians = getSam(a, b) 53 | % GETSAM computes the spectral angle error between the vector b and 54 | % every column of matrix a (or just the first column, if a is a vector) 55 | 56 | [~,N] = size(a); 57 | errRadians = zeros(1,N); 58 | 59 | for k=1:N 60 | tmp = a(:,k); 61 | errRadians(k) = acos(dot(tmp, b)/ (norm(b) * norm(tmp))); 62 | end 63 | -------------------------------------------------------------------------------- /functions/hyperSaveFigure.m: -------------------------------------------------------------------------------- 1 | function hyperSaveFigure(h, filename, fmt) 2 | % HYPERSAVEFIGURE Writes a figure to disk as an image. 3 | % 4 | % Usage 5 | % hyperSaveFigure(gcf, 'filename.png'); 6 | % Inputs 7 | % h - Handle to figure 8 | % filename - Filename for output file. Extension determines image type. 9 | % fmt - Format of output image. 'wysiwyg' or wysiwyp' for 'what you see 10 | % is what you get' and what 'you see is what you print' respectively. 11 | % Outputs 12 | % none 13 | 14 | if (nargin == 2) 15 | fmt = 'wysiwyg'; 16 | end 17 | 18 | fmt = lower(fmt); 19 | 20 | if strcmp(fmt, 'wysiwyp') 21 | saveas(h, filename); 22 | elseif strcmp(fmt, 'wysiwyg') 23 | set(h, 'Color',[1 1 1]); 24 | frame = getframe(h); 25 | [X,map] = frame2im(frame); 26 | imwrite(X ,filename); 27 | else 28 | error('Bad format string specified.'); 29 | end 30 | %print(h, '-dpng', filename); -------------------------------------------------------------------------------- /functions/hyperSid.m: -------------------------------------------------------------------------------- 1 | function [ err ] = hyperSid( M, b ) 2 | % HYPERSID Computes the spectral information divergence between two vectors 3 | % 4 | % Usage 5 | % [err] = hyperSid(a, b) 6 | % Inputs 7 | % M - 2d matrix of data (p x N) 8 | % b - vector 2 9 | % Outputs 10 | % err - spectral information divergence between M and b 11 | % 12 | % References 13 | % C.-I Chang, "Spectral information divergence for hyperspectral image 14 | % analysis," IEEE 1999 International Geoscience and Remote Sensing Symp., 15 | % Hamburg, Germany, pp. 509-511, 28 June-2 July, 1999. 16 | 17 | [p, N] = size(M); 18 | err = zeros(1, N); 19 | for k=1:N 20 | err(k) = abs(sum(M(:,k).*log(M(:,k)./b)) + sum(b.*log(b./M(:,k)))); 21 | end 22 | err = 1./(err+eps); 23 | -------------------------------------------------------------------------------- /functions/hyperSignedAce.m: -------------------------------------------------------------------------------- 1 | function [results] = hyperSignedAce(M, t) 2 | % TODO 3 | % HYPERACE Performs the adaptive cosin/coherent estimator algorithm 4 | % Performs the adaptive cosin/coherent estimator algorithm for target 5 | % detection. 6 | % 7 | % Usage 8 | % [results] = hyperAce(M, S) 9 | % Inputs 10 | % M - 2d matrix of HSI data (p x N) 11 | % S - 2d matrix of target endmembers (p x q) 12 | % Outputs 13 | % results - vector of detector output (N x 1) 14 | % 15 | % References 16 | % X Jin, S Paswater, H Cline. "A Comparative Study of Target Detection 17 | % Algorithms for Hyperspectral Imagery." SPIE Algorithms and Technologies 18 | % for Multispectral, Hyperspectral, and Ultraspectral Imagery XV. Vol 19 | % 7334. 2009. 20 | 21 | 22 | [p, N] = size(M); 23 | % Remove mean from data 24 | u = mean(M.').'; 25 | M = M - repmat(u, 1, N); 26 | t = t - u; 27 | 28 | R_hat = hyperCov(M); 29 | G = inv(R_hat); 30 | 31 | results = zeros(1, N); 32 | tmp = (t'*G*t); 33 | for k=1:N 34 | x = M(:,k); 35 | results(k) = ((x'*G*t)*abs(x'*G*t)) / (tmp*(x'*G*x)); 36 | end 37 | -------------------------------------------------------------------------------- /functions/hyperUcls.m: -------------------------------------------------------------------------------- 1 | function [ W ] = hyperUcls( M, U ) 2 | %HYPERUCLS Unconstrained least squares 3 | % hyperUcls performs unconstrained least squares abundance estimation 4 | % 5 | % Usage 6 | % [ W ] = hyperUcls( M, U ) 7 | % Inputs 8 | % M - 2D data matrix (p x N) 9 | % U - 2D matrix of endmembers (p x q) 10 | % Outputs 11 | % W - Abundance maps (q x N) 12 | 13 | if (ndims(M) ~= 2) 14 | error('M must be a p x N matrix.'); 15 | end 16 | if (ndims(U) ~= 2) 17 | error('M must be a p x q matrix.'); 18 | end 19 | 20 | [p1, N] = size(M); 21 | [p2, q] = size(U); 22 | if (p1 ~= p2) 23 | error('M and U must have the same number of spectral bands.'); 24 | end 25 | 26 | Minv = pinv(U); 27 | W = zeros(q, N); 28 | for n1 = 1:N 29 | W(:, n1) = Minv*M(:, n1); 30 | end 31 | 32 | return; 33 | -------------------------------------------------------------------------------- /functions/hyperVca.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidkun/HyperSpectralToolbox/9dc222bb9c863e19b8a3f1946e947125dacc49cb/functions/hyperVca.m -------------------------------------------------------------------------------- /functions/hyperWhiten.m: -------------------------------------------------------------------------------- 1 | function [X_whitened, Aw, u] = hyperWhiten( X ) 2 | %HYPERWHITEN Whitens a data matrix 3 | % hyperWhiten whitens a data matrix by performing a transform upon it so 4 | % that diagonals of its covariance matrix are all unity. Whitening is 5 | % simply a coordinate rotation followed by a scaling factor. 6 | % 7 | % Usage 8 | % [X_whitened] = hyperWhiten( X ) 9 | % Inputs 10 | % X - 2D matrix (p x N) 11 | % Outputs 12 | % X_whitened - 2D matrix (p x N), now whitened 13 | % Aw - 2D whitening matrix. 14 | % u - Vector of data mean 15 | % 16 | % References 17 | % http://en.wikipedia.org/wiki/Whitening_transformation 18 | 19 | [p, N] = size(X); 20 | 21 | % Remove the data mean 22 | u = mean(X.').'; 23 | X = X - repmat(u, 1, N); 24 | 25 | % Compute covariance matrix 26 | sigma = hyperCov(X); 27 | % Compute SVD of covariance matrix to get eigenvectors/values 28 | % The columns of V are the eigenvectors of sigma. 29 | % Assume S is positive and U encodes the axis reflection information 30 | [U,S,V] = svd(sigma); 31 | Aw = inv(sqrt(S))* V.'; 32 | % Whiten the data 33 | X_whitened = Aw * X; 34 | 35 | return; -------------------------------------------------------------------------------- /newFunctions/README.md: -------------------------------------------------------------------------------- 1 | ## New Functions ## 2 | 3 | These are some of the functions I am working on adding to the Toolbox. Depending on the rate of progress, I hope that this list will continue to grow. Crossed out functions are done. 4 | 5 | ### Endmember Determination (Extraction) Algorithms ### 6 | 7 | * ~~Automated Morphological Endmember Extraction (AMEE)~~ 8 | * ~~Alternating Volume Maximization (AVMAX)~~ 9 | * ~~N-FINDR~~ 10 | * Random N-FINDR (RN-FINDR) 11 | 12 | ### Other ### 13 | * ~~Demo file (guide) for using these functions~~ 14 | * ~~Truecolor composite generation from RGB spectral bands~~ 15 | -------------------------------------------------------------------------------- /newFunctions/hyperAmee.m: -------------------------------------------------------------------------------- 1 | function [U] = hyperAmee(M, q, Smin, Smax, Imax) 2 | % HYPERAMEE Performs the AMEE algorithm to find q endmembers 3 | % Performs the Automated Morphological Endmember Extraction (AMEE) 4 | % algorithm to find q endmembers. If only M is 5 | % given as input, this function calls hyperHfcVd to estimate the number 6 | % of endmembers (q) and then hyperPct to reduce dimensionality to (q-1). 7 | % 8 | % Usage 9 | % [U] = hyperAmee(M, q, Smin) 10 | % [U] = hyperAmee(M, q, Smin, Smax) 11 | % [U] = hyperAmee(M, q, Smin, Smax, Imax) 12 | % Inputs 13 | % M - 3d matrix of HSI data (m x n x p) 14 | % q - Number of endmembers to find 15 | % Smin - minimum kernel size (Smin x Smin) 16 | % Smax - maximum kernel size (Smax x Smax) 17 | % Imax - maximum iterations 18 | % Outputs 19 | % U - Recovered endmembers (p x q) 20 | % 21 | % References 22 | % Plaza, Antonio, et al. "Spatial/spectral endmember extraction 23 | % by multidimensional morphological operations." Geoscience and 24 | % Remote Sensing, IEEE Transactions on 40.9 (2002): 2025-2041. 25 | 26 | % Error trapping 27 | if nargin < 3 || nargin > 5 28 | help hyperAmee 29 | error('Not enough input arguments. See function description.') 30 | elseif nargin == 3 31 | % i.e. Smax and Imax not given 32 | Smax = Smin; 33 | Imax = 1; 34 | elseif nargin == 4 35 | % i.e. if Imax not given 36 | if Smin <= Smax 37 | Imax = round((Smax-Smin)/2)+1; 38 | else 39 | help hyperAmee 40 | error('Smax cannot be less than Smin. See function description.') 41 | end 42 | elseif nargin == 5 43 | if Smin == Smax && Imax < 2 44 | help hyperAmee 45 | error('Cannot iterate more than once with these S limits.') 46 | elseif Imax > (Smax-Smin+1) 47 | Imax = round((Smax-Smin)/2)+1; 48 | end 49 | end 50 | 51 | if ndims(M) ~= 3 52 | error('Input image must be (m x n x p)'); 53 | else 54 | [h, w, p] = size(M); 55 | end 56 | 57 | 58 | % Build pixel vectors from M 59 | pixVec = cell(h, w); 60 | for hIter = 1:h 61 | for wIter = 1:w 62 | pixVec{hIter,wIter} = squeeze(M(hIter,wIter,:)); 63 | end 64 | end 65 | 66 | % Morphological Eccentricity Index Score (MEI) 67 | MEI = zeros(h, w); 68 | 69 | % Kernel (structuring element) 70 | for B = round(linspace(Smin, Smax, Imax)); 71 | % Create non-overlapping arrays (to reduce computational load) 72 | hArray = 1:B:h; hArray(end) = h-B+1; 73 | wArray = 1:B:w; wArray(end) = w-B+1; 74 | 75 | % Move B though all pixels in M 76 | for wPixel = wArray; 77 | for hPixel = hArray; 78 | % (hPixel,wPixel) defines the top-left pixel of the current kernel 79 | ker = pixVec(hPixel:hPixel+B-1, wPixel:wPixel+B-1); 80 | [x, y, mei] = spatialSearch( ker ); 81 | % global (x,y) from local (x,y) 82 | x = x+hPixel-1; 83 | y = y+wPixel-1; 84 | % set MEI value at max pixel location 85 | MEI(x, y) = mei; 86 | end 87 | end 88 | end 89 | 90 | % Find q largest MEI values 91 | [tmp,idx] = sort(MEI(:), 'descend'); 92 | top = idx(1:q)'; 93 | 94 | % Return endmembers 95 | U = cell2mat(pixVec(top)); 96 | 97 | end % hyperAmee function 98 | 99 | 100 | function [xMax, yMax, mei] = spatialSearch( ker ) 101 | %function [xMax, yMax, mei] = spatialSearch( ker ) 102 | % spatialSearch finds the max and min cumulative distances 103 | % between each pixel vector and its neighbors inside a kernel 104 | % of size (B x B) and computes the local MEI. 105 | 106 | if ~iscell(ker) 107 | error('ker is not a cell! See line 57 of hyperAmee.m') 108 | end 109 | 110 | B = size(ker,1); 111 | 112 | dist = zeros(B); 113 | for i = 1:B; 114 | for j = 1:B; 115 | dist(i,j) = Dist(ker{i,j}, ker); 116 | end 117 | end 118 | 119 | % Morphological erosion to find minimum pixel vector in region B 120 | [tmp,rowIdx] = min(dist); 121 | [val,colIdx] = min(tmp); 122 | xMin = rowIdx(colIdx); 123 | yMin = colIdx; 124 | 125 | % Morphological dilation to find maximum pixel vector in region B 126 | [tmp,rowIdx] = max(dist); 127 | [val,colIdx] = max(tmp); 128 | xMax = rowIdx(colIdx); 129 | yMax = colIdx; 130 | 131 | % MEI computation 132 | mei = Dist(ker{xMin, yMin}, ker{xMax, yMax}); 133 | 134 | end % spatialSearch function 135 | 136 | 137 | 138 | function dist = Dist(a, C) 139 | %function dist = Dist(a, C) 140 | % Cumulative distance measure between a pixel vector and its neighbor(s). 141 | % Plaza et al. used the Spectral Angle Mapper (SAM) measure. 142 | % 143 | % Inputs 144 | % a - pixel vector of interest (p x 1) 145 | % C - all pixels in neighborhood (or a single pixel vector) 146 | % Outpus 147 | % dist - (cumulative) SAM distance 148 | 149 | if ~iscell(C) 150 | dist = acos(dot(a,C)/(norm(a)*norm(C))); 151 | else 152 | dist = 0; 153 | for k = 1:numel(C); 154 | dist = dist + acos(dot(a,C{k})/(norm(a)*norm(C{k}))); 155 | end 156 | end 157 | 158 | end % Dist function 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /newFunctions/hyperAvmax.m: -------------------------------------------------------------------------------- 1 | function [U] = hyperAvmax(M, q) 2 | % HYPERAVMAX Performs the AVMAX algorithm 3 | % Performs the Alternating Volume Maximization (AVMAX) algorithm 4 | % to find q endmembers. If only M is given as input, this function 5 | % calls hyperHfcVd to estimate the number of endmembers (q) and 6 | % then hyperPct to reduce dimensionality to (q-1). 7 | % 8 | % Usage 9 | % [U] = hyperNfindr(M) 10 | % [U] = hyperNfindr(M, q) 11 | % Inputs 12 | % M - 2d matrix of HSI data (p x N) 13 | % q - Number of endmembers to find 14 | % -- if not given, q is obtained from hyperHfcVd(M, 10^-3) 15 | % Outputs 16 | % U - Recovered endmembers (p x q) 17 | % 18 | % References 19 | % T.H. Chan et al., "A simplex volume maximization framework 20 | % for hyperspectral endmember extraction." Geoscience and Remote 21 | % Sensing, IEEE Transactions on 49.11 (2011): 4177-4193. 22 | 23 | % Error trapping 24 | if ndims(M) ~= 2 25 | warning('WarnTests:dim', ... 26 | 'Input image must be p x N.\n',... 27 | 'Converting with hyperConvert2d.\n') 28 | M = hyperConvert2d(M); 29 | end 30 | 31 | M_orig = M; 32 | [p, N] = size(M); 33 | 34 | if nargin == 1 35 | q = hyperHfcVd(M_orig, [10^-3]); 36 | M = hyperPct(M, q-1); 37 | elseif q < p+1 38 | M = hyperPct(M, q-1); 39 | warning('WarnTests:dim', ... 40 | strcat('AVMAX requires (q-1) spectral bands.\n',... 41 | 'Performing PCA to reduce dimensionality.\n')) 42 | elseif q > p+1 43 | warning('WarnTests:dim', ... 44 | strcat('AVMAX requires (q-1) spectral bands.\n',... 45 | 'Performing PCA to reduce dimensionality.\n')) 46 | error('ErrTests:dim', ... 47 | strcat('AVMAX cannot find more than (p+1) endmembers (q),\n', ... 48 | 'where p is the number of available spectral bands.\n')) 49 | end 50 | 51 | % Initialize 52 | M = M*1e2; % Scale up reflectances to reduce numerical errors 53 | tol = 5e-5; % Convergence tolerance 54 | maxitr = 1e2; % Maximum iterations for search 55 | 56 | % Step 1 57 | U_idx = randperm(N,q); % Random endmember selection 58 | U = [M(:,U_idx); % Initialize endmember matrix 59 | ones(1,q)]; 60 | bj = zeros(q-1,1); 61 | 62 | % Step 2 63 | rho = det(U); % Initial volume 64 | 65 | % Begin search 66 | for zeta = 1:maxitr 67 | 68 | for j = 1:q 69 | % Step 3 70 | U_tmp1 = U; 71 | U_tmp1(:,j) = []; % Remove j-th column 72 | U_tmp2 = U_tmp1; 73 | for i = 1:q-1 74 | U_tmp2(i,:) = []; % Remove i-th row 75 | bj(i) = (-1)^(i+j) * det(U_tmp2); 76 | U_tmp2 = U_tmp1; % Add back i-th row 77 | end 78 | 79 | % Step 4 80 | [val,l] = max(bj.'*M); 81 | U(1:q-1,j) = M(:,l); % Update endmember matrix 82 | U_idx(j) = l; % Keep track of indices 83 | end 84 | 85 | % Step 5 86 | rho_bar = det(U); 87 | 88 | % Step 6 89 | if abs(rho_bar-rho)/rho > tol 90 | rho = rho_bar; 91 | else 92 | break 93 | end 94 | end 95 | 96 | if zeta == maxitr 97 | warning('WarnTests:maxitr', ... 98 | ['Maximum iterations reached without convergence.\n ', ... 99 | 'Convergence tolerance:\t %0.5g \n Limit reached: %0.5g \n', ... 100 | ' Iterations: %d \n'], ... 101 | tol, abs(rho_bar-rho)/rho, zeta) 102 | else 103 | fprintf('Total iterations: %d', zeta) 104 | end 105 | 106 | % Return endmembers 107 | U = M_orig(:, U_idx); 108 | -------------------------------------------------------------------------------- /newFunctions/hyperDemo2.m: -------------------------------------------------------------------------------- 1 | function hyperDemo2 2 | % HYPERDEMO2 Demonstrates new functions in the hyperspectral toolbox 3 | clear all; close all; clc; 4 | 5 | %-------------------------------------------------------------------------- 6 | % Measurements and reflectance (input) files/directory 7 | % The data files are obtained from: http://aviris.jpl.nasa.gov/data/free_data.html 8 | % (the reflectance .rar file for Cuprite) 9 | dataDir = ['~' filesep 'Downloads' filesep 'f970619t01p02r02c']; 10 | rflFile = [dataDir filesep 'f970619t01p02_r02_sc04.a.rfl']; 11 | spcFile = [dataDir filesep 'f970619t01p02_r02.a.spc']; 12 | 13 | % Results (output) directory 14 | resultsDir = '~/Dropbox/Purdue Grad/Semester 2/AAE 590/Project/Simulation/results'; 15 | if ~isdir(resultsDir) 16 | mkdir(resultsDir); 17 | end 18 | 19 | %-------------------------------------------------------------------------- 20 | % Record outputs (not including figures) 21 | diary(sprintf('%s/log.txt',resultsDir)) 22 | dnt = fix(clock); % date and time 23 | fprintf('%d/%d/%d %d:%d:%d\n\n', dnt([2,3,1,4,5,6])) 24 | 25 | fprintf(' Reading data from %s \n in the directory %s.\n', rflFile, dataDir); 26 | fprintf(' Storing results in %s directory.\n', resultsDir); 27 | 28 | %% Read in an HSI image and display one band 29 | bndnum = 120; % Band Number 30 | tmp = hyperReadAvirisSpc(spcFile); 31 | bnd = tmp(bndnum); 32 | slice = hyperReadAvirisRfl(rflFile, [1 512], [1 614], [bndnum bndnum]); 33 | figure; imagesc(slice); axis image; colormap(gray); 34 | title(['Slice of HSI, at $\lambda=$',sprintf('%5.6g nm',bnd)],... 35 | 'Interpreter', 'Latex', 'FontSize', 14); 36 | print(gcf, '-r600', '-depsc', sprintf('%s/sampleSlice', resultsDir)); 37 | 38 | %% True Color Composite 39 | rgbBands = [31,20,12]; % RGB bands (default): [665.73, 557.07, 478.17] nm 40 | tColor = hyperTruecolor(rflFile, 512, 614, 224, rgbBands, 'stretchlim'); 41 | figure; imagesc(tColor); axis image 42 | title('Cuprite, Nevada. AVIRIS 1997 data.', 'Interpreter', 'Latex', 'FontSize', 14); 43 | print(gcf, '-r600', '-depsc', sprintf('%s/truecolor', resultsDir)); 44 | 45 | %% Read part of AVIRIS reflectance data file that we will further process 46 | M = hyperReadAvirisRfl(rflFile, [1 512], [1 614], [1 224]); 47 | 48 | % Read AVIRIS .spc file 49 | lambdasNm = hyperReadAvirisSpc(spcFile); 50 | 51 | % Resample AVIRIS image 52 | [h, w, p] = size(M); 53 | M2d = hyperConvert2d(M); 54 | desiredLambdasNm = 400:(2400-400)/(224-1):2400; 55 | 56 | fprintf('Resampling M for desired wavelengths...\n'); tic; 57 | M2d = hyperResample(M2d, lambdasNm, desiredLambdasNm); 58 | et=toc; fprintf('...Done. (~%1.3g seconds)\n',et); 59 | 60 | %% Remove low SNR bands and bands affected by water absorption 61 | % Examine the spectral profile of some random pixels (targets) 62 | M = hyperConvert3d(M2d, h, w, p); 63 | ntarg = 20; % number of targets 64 | htarg = randi(h, 1, ntarg); % h position of targets 65 | wtarg = randi(w, 1, ntarg); % w position of targets 66 | targets = zeros(ntarg, p); 67 | for idx = 1:ntarg 68 | targets(idx,:) = squeeze(M(htarg(idx), wtarg(idx), :)); 69 | end 70 | 71 | figure; 72 | set(0,'Units','pixels'); scnsz = get(0,'ScreenSize'); 73 | set(gcf, 'OuterPosition',[1,1,scnsz(3)/3,scnsz(4)],'PaperPositionMode', 'auto'); 74 | subplot(211); 75 | plot(desiredLambdasNm, targets, '.'); grid on; ylim([0,0.6]); 76 | title(sprintf('(a) %d Target Signatures (All Bands)', ntarg), 'Interpreter', 'Latex', 'FontSize', 14); 77 | ax(1) = xlabel('Wavelengths [nm]'); 78 | ax(2) = ylabel('Reflectance'); 79 | set(ax, 'Interpreter', 'Latex', 'FontSize', 12); 80 | 81 | fprintf('Removing low SNR bands...\n'); 82 | % [rows,cols,vals]=find(sum(M2d,2)==0); 83 | % goodBands = [4:104 116:149 171:224]; 84 | goodBands = [4:104 116:135 137:149 174:224]; 85 | M2d = M2d(goodBands, :); 86 | p = length(goodBands); 87 | lambdasNm = desiredLambdasNm(goodBands); 88 | 89 | % Final hyperspectral data cube that will be used throughout this demo 90 | M = hyperConvert3d(M2d, h, w, p); 91 | fprintf('...Done\n'); 92 | 93 | % Plot new target signatures (only good bands now) 94 | targets = zeros(ntarg, p); 95 | for idx = 1:ntarg 96 | targets(idx,:) = squeeze(M(htarg(idx), wtarg(idx), :)); 97 | end 98 | subplot(212); plot(lambdasNm, targets, '.'); grid on; ylim([0,0.6]); 99 | title(sprintf('(b) %d Target Signatures (Good Bands)', ntarg), 'Interpreter', 'Latex', 'FontSize', 14); 100 | ax(1) = xlabel('Wavelengths [nm]'); 101 | ax(2) = ylabel('Reflectance'); 102 | set(ax, 'Interpreter', 'Latex', 'FontSize', 12); 103 | print(gcf, '-r600', '-depsc', sprintf('%s/targets_spectra', resultsDir)); 104 | 105 | %% -------------------------------------------------------------------------- 106 | % Perform various endmember determination algorithms 107 | % Estimate number of endmembers in image. 108 | % q = hyperHfcVd(M2d, [10^-3]); % doesn't work because corr(M') returns 109 | % some NaNs, which means that there's no variance in some of the bands... 110 | q = 6; % number of endmembers to find 111 | % M2dnorm = hyperNormalize(M2d); % normalized [0-1] reflectance 112 | 113 | %% PPI 114 | fprintf('Performing PPI for endmember determination...\n'); tic; 115 | Uppi = hyperPpi(M2d, q, 1000); 116 | et=toc; fprintf('...Done. (~%1.3g seconds)\n',et); 117 | 118 | % Plot endmember signatures 119 | figure; plot(lambdasNm, Uppi, '.'); grid on; 120 | title('PPI Recovered Endmembers', 'Interpreter', 'Latex', 'FontSize', 14); 121 | ax(1) = ylabel('Reflectance [0-1]'); 122 | ax(2) = xlabel('Wavelength [nm]'); 123 | set(ax, 'Interpreter', 'Latex', 'FontSize', 12); 124 | l = legend(cellstr(num2str((1:q)'))', 'Location', 'EastOutside'); 125 | a = get(l, 'children'); set(a(1:3:end), 'MarkerSize', 20); 126 | print(gcf, '-r600', '-depsc', sprintf('%s/endmmbrs-ppi', resultsDir)); 127 | 128 | %% N-FINDR 129 | fprintf('Performing N-FINDR for endmember determination...\n'); tic; 130 | Unfindr = hyperNfindr(M2d, q); 131 | et=toc; fprintf('...Done. (~%1.3g seconds)\n',et); 132 | 133 | % Plot endmember signatures 134 | figure; plot(lambdasNm, Unfindr, '.'); grid on; 135 | title('N-FINDR Recovered Endmembers', 'Interpreter', 'Latex', 'FontSize', 14); 136 | ax(1) = ylabel('Reflectance [0-1]'); 137 | ax(2) = xlabel('Wavelength [nm]'); 138 | set(ax, 'Interpreter', 'Latex', 'FontSize', 12); 139 | l = legend(cellstr(num2str((1:q)'))', 'Location', 'EastOutside'); 140 | a = get(l, 'children'); set(a(1:3:end), 'MarkerSize', 20); 141 | print(gcf, '-r600', '-depsc', sprintf('%s/endmmbrs-nfindr', resultsDir)); 142 | 143 | %% AVMAX 144 | fprintf('Performing AVMAX for endmember determination...\n'); tic; 145 | Uavmax = hyperAvmax(M2d, q); 146 | et=toc; fprintf('...Done. (~%1.3g seconds)\n',et); 147 | 148 | % Plot endmember signatures 149 | figure; plot(lambdasNm, Uavmax, '.'); grid on; 150 | title('AVMAX Recovered Endmembers', 'Interpreter', 'Latex', 'FontSize', 14); 151 | ax(1) = ylabel('Reflectance [0-1]'); 152 | ax(2) = xlabel('Wavelength [nm]'); 153 | set(ax, 'Interpreter', 'Latex', 'FontSize', 12); 154 | l = legend(cellstr(num2str((1:q)'))', 'Location', 'EastOutside'); 155 | a = get(l, 'children'); set(a(1:3:end), 'MarkerSize', 20); 156 | print(gcf, '-r600', '-depsc', sprintf('%s/endmmbrs-avmax', resultsDir)); 157 | 158 | %% AMEE 159 | fprintf('Performing AMEE for endmember determination...\n'); tic; 160 | Uamee = hyperAmee(M, q, 5); 161 | et=toc; fprintf('...Done. (~%1.3g seconds)\n',et); 162 | 163 | % Plot endmember signatures 164 | figure; plot(lambdasNm, Uamee, '.'); grid on; ylim([0,1]); 165 | title('AMEE Recovered Endmembers', 'Interpreter', 'Latex', 'FontSize', 14); 166 | ax(1) = ylabel('Reflectance [0-1]'); 167 | ax(2) = xlabel('Wavelength [nm]'); 168 | set(ax, 'Interpreter', 'Latex', 'FontSize', 12); 169 | l = legend(cellstr(num2str((1:q)'))', 'Location', 'EastOutside'); 170 | a = get(l, 'children'); set(a(1:3:end), 'MarkerSize', 20); 171 | print(gcf, '-r600', '-depsc', sprintf('%s/endmmbrs-amee', resultsDir)); 172 | 173 | %% -------------------------------------------------------------------------- 174 | % Create abundance maps from unmixed endmembers 175 | %% From PPI results: 176 | fprintf('Creating abundance maps from PPI endmember results...\n'); tic; 177 | abundanceMaps = hyperNnls(M2d, Uppi); 178 | abundanceMaps = hyperConvert3d(abundanceMaps, h, w, q); 179 | et=toc; fprintf('...Done. (~%1.3g seconds)\n',et); 180 | 181 | fprintf('Plotting and saving PPI abundance maps...\n'); 182 | for i=1:q 183 | if i==1; figure; end; 184 | clf; imagesc(abundanceMaps(:,:,i)); colorbar; axis image; 185 | title(sprintf('Abundance Map %d/%d', i, q), 'Interpreter', 'Latex'); 186 | print(gcf, '-depsc', '-r600', sprintf('%s/abund-ppi-%d', resultsDir, i)) 187 | end 188 | close(gcf); fprintf('...Done.\n'); 189 | 190 | %% From N-FINDR results: 191 | fprintf('Creating abundance maps from N-FINDR endmember results...\n'); tic; 192 | abundanceMaps = hyperNnls(M2d, Unfindr); 193 | abundanceMaps = hyperConvert3d(abundanceMaps, h, w, q); 194 | et=toc; fprintf('...Done. (~%1.3g seconds)\n',et); 195 | 196 | fprintf('Plotting and saving N-FINDR abundance maps...\n'); 197 | for i=1:q 198 | if i==1; figure; end; 199 | clf; imagesc(abundanceMaps(:,:,i)); colorbar; axis image; 200 | title(sprintf('Abundance Map %d/%d', i, q), 'Interpreter', 'Latex'); 201 | print(gcf, '-depsc', '-r600', sprintf('%s/abund-nfindr-%d', resultsDir, i)) 202 | end 203 | close(gcf); fprintf('...Done.\n'); 204 | 205 | %% From AVMAX results: 206 | fprintf('Creating abundance maps from AVMAX endmember results...\n'); tic; 207 | abundanceMaps = hyperNnls(M2d, Uavmax); 208 | abundanceMaps = hyperConvert3d(abundanceMaps, h, w, q); 209 | et=toc; fprintf('...Done. (~%1.3g seconds)\n',et); 210 | 211 | fprintf('Plotting and saving AVMAX abundance maps...\n'); 212 | for i=1:q 213 | if i==1; figure; end; 214 | clf; imagesc(abundanceMaps(:,:,i)); colorbar; axis image; 215 | title(sprintf('Abundance Map %d/%d', i, q), 'Interpreter', 'Latex'); 216 | print(gcf, '-depsc', '-r600', sprintf('%s/abund-avmax-%d', resultsDir, i)) 217 | end 218 | close(gcf); fprintf('...Done.\n'); 219 | 220 | %% From AMEE results: 221 | fprintf('Creating abundance maps from AMEE endmember results...\n'); tic; 222 | abundanceMaps = hyperNnls(M2d, Uamee); 223 | abundanceMaps = hyperConvert3d(abundanceMaps, h, w, q); 224 | et=toc; fprintf('...Done. (~%1.3g seconds)\n',et); 225 | 226 | fprintf('Plotting and saving AMEE abundance maps...\n'); 227 | for i=1:q 228 | if i==1; figure; end; 229 | clf; imagesc(abundanceMaps(:,:,i)); colorbar; axis image; 230 | title(sprintf('Abundance Map %d/%d', i, q), 'Interpreter', 'Latex'); 231 | print(gcf, '-depsc', '-r600', sprintf('%s/abund-amee-%d', resultsDir, i)) 232 | end 233 | close(gcf); fprintf('...Done.\n'); 234 | 235 | %% Save data and end log file 236 | saveDataFile = 'dataOutput'; 237 | fprintf('\nSaving endmemebers (from each method) to %s.mat...\n', saveDataFile); 238 | save([resultsDir,filesep,saveDataFile], 'lambdasNm', ... 239 | 'Uppi', 'Unfindr', 'Uavmax', 'Uamee'); 240 | fprintf('...Done.\n'); 241 | diary off; close all 242 | -------------------------------------------------------------------------------- /newFunctions/hyperNfindr.m: -------------------------------------------------------------------------------- 1 | function [U] = hyperNfindr(M, q) 2 | % HYPERNFINDR Performs the N-FINDR (endmember extraction) algorithm 3 | % Performs the N-FINDR algorithm to find q endmembers. If only M is 4 | % given as input, this function calls hyperHfcVd to estimate the number 5 | % of endmembers (q) and then hyperPct to reduce dimensionality to (q-1). 6 | % 7 | % Usage 8 | % [U] = hyperNfindr(M) 9 | % [U] = hyperNfindr(M, q) 10 | % Inputs 11 | % M - 2d matrix of HSI data (p x N) 12 | % q - Number of endmembers to find 13 | % -- if not given, q is obtained from hyperHfcVd(M, 10^-3) 14 | % Outputs 15 | % U - Recovered endmembers (p x q) 16 | % 17 | % References 18 | % M. Winter, "N-findr: an algorithm for fast autonomous 19 | % spectral endmember determination in hyperspectral data," SPIE’s 20 | % International Symposium on Optical Science, Engineering, and 21 | % Instrumentation, pages 266–275. International Society for Optics 22 | % and Photonics, 1999. 23 | 24 | % Error trapping 25 | if ndims(M) ~= 2 26 | warning('WarnTests:dim', ... 27 | 'Input image must be p x N.\n',... 28 | 'Converting with hyperConvert2d.\n') 29 | M = hyperConvert2d(M); 30 | end 31 | 32 | M_orig = M; 33 | [p, N] = size(M); 34 | 35 | if nargin == 1 36 | fprintf('Implementing hyperHfcVd to determine the number of endmembers.\n') 37 | q = hyperHfcVd(M_orig, [10^-3]); 38 | fprintf('Reducing dimensionality to (q-1) using hyperPct.\n') 39 | M = hyperPct(M, q-1); 40 | elseif q < p+1 41 | warning('WarnTests:dim', ... 42 | strcat('N-FINDR requires (q-1) spectral bands.\n',... 43 | 'Performing PCA to reduce dimensionality.\n')) 44 | M = hyperPct(M, q-1); 45 | elseif q > p+1 46 | warning('WarnTests:dim', ... 47 | strcat('N-FINDR requires (q-1) spectral bands.\n',... 48 | 'Performing PCA to reduce dimensionality.\n')) 49 | error('ErrTests:dim', ... 50 | strcat('N-FINDR cannot find more than (p+1) endmembers (q),\n', ... 51 | 'where p is the number of available spectral bands.\n')) 52 | end 53 | 54 | % Initialize 55 | U_idx = randperm(N,q); % Random endmember selection 56 | E = M(:,U_idx); % Endmember matrix 57 | V = abs(det([ones(1,q); E])) / factorial(q-1); % Simplex volume 58 | vols = zeros(q,1); 59 | 60 | % Search for maximum volume simplex 61 | for j = 1:N; 62 | % Replace each column of E with sample vector M(:,j) 63 | % and compute the volume for each 64 | for k = 1:q; 65 | E_tmp = E; 66 | E_tmp(:,k) = M(:,j); 67 | vols(k) = abs(det([ones(1,q); E_tmp])) / factorial(q-1); 68 | end 69 | % If max volume is greater than previous V, update E and V 70 | [V_tmp,k_idx] = max(vols); 71 | if V_tmp > V 72 | V = V_tmp; 73 | E(:,k_idx) = M(:,j); 74 | U_idx(k_idx) = j; 75 | end 76 | end 77 | 78 | % Return endmembers 79 | U = M_orig(:, U_idx); 80 | -------------------------------------------------------------------------------- /newFunctions/hyperRnfindr.m: -------------------------------------------------------------------------------- 1 | function [ U, X, n ] = hyperRnfindr( M, q, U_init ) 2 | % HYPERRNFINDR Performs the RN-FINDR (endmember extraction) algorithm 3 | % Performs the RN-FINDR algorithm to generate abundance maps 4 | % and find the purest pixels. This function utilizes FastICA. 5 | % 6 | % Usage 7 | % [ U, X, n ] = hyperNfindr( M, q, U_init ) 8 | % Inputs 9 | % M - HSI data in 2D (p x N) 10 | % q - Number of materials to unmix 11 | % U_init - Initia l endmembers (p x #) 12 | % Outputs 13 | % U - matrix of recovered endmembers (p x q) 14 | % X - material abundance maps (q x N) 15 | % n - (optional) Indicies of recovered endmembers (q x 1) 16 | % 17 | % References 18 | % C. Chang, C.C. Wu, and C.T. Tsai., "Random N-finder (N-FINDR) 19 | % endmember extraction algorithms for hyperspectral imagery." 20 | % Image Processing, IEEE Transactions on 20.3 (2011): 641-656. -------------------------------------------------------------------------------- /newFunctions/hyperTruecolor.m: -------------------------------------------------------------------------------- 1 | function [tColor] = hyperTruecolor(rflFile, height, width, bands, rgbBands, strechtype) 2 | % HYPERTRUECOLOR Returns a truecolor composite image, given a reflectance file 3 | % hyperTruecolor returns a truecolor composite image, given an AVIRIS reflectance file, 4 | % with an optional enhancement of the image using one of two contrast streches. 5 | % 6 | % Usage 7 | % [tColor] = hyperTruecolor(rflFile, height, width, bands) 8 | % [tColor] = hyperTruecolor(rflFile, height, width, bands, rgbBands) 9 | % [tColor] = hyperTruecolor(rflFile, height, width, bands, rgbBands, strechtype) 10 | % Inputs 11 | % rflFile - Path and filename of AVIRIS reflectance measurements 12 | % height - Height in pixels 13 | % width - Width in pixels 14 | % bands - Number of bands 15 | % rgbBands - [Red, green, blue] bands (1x3 vector) 16 | % [31,20,12] is the default if no argument is given 17 | % strechtype - truecolor enhancement contrast strech (string): 18 | % 'none' : default if no argument is given 19 | % 'stretchlim' : linear contrast stretch 20 | % 'decorrstretch': decorrelation stretch 21 | % (enhanced color separation across highly correlated channels) 22 | % Outputs 23 | % tColor - Truecolor composite image 24 | 25 | if nargin < 4 || nargin > 6 26 | help hyperTruecolor 27 | error('Incorrect usage, see function description above.') 28 | end 29 | 30 | if nargin == 4 31 | % RGB bands: [665.73, 557.07, 478.17] nm 32 | rgbBands = [31,20,12]; 33 | strechtype = 'none'; 34 | elseif nargin == 5 35 | strechtype = 'none'; 36 | end 37 | 38 | h = height; 39 | w = width; 40 | p = bands; 41 | 42 | % Read the 3 RGB bands 43 | tColor = multibandread(rflFile, [h w p], 'int16', 0, 'bip', 'ieee-be', ... 44 | {'Row', 'Range', [1 h]}, {'Column', 'Range', [1 w]}, ... 45 | {'Band', 'Direct', rgbBands} ); 46 | 47 | % Normalize to proper reflectance units. 48 | tColor = tColor ./ 1e4; 49 | 50 | switch lower(strechtype) 51 | case 'none' 52 | return 53 | case 'stretchlim' 54 | % Apply a linear contrast stretch to the truecolor composite image 55 | tColor = imadjust(tColor, stretchlim(tColor)); 56 | case 'decorrstretch' 57 | % Apply a decorrelation stretch to the truecolor composite image 58 | tColor = decorrstretch(tColor, 'Tol', 0.01); 59 | otherwise 60 | help hyperTruecolor 61 | error(sprintf('Unknown method %s. See function description above.', strechtype)) 62 | end 63 | --------------------------------------------------------------------------------