All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.ojil.algorithm.Gray8GaussSmoothVert Maven / Gradle / Ivy

There is a newer version: 0.0.11
Show newest version
/*
 * GaussHoriz.java
 *
 * Created on August 27, 2006, 4:32, PM
 *
 * To change this templatef, choose Tools | Template Manager
 * and open the template in the editor.
 *
 * Copyright 2007 by Jon A. Webb
 *     This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Lesser General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Lesser General Public License for more details.
 *
 *    You should have received a copy of the Lesser GNU General Public License
 *    along with this program.  If not, see .
 *
 */

package com.github.ojil.algorithm;

import com.github.ojil.core.Gray8Image;
import com.github.ojil.core.Image;
import com.github.ojil.core.ImageError;
import com.github.ojil.core.PipelineStage;

/**
 * Computes a vertical Gaussian blur for an input gray image. The sigma value
 * for the operator is set in the constructor or setSigma. All calculations are
 * done in integer (per CLDC 1.0) and the sigma value is specified as multiplied
 * by 10.0. The minimum value for the unmultiplied sigma is 0.1; the maximum
 * value is about 10.0. Larger sigma values give an operator which is more
 * blurred.
 * 

* Hungarian prefix is 'gshz'. * * @author webb */ public class Gray8GaussSmoothVert extends PipelineStage { /** * cSigma is the sigma value we'll be using. It has been multiplied by 10.0 * and converted to integer because CLDC 1.0 doesn't allow floating point. * The minimum legal value for cSigma is 1; the maximum is given by the * length of nCoeff below. */ private int cSigma; /** * nCoeff row i is the precomputed Gauss coefficients for sigma = i/10.0. * They have been scaled by 256 and converted to integer because CLDC 1.0 * doesn't allow floating point. The coefficients have been scaled and * normalized so the sum is 0 and the sum of the absolute values is 256 * (counting both sides of the Canny operator -- the operator is symmetric * so we just give one side below.) */ /** * The array below was generated using two Excel macros: In cell b2 and * filled out to column AM and down: * =EXP(-(COLUMN(B2)-1)*(COLUMN(B2)-1)/((ROW(B2)-1)/10*(ROW(B2)-1)/10)) To * compute the value shown below: =ROUND(B2/SUM($B2:$AM2)*256,0) */ private final Integer[][] nCoeff = {// @formatter:off {0}, // unused, inserted to make lookup simpler {256}, {256}, {256}, {256}, {256}, {256}, {255,1}, {254,2}, {250,6}, {244,12}, {236,20}, {227,28,1}, {217,37,2}, {207,45,4}, {198,52,6}, {189,58,8,1}, {180,64,11,1}, {172,68,15,2}, {164,71,18,3}, {157,74,21,4}, {150,76,24,5,1}, {144,77,28,6,1}, {138,78,30,8,1}, {132,79,33,10,2}, {127,79,35,12,3}, {122,79,37,13,4,1}, {118,78,39,15,4,1}, {114,78,41,17,5,1}, {110,77,42,18,6,2}, {106,76,44,20,7,2,1}, {103,75,45,22,8,3,1}, {99,74,46,23,10,3,1}, {96,73,46,24,11,4,1}, {93,72,47,26,12,5,1}, {91,71,47,27,13,5,2,1}, {88,70,48,28,14,6,2,1}, {86,69,48,29,15,7,3,1}, {83,68,48,29,16,7,3,1}, {81,67,48,30,17,8,3,1}, {79,65,48,31,18,9,4,2,1}, {77,64,48,32,18,10,4,2,1}, {75,63,48,32,19,10,5,2,1}, {73,62,48,33,20,11,5,2,1}, {72,61,47,33,21,12,6,3,1}, {70,60,47,33,21,12,7,3,1,1}, {68,59,47,34,22,13,7,3,2,1}, {67,58,46,34,23,14,8,4,2,1}, {65,57,46,34,23,14,8,4,2,1}, {64,56,46,34,24,15,9,5,2,1}, {63,55,45,34,24,15,9,5,3,1,1}, {61,55,45,34,24,16,10,5,3,1,1}, {60,54,45,34,25,16,10,6,3,2,1}, {59,53,44,35,25,17,11,6,3,2,1}, {58,52,44,35,25,17,11,7,4,2,1}, {57,51,43,34,26,18,12,7,4,2,1,1}, {56,50,43,34,26,18,12,7,4,2,1,1}, {55,50,43,34,26,19,12,8,5,3,1,1}, {54,49,42,34,26,19,13,8,5,3,2,1}, {53,48,42,34,26,19,13,9,5,3,2,1}, {52,48,41,34,27,20,14,9,6,3,2,1}, {51,47,41,34,27,20,14,9,6,4,2,1,1}, {50,46,41,34,27,20,14,10,6,4,2,1,1}, {49,46,40,34,27,20,15,10,7,4,2,1,1}, {48,45,40,33,27,21,15,10,7,4,3,1,1}, {48,44,39,33,27,21,15,11,7,5,3,2,1}, {47,44,39,33,27,21,16,11,7,5,3,2,1,1}, {46,43,39,33,27,21,16,11,8,5,3,2,1,1}, {45,42,38,33,27,21,16,12,8,5,3,2,1,1}, {45,42,38,33,27,21,16,12,8,6,4,2,1,1}, {44,41,37,32,27,22,17,12,9,6,4,2,1,1}, {43,41,37,32,27,22,17,12,9,6,4,3,2,1,1}, {43,40,37,32,27,22,17,13,9,6,4,3,2,1,1}, {42,40,36,32,27,22,17,13,9,7,4,3,2,1,1}, {41,39,36,32,27,22,17,13,10,7,5,3,2,1,1}, {41,39,35,31,27,22,17,13,10,7,5,3,2,1,1}, {40,38,35,31,27,22,18,14,10,7,5,3,2,1,1}, {40,38,35,31,27,22,18,14,10,7,5,4,2,1,1,1}, {39,37,34,31,26,22,18,14,11,8,5,4,2,2,1,1}, {39,37,34,30,26,22,18,14,11,8,6,4,3,2,1,1}, {38,36,34,30,26,22,18,14,11,8,6,4,3,2,1,1}, {38,36,33,30,26,22,18,14,11,8,6,4,3,2,1,1}, {37,36,33,30,26,22,18,15,11,9,6,4,3,2,1,1,1}, {37,35,33,30,26,22,18,15,12,9,6,5,3,2,1,1,1}, {36,35,32,29,26,22,18,15,12,9,7,5,3,2,2,1,1}, {36,34,32,29,26,22,18,15,12,9,7,5,4,2,2,1,1}, {35,34,32,29,26,22,19,15,12,9,7,5,4,3,2,1,1}, {35,34,32,29,26,22,19,15,12,9,7,5,4,3,2,1,1}, {35,33,31,29,25,22,19,15,12,10,7,5,4,3,2,1,1,1}, {34,33,31,28,25,22,19,15,12,10,8,6,4,3,2,1,1,1}, {34,33,31,28,25,22,19,16,13,10,8,6,4,3,2,1,1,1}, {33,32,30,28,25,22,19,16,13,10,8,6,4,3,2,2,1,1}, {33,32,30,28,25,22,19,16,13,10,8,6,5,3,2,2,1,1}, {33,32,30,27,25,22,19,16,13,10,8,6,5,3,2,2,1,1,1}, {32,31,30,27,25,22,19,16,13,11,8,6,5,4,3,2,1,1,1}, {32,31,29,27,25,22,19,16,13,11,8,7,5,4,3,2,1,1,1}, {32,31,29,27,24,22,19,16,13,11,9,7,5,4,3,2,1,1,1}, {31,30,29,27,24,22,19,16,13,11,9,7,5,4,3,2,1,1,1}, {31,30,28,26,24,21,19,16,13,11,9,7,5,4,3,2,2,1,1}, {31,30,28,26,24,21,19,16,14,11,9,7,6,4,3,2,2,1,1,1}, {30,29,28,26,24,21,19,16,14,11,9,7,6,4,3,2,2,1,1,1} };// @formatter:on /** * Creates a new instance of GaussHoriz * * @param cSigma * the sigma value for the operator, which is the sigma in the * Gaussian distribution multipied by 10.0 and converted to * integer. * @throws ImageError * is sigma is out of range. */ public Gray8GaussSmoothVert(final int cSigma) throws ImageError { setSigma(cSigma); } /** * Apply the Gaussian horizontally to the input input image. The sigma value * for the operator is set in the class constructor. We handle the borders * of the image a little carefully to avoid creating spurious edges at them. * The image value at the border is reflected so that image(-1,0), for * example, is made equal to image(1,0). * * @param image * the input Gray8Image * @throws ImageError * if image is not a Gray8Image */ @Override public void push(final Image image) throws ImageError { if (!(image instanceof Gray8Image)) { throw new ImageError(ImageError.PACKAGE.ALGORITHM, AlgorithmErrorCodes.IMAGE_NOT_GRAY8IMAGE, image.toString(), null, null); } final Gray8Image input = (Gray8Image) image; final Gray8Image result = new Gray8Image<>(image.getWidth(), image.getHeight()); final Byte[] bIn = input.getData(); final Byte[] bResult = result.getData(); final Integer[] wCoeff = nCoeff[cSigma]; final int cHeight = input.getHeight(); for (int j = 0; j < input.getWidth(); j++) { for (int i = 0; i < cHeight; i++) { /* left side of Gaussian */ int wSum = 0; /* * Use Math.abs to mirror the index at the border */ for (int k = 1; k < wCoeff.length; k++) { wSum += wCoeff[k] * bIn[(Math.abs(i - k) * cHeight) + j]; } /* right side of Gaussian */ for (int k = 0; k < wCoeff.length; k++) { if ((i + k) < cHeight) { wSum += wCoeff[k] * bIn[((i + k) * cHeight) + j]; } else { // reflect at border. i + k >= cHeight so // 2*cWidth - (i + k + 1) < cHeight final int cPos = (2 * cHeight) - (i + k + 1); wSum += wCoeff[k] * bIn[(cPos * cHeight) + j]; } } /* * Gaussian coefficients are scaled so sum is 256. */ wSum = wSum >> 8; bResult[(i * cHeight) + j] = (byte) wSum; } } super.setOutput(result); } /** * Returns the current value of sigma. * * @return the sigma value */ public int getSigma() { return cSigma; } /** * sets a new value for sigma. Sigma controls the frequency of edges that * the operator responds to. A small sigma value gives less blur. * * @param cSigma * the new sigma value * @throws ImageError * if cSigma is out of range -- less than or equal to 1 or * greater than the number of coefficients we're precomputed. */ public void setSigma(final int cSigma) throws ImageError { if ((cSigma <= 1) || (cSigma >= nCoeff.length)) { throw new ImageError(ImageError.PACKAGE.ALGORITHM, AlgorithmErrorCodes.PARAMETER_OUT_OF_RANGE, new Integer(cSigma).toString(), new Integer(1).toString(), new Integer(nCoeff.length).toString()); } this.cSigma = cSigma; } /** * returns a string describing this Gaussian blur. * * @return a string describing the Gaussian blur. */ @Override public String toString() { return super.toString() + " (" + cSigma + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy