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.connectedcomponent.proc;
031
032import org.openimaj.feature.DoubleFV;
033import org.openimaj.feature.FeatureVectorProvider;
034import org.openimaj.image.pixel.ConnectedComponent;
035import org.openimaj.image.processor.connectedcomponent.ConnectedComponentProcessor;
036
037
038/**
039 * Implementation of the 7 Hu moments for describing
040 * connected component shape.
041 * 
042 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
043 */
044public class HuMoments implements ConnectedComponentProcessor, FeatureVectorProvider<DoubleFV> {
045        /**
046         * The first Hu moment
047         */
048        public double h1;
049        
050        /**
051         * The second Hu moment
052         */
053        public double h2;
054        
055        /**
056         * The third Hu moment
057         */
058        public double h3;
059        
060        /**
061         * The forth Hu moment
062         */
063        public double h4;
064        
065        /**
066         * The fifth Hu moment
067         */
068        public double h5;
069        
070        /**
071         * The sixth Hu moment
072         */
073        public double h6;
074        
075        /**
076         * The seventh Hu moment
077         */
078        public double h7;
079        
080        @Override
081        public void process(ConnectedComponent cc) {
082                double v11 = cc.calculateMomentNormalised(1, 1);
083                
084                double v12 = cc.calculateMomentNormalised(1, 2);
085                double v21 = cc.calculateMomentNormalised(2, 1);
086                
087                double v02 = cc.calculateMomentNormalised(0, 2);
088                double v20 = cc.calculateMomentNormalised(2, 0);
089                
090                double v03 = cc.calculateMomentNormalised(0, 3);
091                double v30 = cc.calculateMomentNormalised(3, 0);
092                
093                h1 = v20 + v02;
094                h2 = ((v20 - v02) * (v20 - v02)) + (4 * v11 * v11); 
095                h3 = ((v30 - 3*v12)*(v30 - 3*v12)) + ((3*v21 - v03)*(3*v21 - v03));
096                h4 = ((v30+v12)*(v30+v12)) + ((v21+v03)*(v21+v03));
097                h5 = (((v30 - 3*v12)*(v30+v12)) * (((v30+v12)*(v30+v12) - (3*(v21+v03)*(v21+v03))))) +
098                                (((3*v21-v03)*(v21+v03)) * ((3*(v30+v12)*(v30+v12)) - (v21+v03)*(v21+v03)));
099                h6 = ((v20 - v02) * ((v30+v12)*(v30+v12) - (v21 + v03)*(v21 + v03))) + (4*v11*(v30+v12)*(v21+v03));
100                h7 = ((3*v21 - v03)*(v30+v12)*((v30+v12)*(v30+v12) - 3*(v21+v03)*(v21+v03))) -
101                                ((v30-3*v12)*(v21+v03)*(3*(v30+v12)*(v30+v12) - (v21+v03)*(v21+v03)));
102        }
103        
104        @Override
105        public String toString() {
106                return String.format("%2.2f, %2.2f, %2.2f, %2.2f, %2.2f, %2.2f, %2.2f", h1, h2, h3, h4, h5, h6, h7);
107        }
108
109        /**
110         * Get all the values of the descriptor as an array.
111         * @return an array of descriptor values
112         */
113        public double[] getFeatureVectorArray() {
114                return new double[] {h1, h2, h3, h4, h5, h6, h7};
115        }
116        
117        @Override
118        public DoubleFV getFeatureVector() {
119                return new DoubleFV(getFeatureVectorArray());
120        }
121}
122