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.transform; 031 032import java.util.HashMap; 033import java.util.Map; 034 035import org.openimaj.image.FImage; 036import org.openimaj.math.geometry.point.Point2d; 037import org.openimaj.math.geometry.point.Point2dImpl; 038import org.openimaj.math.geometry.shape.Shape; 039 040/** 041 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 042 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 043 * 044 * Perform a set of matrix transforms on a set of images and construct a single image containing all the pixels (or a window of the pixels) 045 * in the projected space. 046 */ 047public class FProjectionProcessor extends ProjectionProcessor<Float, FImage> { 048 049 /** 050 * Perform projection but only request data for pixels within the windowed range provided. Specify the background colour, i.e. the value of pixels 051 * with no data post projection. 052 * @param windowMinC left X 053 * @param windowMaxC right X 054 * @param windowMinR top Y 055 * @param windowMaxR bottom Y 056 * @param backgroundColour background colour of pixels with no data 057 * @return projected image within the window 058 */ 059 @Override 060 public FImage performProjection(int windowMinC , int windowMaxC , int windowMinR , int windowMaxR , Float backgroundColour) { 061 FImage output = null; 062 output = new FImage(windowMaxC-windowMinC,windowMaxR-windowMinR); 063 if(backgroundColour!=null) 064 output.fill(backgroundColour); 065 Shape[][] shapeRects = this.getCurrentShapes(); 066 for(int y = 0; y < output.getHeight(); y++) 067 { 068 for(int x = 0; x < output.getWidth(); x++){ 069 Point2d realPoint = new Point2dImpl(windowMinC + x,windowMinR + y); 070 int i = 0; 071 for (int j = 0; j < shapeRects.length; j++) { 072 if(backgroundColour == null || isInside(j,shapeRects,realPoint)){ 073 double[][] transform = this.transformsInverted.get(i).getArray(); 074 075 float xt = (float)transform[0][0] * realPoint.getX() + (float)transform[0][1] * realPoint.getY() + (float)transform[0][2]; 076 float yt = (float)transform[1][0] * realPoint.getX() + (float)transform[1][1] * realPoint.getY() + (float)transform[1][2]; 077 float zt = (float)transform[2][0] * realPoint.getX() + (float)transform[2][1] * realPoint.getY() + (float)transform[2][2]; 078 079 xt /= zt; 080 yt /= zt; 081 FImage im = this.images.get(i); 082 if(backgroundColour!=null) 083 output.pixels[y][x] = im.getPixelInterp(xt, yt,backgroundColour); 084 else 085 output.pixels[y][x] = im.getPixelInterp(xt, yt); 086 } 087 i++; 088 } 089 } 090 } 091 return output; 092 } 093 094 /** 095 * Perform blended projection but only request data for pixels within the windowed range provided. Specify the background colour, i.e. the value of pixels 096 * with no data post projection. This blends any existing pixels to newly added pixels 097 * @param windowMinC left X 098 * @param windowMaxC right X 099 * @param windowMinR top Y 100 * @param windowMaxR bottom Y 101 * @param backgroundColour background colour of pixels with no data 102 * @return projected image within the window 103 */ 104 @Override 105 public FImage performBlendedProjection(int windowMinC , int windowMaxC , int windowMinR , int windowMaxR , Float backgroundColour) { 106 FImage output = null; 107 output = new FImage(windowMaxC-windowMinC,windowMaxR-windowMinR); 108 Map<Integer,Boolean> setMap = new HashMap<Integer,Boolean>(); 109 FImage blendingPallet = output.newInstance(2, 1); 110 for(int y = 0; y < output.getHeight(); y++) 111 { 112 for(int x = 0; x < output.getWidth(); x++){ 113 Point2d realPoint = new Point2dImpl(windowMinC + x,windowMinR + y); 114 int i = 0; 115 for(Shape s : this.projectedShapes){ 116 if(s.isInside(realPoint)){ 117 double[][] transform = this.transformsInverted.get(i).getArray(); 118 119 float xt = (float)transform[0][0] * realPoint.getX() + (float)transform[0][1] * realPoint.getY() + (float)transform[0][2]; 120 float yt = (float)transform[1][0] * realPoint.getX() + (float)transform[1][1] * realPoint.getY() + (float)transform[1][2]; 121 float zt = (float)transform[2][0] * realPoint.getX() + (float)transform[2][1] * realPoint.getY() + (float)transform[2][2]; 122 123 xt /= zt; 124 yt /= zt; 125 Float toSet = null; 126 if(backgroundColour!=null) 127 toSet = this.images.get(i).getPixelInterp(xt, yt,backgroundColour); 128 else 129 if(setMap.get(y * output.getWidth() + x)!=null) 130 toSet = this.images.get(i).getPixelInterp(xt, yt,output.getPixelInterp(x, y)); 131 else 132 toSet = this.images.get(i).getPixelInterp(xt, yt); 133 // Blend the pixel with the existing pixel 134 if(setMap.get(y * output.getWidth() + x)!=null){ 135 blendingPallet.pixels[0][1] = toSet; 136 blendingPallet.pixels[0][0] = output.getPixel(x, y); 137 138 toSet = blendingPallet.getPixelInterp(0.1, 0.5); 139 } 140 setMap.put(y * output.getWidth() + x,true); 141 output.pixels[y][x] = toSet; 142 } 143 i++; 144 } 145 } 146 } 147 return output; 148 } 149 150}