001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.image.processing.convolution.filterbank; 031 032import org.openimaj.citation.annotation.Reference; 033import org.openimaj.citation.annotation.ReferenceType; 034import org.openimaj.image.FImage; 035import org.openimaj.image.processing.convolution.SumBoxFilter; 036 037/** 038 * Implementation of Laws texture energy measures, based on the description in 039 * <a href="https://courses.cs.washington.edu/courses/cse576/book/ch7.pdf"> 040 * Shapiro and Stockman Section 7.3.4</a>. 041 * <p> 042 * Nine texture energy images are created by convolving with the 16 base 5x5 043 * Laws filters, and then computing the energy for each pixel by summing the 044 * absolute pixel values in a macro window about that pixel. 045 * 046 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 047 * 048 */ 049@Reference( 050 type = ReferenceType.Inproceedings, 051 author = { "Laws, K. I." }, 052 title = "{Rapid Texture Identification}", 053 year = "1980", 054 booktitle = "Proc. SPIE Conf. Image Processing for Missile Guidance", 055 pages = { "376", "", "380" }, 056 customData = { 057 "citeulike-article-id", "2335645", 058 "keywords", "bibtex-import", 059 "posted-at", "2008-02-05 15:32:50", 060 "priority", "2" 061 }) 062public class LawsTexture extends LawsTextureBase { 063 064 private int macroWidth = 15; 065 private int macroHeight = 15; 066 067 /** 068 * Construct using 15*15 macro windows for the energy computation 069 */ 070 public LawsTexture() { 071 } 072 073 /** 074 * Construct using the given sized macro windows for the energy computation 075 * 076 * @param macro 077 * the the window width and height 078 */ 079 public LawsTexture(int macro) { 080 this.macroWidth = macro; 081 this.macroHeight = macro; 082 } 083 084 /** 085 * Construct using the given sized macro windows for the energy computation 086 * 087 * @param macroWidth 088 * the window width 089 * @param macroHeight 090 * the window height 091 */ 092 public LawsTexture(int macroWidth, int macroHeight) { 093 this.macroWidth = macroWidth; 094 this.macroHeight = macroHeight; 095 } 096 097 @Override 098 public void analyseImage(FImage in) { 099 super.analyseImage(in); 100 101 final FImage[] tmpResp = responses; 102 responses = new FImage[9]; 103 104 responses[0] = absAverage(tmpResp[L5E5], tmpResp[E5L5]); 105 responses[1] = absAverage(tmpResp[L5R5], tmpResp[R5L5]); 106 responses[2] = absAverage(tmpResp[E5S5], tmpResp[S5E5]); 107 responses[3] = tmpResp[S5S5].abs(); 108 responses[4] = tmpResp[R5R5].abs(); 109 responses[5] = absAverage(tmpResp[L5S5], tmpResp[S5L5]); 110 responses[6] = tmpResp[E5E5].abs(); 111 responses[7] = absAverage(tmpResp[E5R5], tmpResp[R5E5]); 112 responses[8] = absAverage(tmpResp[S5R5], tmpResp[R5S5]); 113 114 for (int i = 0; i < 9; i++) { 115 responses[i] = responses[i].processInplace(new SumBoxFilter(macroWidth, macroHeight)); 116 } 117 } 118 119 private FImage absAverage(FImage i1, FImage i2) { 120 final FImage img = new FImage(i1.width, i1.height); 121 122 for (int y = 0; y < img.height; y++) 123 for (int x = 0; x < img.width; x++) 124 img.pixels[y][x] = Math.abs(i1.pixels[y][x] + i2.pixels[y][x]) / 2; 125 126 return img; 127 } 128}