001    /*
002     * MatrixCreator
003     * 
004     * Copyright (c) 2001, 2002, 2003 Marco Schmidt.
005     * All rights reserved.
006     */
007    
008    package net.sourceforge.jiu.color.analysis;
009    
010    import net.sourceforge.jiu.data.Gray8Image;
011    import net.sourceforge.jiu.data.IntegerImage;
012    import net.sourceforge.jiu.data.Paletted8Image;
013    import net.sourceforge.jiu.color.data.CoOccurrenceMatrix;
014    import net.sourceforge.jiu.color.data.CoOccurrenceFrequencyMatrix;
015    import net.sourceforge.jiu.color.data.MemoryCoOccurrenceMatrix;
016    import net.sourceforge.jiu.color.data.MemoryCoOccurrenceFrequencyMatrix;
017    
018    /**
019     * This class creates and initializes co-occurrence matrices and co-occurrence 
020     * frequency matrices.
021     * @author Marco Schmidt
022     */
023    public class MatrixCreator
024    {
025            private MatrixCreator()
026            {
027            }
028    
029            public static CoOccurrenceMatrix createCoOccurrenceMatrix(Gray8Image image)
030            {
031                    return createCoOccurrenceMatrix(image, 0);
032            }
033    
034            public static CoOccurrenceMatrix createCoOccurrenceMatrix(Paletted8Image image)
035            {
036                    return createCoOccurrenceMatrix(image, 0);
037            }
038    
039            public static CoOccurrenceMatrix createCoOccurrenceMatrix(IntegerImage image, int channelIndex)
040            {
041                    if (image == null)
042                    {
043                            throw new IllegalArgumentException("The image must non-null.");
044                    }
045                    if (channelIndex < 0)
046                    {
047                            throw new IllegalArgumentException("The channel index must be zero or larger.");
048                    }
049                    if (channelIndex >= image.getNumChannels())
050                    {
051                            throw new IllegalArgumentException("The channel index must be smaller than the number of channels in the image (" + image.getNumChannels() + ").");
052                    }
053                    int dim = image.getMaxSample(channelIndex) + 1;
054                    MemoryCoOccurrenceMatrix matrix = new MemoryCoOccurrenceMatrix(dim);
055                    initCoOccurrenceMatrix(image, channelIndex, matrix);
056                    return matrix;
057            }
058    
059            /** 
060             * Initializes a co-occurrence matrix from the input image, using the <em>direct</em>
061             * four neighbor pixels.
062             * The number of entries in the palette of the argument image must be equal to the dimension
063             * of the argument matrix.
064             * @param image the image that will be used to initialize the matrix
065             * @param matrix the matrix that will first be cleared and then initialized from the image
066             * @throws IllegalArgumentException if at least one of the arguments is null or if the
067             *  palette size is not equal to the matrix dimension
068             */
069            public static void initCoOccurrenceMatrix(IntegerImage image, int channelIndex, CoOccurrenceMatrix matrix)
070            {
071                    if (image == null)
072                    {
073                            throw new IllegalArgumentException("The image must non-null.");
074                    }
075                    if (channelIndex < 0)
076                    {
077                            throw new IllegalArgumentException("The channel index must be zero or larger.");
078                    }
079                    if (channelIndex >= image.getNumChannels())
080                    {
081                            throw new IllegalArgumentException("The channel index must be smaller than the number of channels in the image (" + image.getNumChannels() + ").");
082                    }
083                    int dim = image.getMaxSample(channelIndex) + 1;
084                    if (matrix == null)
085                    {
086                            throw new IllegalArgumentException("The matrix must non-null.");
087                    }
088                    if (matrix.getDimension() != dim)
089                    {
090                            throw new IllegalArgumentException("Dimension of matrix (" + 
091                                    matrix.getDimension() + " must be exactly one larger than " +
092                                    "maximum sample value (" + (dim - 1) + ").");
093                    }
094                    matrix.clear();
095                    int maxX = image.getWidth() - 1;
096                    int maxY = image.getHeight() - 1;
097                    for (int y = 0; y <= maxY; y++)
098                    {
099                            for (int x = 0; x <= maxX; x++)
100                            {
101                                    int index = image.getSample(channelIndex, x, y);
102                                    if (x > 0)
103                                    {
104                                            int leftNeighbor = image.getSample(channelIndex, x - 1, y);
105                                            matrix.incValue(index, leftNeighbor);
106                                    }
107                                    if (x < maxX)
108                                    {
109                                            int rightNeighbor = image.getSample(channelIndex, x + 1, y);
110                                            matrix.incValue(index, rightNeighbor);
111                                    }
112                                    if (y > 0)
113                                    {
114                                            int topNeighbor = image.getSample(channelIndex, x, y - 1);
115                                            matrix.incValue(index, topNeighbor);
116                                    }
117                                    if (y < maxY)
118                                    {
119                                            int bottomNeighbor = image.getSample(channelIndex, x, y + 1);
120                                            matrix.incValue(index, bottomNeighbor);
121                                    }
122                            }
123                    }
124            }
125    
126            /**
127             * Creates a new co-occurrence frequency with the same dimension as the argument co-occurrence
128             * matrix, calls {@link #initCoOccurrenceFrequencyMatrix} with them to initialize the new matrix,
129             * then returns it.
130             * A {@link MemoryCoOccurrenceFrequencyMatrix} is created.
131             * @param A the co-occurrence matrix from which the resulting matrix will be initialized
132             * @return the newly-created co-occurrence frequency matrix
133             * @throws IllegalArgumentException if the argument matrix is null 
134             */
135            public static CoOccurrenceFrequencyMatrix createCoOccurrenceFrequencyMatrix(final CoOccurrenceMatrix A)
136            {
137                    if (A == null)
138                    {
139                            throw new IllegalArgumentException("Matrix argument must be non-null.");
140                    }
141                    int dimension = A.getDimension();
142                    MemoryCoOccurrenceFrequencyMatrix matrix = new MemoryCoOccurrenceFrequencyMatrix(dimension);
143                    initCoOccurrenceFrequencyMatrix(A, matrix);
144                    return matrix;
145            }
146    
147            /**
148             * Initializes a co-occurrence frequency matrix from a co-occurrence matrix.
149             * The two argument matrices must be non-null and have the same dimension.
150             * @param A co-occurrence matrix used as input
151             * @param cofm co-occurrence matrix, will be initialized by this method
152             * @throws IllegalArgumentException if either matrix is null or if the dimensions are not equal 
153             */
154            public static void initCoOccurrenceFrequencyMatrix(final CoOccurrenceMatrix A, CoOccurrenceFrequencyMatrix cofm)
155            {
156                    if (A == null)
157                    {
158                            throw new IllegalArgumentException("Co-occurrence matrix A argument must not be null.");
159                    }
160                    if (cofm == null)
161                    {
162                            throw new IllegalArgumentException("Co-occurrence frequency matrix cofm argument must not be null.");
163                    }
164                    final int DIMENSION = A.getDimension();
165                    if (DIMENSION != cofm.getDimension())
166                    {
167                            throw new IllegalArgumentException("Dimension of matrices A (" +
168                                    DIMENSION + ") and cofm (" + cofm.getDimension() + ") must " +
169                                    "be equal.");
170                    }
171                    cofm.clear();
172                    double totalSum = 0.0;
173                    for (int i = 0; i < DIMENSION; i++)
174                    {
175                            // first sum up A[i, k], k = 0..dimension-1
176                            double sum = 0.0;
177                            for (int k = 0; k < DIMENSION; k++)
178                            {
179                                    sum += A.getValue(i, k);
180                            }
181                            totalSum += sum;
182                            for (int j = 0; j < DIMENSION; j++)
183                            {
184                                    double value = A.getValue(i, j);
185                                    double result;
186                                    if (sum == 0.0)
187                                    {
188                                            result = 0.0;
189                                    }
190                                    else
191                                    {
192                                            result = value / sum;
193                                    }
194                                    cofm.setValue(i, j, result);
195                            }
196                    }
197                    cofm.computeStatistics();
198            }
199    }