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.pixel.statistics; 031 032import org.openimaj.feature.FeatureVectorProvider; 033import org.openimaj.image.MBFImage; 034import org.openimaj.math.statistics.distribution.MultidimensionalHistogram; 035import org.openimaj.util.pair.Pair; 036 037/** 038 * A multidimensional histogram calculated from image pixels (assumes image is 039 * in 0-1 range) 040 * 041 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 042 * 043 */ 044public class HistogramModel extends AbstractPixelStatisticsModel 045 implements 046 FeatureVectorProvider<MultidimensionalHistogram> 047{ 048 private static final long serialVersionUID = 1L; 049 050 /** 051 * The histogram data 052 */ 053 public MultidimensionalHistogram histogram; 054 055 /** 056 * Construct with the given number of bins per dimension 057 * 058 * @param nbins 059 * the number of bins in each dimension for the histograms 060 */ 061 public HistogramModel(int... nbins) { 062 super(nbins.length); 063 064 assert (nbins.length > 0); 065 066 histogram = new MultidimensionalHistogram(nbins); 067 } 068 069 @Override 070 public void estimateModel(MBFImage... images) { 071 reset(); 072 for (final MBFImage im : images) { 073 accum(im); 074 } 075 histogram.normalise(); 076 } 077 078 protected void reset() { 079 for (int i = 0; i < histogram.values.length; i++) 080 histogram.values[i] = 0; 081 } 082 083 /** 084 * For a given index, map to the range of colours which could map to it 085 * 086 * @param index 087 * @return start/end colour 088 */ 089 public Pair<float[]> colourRange(int index) { 090 final int[] coord = this.histogram.getCoordinates(index); 091 final float[] start = new float[coord.length]; 092 final float[] end = new float[coord.length]; 093 final int[] nbins = histogram.nbins; 094 for (int i = 0; i < coord.length; i++) { 095 start[i] = (float) coord[i] / (float) nbins[i]; 096 end[i] = ((float) coord[i] + 1) / nbins[i]; 097 } 098 return new Pair<float[]>(start, end); 099 } 100 101 /** 102 * For a given index, get the average colour which would map to it 103 * 104 * @param index 105 * @return start/end colour 106 */ 107 public float[] colourAverage(int index) { 108 final int[] coord = this.histogram.getCoordinates(index); 109 final float[] average = new float[coord.length]; 110 final int[] nbins = histogram.nbins; 111 for (int i = 0; i < coord.length; i++) { 112 final float start = (float) coord[i] / (float) nbins[i]; 113 final float end = ((float) coord[i] + 1) / nbins[i]; 114 average[i] = (start + end) / 2f; 115 } 116 117 return average; 118 } 119 120 protected void accum(MBFImage im) { 121 final int height = im.getHeight(); 122 final int width = im.getWidth(); 123 final int[] bins = new int[ndims]; 124 125 final float[][][] bands = new float[im.numBands()][][]; 126 for (int i = 0; i < bands.length; i++) 127 bands[i] = im.getBand(i).pixels; 128 129 final int[] nbins = histogram.nbins; 130 final double[] values = histogram.values; 131 132 for (int y = 0; y < height; y++) { 133 for (int x = 0; x < width; x++) { 134 for (int i = 0; i < ndims; i++) { 135 bins[i] = (int) (bands[i][y][x] * (nbins[i])); 136 if (bins[i] >= nbins[i]) 137 bins[i] = nbins[i] - 1; 138 } 139 140 int bin = 0; 141 for (int i = 0; i < ndims; i++) { 142 int f = 1; 143 for (int j = 0; j < i; j++) 144 f *= nbins[j]; 145 146 bin += f * bins[i]; 147 } 148 149 values[bin]++; 150 } 151 } 152 } 153 154 @Override 155 public String toString() { 156 return histogram.toString(); 157 } 158 159 @Override 160 public HistogramModel clone() { 161 final HistogramModel model = new HistogramModel(); 162 model.histogram = histogram.clone(); 163 model.ndims = ndims; 164 return model; 165 } 166 167 @Override 168 public MultidimensionalHistogram getFeatureVector() { 169 return histogram; 170 } 171}