anisostropic diffusion java implementation

Upload: 36rohit

Post on 14-Apr-2018

222 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/29/2019 Anisostropic diffusion java implementation

    1/50

    12/11/2008

    Anisotropic Diffusion Model forEdge Detection: a JavaImplementation

    Jos Iguelmar Miranda

  • 7/29/2019 Anisostropic diffusion java implementation

    2/50

    Jos Iguelmar Miranda

    1

    Anisotropic Diffusion Model for

    Edge Detection: a Java

    Implementation

    Introduction

    The purpose of this document is to present the Java implementation of the anisotropic

    diffusion filter to attenuate noise and detect edges in digital images, based on the model

    presented by Perona & Malik (1990). Edge detection is one of the most fundamental

    processes when analyzing digital images, with a great availability of algorithms. Edges are

    responsible for the delineation of an objects format. They are the transition regions and,

    generally, define the edges between the object and the background as well as the contour

    among intersecting or overlapping objects.

    This means that the edges of an object, in a scene, can be detected. This way, one can localize

    objects and have their basic properties measured, like area, perimeter, and shape. The edge

    detection process is a qualified tool in the image analyses. Noise is a common problem in

    digital images, due to assorted causes, like camera and lens used, sensor tilting, targets

    temperature, atmospheric effects, etc. It is unlike that the area of two pixels with the same

    gray level, in ground, will have the same gray level in the digital image. Noises belong to two

    groups: random and systematic. The random types are only perceived through a statistic

    distribution while systematic ones are easy to detect and suppress. The net result of noises in

    images is to produce a random variation in the pixels gray levels values, such that the ideal

    edge is not found in the available images.

    Random noise is always present in the image, but not the systematic. The problem is that the

    noise cannot be identified and measured precisely, since one cannot differentiate its

  • 7/29/2019 Anisostropic diffusion java implementation

    3/50

    Jos Iguelmar Miranda

    2

    contribution in the gray level values in the image pixels. Happily, sometimes, the random

    noise can be characterized by its effect in the image, expressed as a probability distribution

    with specific mean and standard deviation (Parker, 1997). Before working with an image, it is

    necessary to filter this kind of noise, normally, using an edge detection process.

    Generally, the edge detection operators can be classified in three groups: (a) those using

    partial derivatives, approximated by differences, in the discrete case of digital images, whose

    function is to identify places where there are great intensity changes; (b) those that model the

    edge with a small dimension kernel, showing abstract properties of an ideal edge; and (c)

    operators that use mathematical models to represent the edges, based on partial differential

    equations (PDE), or diffusion models, searching for the functions maxima or minima. The

    latter is the one presented here.

    Anisotropic diffusion or non linear processes, have been used lately to enhance the edge

    detection task and suppress image noise in several application fields, among others, medical

    images (Chung & Sapiro, 2000; Demirkaya, 2002); agriculture (Karantzalos & Argialas,

    2004), and three dimensional conformal radiotherapy (3D CRT) and intensity modulated

    radiation therapy (IMRT) (Gibou et al., 2005).

    The Anisotropic Diffusion Model

    The importance of describing an image in multiple scales was recognized in the initial years

    of computer vision. The formalism of this problem is tied to the idea of image filtering or

    transformation of its scale-space. Scale-space theory is a theoretical base for representing

    images or signals in multiple scales, developed by the image processing and signal processingcommunities. It is a formal theory to manipulate images structures in differing scales, such

    that attributes in major scales can be successively suppressed and a scale parameter, t, can be

    linked to each level of the scale-space representation. The basic idea for this approach is to

    embed the original image, I0(x, y), in a family of derived images, I(x, y; t), obtained by

    convolving the original image with a Gaussian kernel, G(x, y; t), of variance (time) t

    (Perona & Malik, 1990):

  • 7/29/2019 Anisostropic diffusion java implementation

    4/50

    Jos Iguelmar Miranda

    3

    (1)

    Where:

    I(x,y; t) =I0(x,y)* G(x,y; t) (2)

    The time tis a scale parameter: increases in tyield simpler images representations or coarse

    resolutions. The original image embedding in this one parameter family or simplified images

    is calledscale-space. This one parameter family resolution in t of derived imagery may be

    viewed as the solution of the heat conduction, or diffusion, equation (a second order

    differential partial equation):

    It = I=

    2

    fx

    2+2

    fy

    2(3)

    With the initial condition I(x, y; 0) = I0(x, y), the original image (Perona & Malik, 1990).

    There are variants showing that this is the canonical form to generate a linear scale-space,

    based on the fact that newer structures cannot be created from a minor to a major scale.

    Motivation for creating a representation of scale-space from data comes from the fact that

    objects in the real world are comprised of differing structures and scales. This implies that

    such objects, contrary to mathematically idealized entities, like points and lines, may appear

    in different ways, depending on the observation scale. For instance, the concept of a tree is

    suitable in a meter scale, whilst the concept of leaves and molecules is suitable in larger

    scales. In a computer vision system, analyzing an unknown scene, there is no way for

    someone to know, a priori, what scales are convenient to describe the data. This way, the only

    reasonable approach is to consider the description in all scales, simultaneously.

    From the scale-space representation, a great diversity of image processing and computer

    vision operations can be used, like feature detection, classification, segmentation, moving

    estimates, and shape calculation, based on combination of Gaussian derivatives in multiple

    scales.

    Koenderink (1986) motivated the diffusion equation formulation presenting two criteria: (1)

    causality: any feature at a coarse level of resolution possesses a cause (not necessarily

    unique) at a finer level of resolution; the reverse need not be true. This means that no spurious

  • 7/29/2019 Anisostropic diffusion java implementation

    5/50

    Jos Iguelmar Miranda

    4

    detail should be generated when the resolution is decreased; (2) homogeneity and isotropy: the

    blurring is required to be space invariant.

    The causality criterion does not require a Gaussian kernel to do the blurring, though it is the

    most used and simplest. Perona & Malik (1990) criticized this standard scale-space model and

    presented an additional set of criteria to obtain descriptions in multiple scales semantically

    meaningful, condition obtained by allowing variation in the diffusion coefficient. In their

    new proposal, the causality criterion is still satisfied.

    In the standard scale-space model the true positioning of an edge at a coarse scale is not

    directly available in the coarse scale image. Edges positions in the low resolution or coarse

    scales are shifted from their original position. The reason for this spatial distortion is due to

    the fact that the Gaussian blurring does not respect the natural boundaries of the objects in

    the scene, making them fuzzier.

    Based on these assumptions, Perona & Malik (1990) announced the criteria that must be

    satisfied for generating multiscale semantically meaningful description of images: (1)

    causality: a scale-space representation should have the property that no spurious detail should

    be generated passing from finer to coarser scale; (2) immediate localization: at each

    resolution, the region boundaries should be sharp and coincide with the semantically

    meaningful at that resolution; and (3) piecewise smoothing: at all scales, intraregion

    smoothing should occur preferentially over interregion smoothing.

    The solution addressed by the authors to modify the linear scale-space model happened in the

    diffusion equation, where the diffusion coefficient, c, was assumed to be a constant

    independent of the space localization. They demonstrated that a suitable choice ofc(x, y; t)

    would enable someone to satisfy the second and third criteria listed. Besides, this could be

    done without sacrificing the causality criterion. They proposed the following anisotropicdiffusion equation:

    It= div(c(x,y; t)I) = c(x,y; t)I+ cI (4)

    Where div is the divergence operator; e represent the gradient and Laplacian operators,

    respectively, with respect to the space variable. Equation (4) becomes the isotropic heat

    diffusion equationIt= cIifc(x,y; t) is a constant.

  • 7/29/2019 Anisostropic diffusion java implementation

    6/50

    Jos Iguelmar Miranda

    5

    Suppose that at time (scale) t, the appropriate location of the regions edges were known for

    that scale. The goal was smoothing within a region instead of smoothing across the edges.

    This was done by adjusting the conduction coefficient to be one within each region and zero

    at their edges. The smoothing could happen separately in each region with no interactions

    between regions. The edges would remain sharp.

    The success of the diffusion process in satisfying the three listed criteria depended on how

    precise was the estimated hit of the edges location. A good estimate for edges position with

    outstanding results was the gradient of the brightness function. The authors showed that if the

    diffusion coefficient was chosen locally as a function of the magnitude of the gradient of the

    brightness function according to:

    c(x,y; t) =g(||I(x,y; t)||) (5)

    Then the edges brightness would be preserved and outlined if the function g() was

    appropriately chosen. The choice ofg(), according to the authors, was reduced to a subclass

    of functions monotonically decreasing.

    Case study

    Equation (4) can be discretized in a squared lattice, or 4-nearest-neighbors, with brightness

    values (pixels) associated with the nodes and the conduction coefficients associated with the

    arcs of the lattice. A discretization of the Laplacian can be used according to:

    (6)

    Where 0 in order to keep the numeric schema stable; N, S, E, and W are the

    mnemonic subscripts for North, South, East and West; the superscripts and subscripts on the

    square brackets are applied to all the terms it encloses, and the symbol indicates nearest-

    neighbors differences:

  • 7/29/2019 Anisostropic diffusion java implementation

    7/50

    Jos Iguelmar Miranda

    6

    (7)

    The gradient value can be computed in differing neighborhood structures achieving different

    results between accuracy and locality. The simplest choice consists in approximating the norm

    of the gradient at each arc location with the absolute value of its projection along the direction

    of the arc, according to:

    (8)

    This is not the exact discretization of (4), but of a similar diffusion equation in which the

    conduction tensor is diagonal with input valuesg(|Ix|) andg(|Iy|) instead ofg(||Ix||) andg(||Ix||).

    This discretization schema preserves the properties of the continuous equation (4), thus,

    keeping the total brightness quantity of the image.

    Equations (6), (7), and (8) were used to generate the following images (Fig. 1). The original

    image represented the initial conditions and adiabatic boundary conditions, i.e., setting the

    conduction coefficient equals to zero at the edges of the image. If a constant value is assigned

    to the conduction coefficient, c, then it yields a Gaussian smoothing. The use of different

    functions forg() yielded similar results. Images produced in this document usedg() as:

    (9)

    The scale-space produced by this function emphasizes high contrast edges over low contrast

    edges.

    In the upper left corner of Fig. 1 is the original image. All other images were filtered with the

    anisotropic diffusion algorithm: upper right corner, filtered after five iterations; lower left

    corner, after ten iterations; and lower right corner, after twenty iterations. As the iterations

    increases, intraregions details are lost, while the borders are kept. For instance, details of

  • 7/29/2019 Anisostropic diffusion java implementation

    8/50

    Jos Iguelmar Miranda

    7

    sugar cane plantation rows, differing spectral values inside the center pivot, fringing

    vegetation and bare soil are progressively vanishing, disappearing, eventually.

  • 7/29/2019 Anisostropic diffusion java implementation

    9/50

    Jos Iguelmar Miranda

    8

    Figure 1 Anisotropic diffusion: original and filtered images (detail in text body)

    The source code

    Below, is the source code for the program AnisotropicDiffusionFilter.java. The program was

    developed as a standard Java code. It uses the additional Matriz.java program, also added.

    You can add them to an IDE, like NetBeans or Eclipse, or simply compile and execute

    through a DOS prompt. Initially, it was developed to run in a DOS prompt, as you can see

  • 7/29/2019 Anisostropic diffusion java implementation

    10/50

    Jos Iguelmar Miranda

    9

    how it reads the needed parameters. Running the program with the threshold parameter equals

    to fifteen yields good response to edge preservation. Also, using Perona-Malik function one

    gives better results than function two, which trends to blur the edges. Using standard

    deviation value greater than zero also blurs the image edges. The iterations parameter works

    within regions, leaving them smoother. As this value increases, more intraregions details are

    lost.

    /***********************************************************************************

    AnisotropicDiffusionFilter.java - noise attenuation using anisotropic diffusion.

    WRITTEN BY: Jos Iguelmar Miranda & Joo Camargo Neto.

    DATE: November 2006

    DOCUMENTATION:

    See http://www.cnptia.embrapa.br/files/ct72.pdf

    Copyright (c) 2006 Embrapa Informtica Agropecuria

    PERMISSION TO COPY:

    This program is free software, under the GNU General Public License (GPL); permission to use, copy andmodify this software and its documentation for NON-COMMERCIAL purposes is granted, without fee,

    provided that an acknowledgement to the authors, Jos Iguelmar Miranda & Joo Camargo Neto, atwww.cnptia.embrapa.br, appears in all copies.

    Embrapa Informtica Agropecuria makes no representations about the suitability or fitness of the software forany or for a particular purpose. Embrapa Informtica Agropecuria shall not be liable for any damages sufferedas a result of using, modifying or distributing this software or its derivatives.

    For a copy of GNU General Public License, write to:

    Free Software Foundation, Inc.,

    59 Temple Street, Suite 330, Boston, MA 02111-1307 USA.

    **********************************************************************************

    Description:

  • 7/29/2019 Anisostropic diffusion java implementation

    11/50

    Jos Iguelmar Miranda

    10

    This program implements the edge detection filter using the anisotropic diffusion model.

    Reference paper:

    PERONA, P.; MALIK, J. "Scale-space and edge detection using anisotropic diffusion",IEEE Transactions onPattern Analysis and Machine Intelligence, 12(7), pp. 629-639, 1990.

    This program uses Matriz.java.

    Input:

    1. 'iterations': how many times to filter the source image. It means time, in

    equations (1) and (2) in the body of the document.

    For instance, iterations = 10.

    2. 'Perona-Malik function':

    '1': g(grad(I)) = exp{-(|grad(I)|/K)^2} [equation (9) in this document]

    '2': g(grad(I)) = 1/{1+(|grad(I)|/K) 2} [equation not available in this doc]

    The scale-space yielded by these functions is different:

    - The former equation emphasizes edges with high contrast over low contrast edges.

    - The latter equation emphasizes wide regions over small ones.

    3. 'threshold': a value related to 'K', below which 'g(.)' is monotonically increasing and above, 'g(.)' ismonotonically decreasing; as a result, smoothes small discontinuities and enhance edges. Forinstance, threshold = 15.

    4. 'sigma2': if exists, computes the gradient of the diffusion coefficient, convolved with the Gaussian kernelusing variance = sigma2. For instance, if not using sigma, then sigma2 = 0.0.

    Output:

    JFrame with source and filtered images.

    Informaes do CVS:

    $Source$:

    $Revision$:

    $Date$:

  • 7/29/2019 Anisostropic diffusion java implementation

    12/50

    Jos Iguelmar Miranda

    11

    ***********************************************************************************/

    // generic packagesimport java.io.File;

    import java.io.IOException;

    // AWT packages

    import java.awt.image.WritableRaster;

    import java.awt.image.BufferedImage;

    import java.awt.image.Raster;

    import java.awt.GridLayout;

    // Swing packages for GUI

    import javax.swing.JFrame;

    import javax.swing.JLabel;

    import javax.swing.ImageIcon;

    import javax.swing.JScrollPane;

    // immediate reading mode for J2SE 1.4+

    import javax.imageio.ImageIO;

    public class AnisotropicDiffusionFilter extends JFrame {

    public static void main(String args[]) {

    int iterations = 0, threshold = 0, typePM = 1;

    double sigma2 = 0.0;

    // All parms ok?

    if (args.length != 5) {

    String msga = "Usage: java -cp . AnisotropicDiffusionFilter ";

    String msgb = " ";

    String msgc = " ";

    String msgd = "";

  • 7/29/2019 Anisostropic diffusion java implementation

    13/50

    Jos Iguelmar Miranda

    12

    System.out.println(msga + msgb + msgc + msgd);

    System.exit(0);

    }

    // Show JFrame decorated with Swing

    JFrame.setDefaultLookAndFeelDecorated(true);

    long eq_time = System.currentTimeMillis();

    try {

    iterations = Integer.parseInt(args[1]);

    } catch (NumberFormatException e) {

    String st = "Parameter 'iterations' invalid";

    System.out.println(st);

    System.exit(0);

    }

    try {

    typePM = Integer.parseInt(args[2]);

    } catch (NumberFormatException e) {

    String st = "Parameter 'type Perona-Malik function' invalid";

    System.out.println(st);

    System.exit(0);

    }

    try {

    threshold = Integer.parseInt(args[3]);

    } catch (NumberFormatException e) {

    String st = "Parameter 'threshold' invalid";

    System.out.println(st);

    System.exit(0);

    }

    if (typePM < 1 || typePM > 2) {

  • 7/29/2019 Anisostropic diffusion java implementation

    14/50

    Jos Iguelmar Miranda

    13

    System.out.println("Defining type Perona-Malik function = 1");

    typePM = 1;

    }

    try {

    sigma2 = Double.parseDouble(args[4]);

    } catch (NumberFormatException e) {

    String st = "Parameter 'sigma2' invalid";

    System.out.println(st);

    System.exit(0);

    }

    if (sigma2 < 0.0) {

    System.out.println("Using sigma2 = 0.0");

    sigma2 = 0.0;

    }

    System.out.println("\nAnisotropic diffusion filter - Parameters:\n");

    String st = "\t#iterations: ";

    System.out.println(st + iterations);

    st = "\n\ttype Perona-Malik function: ";

    System.out.println(st + typePM);

    st = "\n\tthreshold: ";

    System.out.println(st + threshold);

    st = "\n\tvariance: ";

    System.out.println(st + sigma2 + "\n");

    AnisotropicDiffusionFilter c = new AnisotropicDiffusionFilter(args[0], iterations, typePM,

    threshold, sigma2);

    eq_time = System.currentTimeMillis() - eq_time;

    String msg = "AnisotropicDiffusionFilter: run time ";

    System.out.println(msg + eq_time + " milisseg.");

  • 7/29/2019 Anisostropic diffusion java implementation

    15/50

  • 7/29/2019 Anisostropic diffusion java implementation

    16/50

    Jos Iguelmar Miranda

    15

    else

    bordas = AnisotropicDiffusion(pixels, iterations, "pm2", threshold, sigma2);

    dest = criaImagem(bordas);

    // ...else, color image} else {

    bordasTriplo = new int[3][w][h];

    pixels = lePixels(src, 0);

    if (typePM == 1)

    bordasTriplo[0] = AnisotropicDiffusion(pixels, iterations, "pm1", threshold, sigma2);

    else

    bordasTriplo[0] = AnisotropicDiffusion(pixels, iterations, "pm2", threshold, sigma2);

    pixels = lePixels(src, 1);

    if (typePM == 1)

    bordasTriplo[1] = AnisotropicDiffusion(pixels, iterations, "pm1", threshold, sigma2);

    else

    bordasTriplo[1] = AnisotropicDiffusion(pixels, iterations, "pm2", threshold, sigma2);

    pixels = lePixels(src, 2);

    if (typePM == 1)

    bordasTriplo[2] = AnisotropicDiffusion(pixels, iterations, "pm1", threshold, sigma2);

    else

    bordasTriplo[2] = AnisotropicDiffusion(pixels, iterations, "pm2", threshold, sigma2);

    dest = criaImagem(bordasTriplo);

    }

    // Record image

    String search = ".";

    int i = file.getName().indexOf(search);

    String prefixo = file.getName().substring(0, i);

    try {

    String nome = "C:\\temp\\" + prefixo + "_FDA" + iterations + ".png";

    ImageIO.write(dest, "png", new File(nome));

    System.out.println("\nStoring image -> " + nome + "\n");

    } catch (IOException e) {

    System.out.println("Problem storing file");

  • 7/29/2019 Anisostropic diffusion java implementation

    17/50

    Jos Iguelmar Miranda

    16

    System.exit(0);

    }

    // Define gridLayout 1 x 2

    getContentPane().setLayout(new GridLayout(1, 2));img1 = new JLabel(new ImageIcon(src));

    img2 = new JLabel(new ImageIcon(dest));

    setSize(2*w, h);

    getContentPane().add(new JScrollPane(img1));

    getContentPane().add(new JScrollPane(img2));

    }

    private int[][] lePixels(BufferedImage src, int banda) {

    int w, h, pixels[][] = null;

    w = src.getWidth();

    h = src.getHeight();

    pixels = new int[w][h];

    Raster srcR = src.getRaster();

    for (int i = 0; i < h; i++)

    for (int j = 0; j < w; j++) {

    pixels[j][i] = srcR.getSample(j, i, banda);

    }

    return pixels;

    }

    private int[][] AnisotropicDiffusion(int[][] in, int iter, String metodo,

    int threshold, double sigma2){

    int h, w, bfi[][], inRet[][];

    double dt, imagemD[][];

    Matriz matrizPM = new Matriz(in);

    // Gradient copies

  • 7/29/2019 Anisostropic diffusion java implementation

    18/50

    Jos Iguelmar Miranda

    17

    Matriz cN, cS, cL, cO, mGradienteN, mGradienteS, mGradienteL, mGradienteO,

    j0 = null;

    w = in.length;

    h = in[0].length;bfi = new int[w][h];

    dt = 0.2;

    System.out.println("Running...");

    for (int i = 0; i < iter; i++){

    System.out.print(".");

    if (sigma2 > 0.0) {

    j0 = matrizPM.copy();

    imagemD = matrizPM.getArrayReference();

    for (int lin = 0; lin < h; lin++)

    for (int col = 0; col < w; col++)

    bfi[col][lin] = (int) imagemD[col][lin];

    inRet = gauss(bfi, 5, sigma2);

    matrizPM = new Matriz(inRet);

    }

    mGradienteN = matrizPM.copy();

    mGradienteS = matrizPM.copy();

    mGradienteL = matrizPM.copy();

    mGradienteO = matrizPM.copy();

    // Gradient in directions N, S, L (E) and O (W)

    mGradienteN.gradiente(4);

    mGradienteS.gradiente(3);

    mGradienteL.gradiente(2);

    mGradienteO.gradiente(1);

    // Save copy of images with gradient for further calculations

    cN = mGradienteN.copy();

  • 7/29/2019 Anisostropic diffusion java implementation

    19/50

    Jos Iguelmar Miranda

    18

    cS = mGradienteS.copy();

    cL = mGradienteL.copy();

    cO = mGradienteO.copy();

    if (metodo.equals("pm1")){

    cN.abs();

    cN.divide((double) threshold);

    cN.elevaQuadrado();

    cN.timesEquals(-1.0);

    cN.exp();

    cS.abs();

    cS.divide((double) threshold);

    cS.elevaQuadrado();

    cS.timesEquals(-1.0);

    cS.exp();

    cL.abs();

    cL.divide((double) threshold);

    cL.elevaQuadrado();

    cL.timesEquals(-1.0);

    cL.exp();

    cO.abs();

    cO.divide((double) threshold);

    cO.elevaQuadrado();

    cO.timesEquals(-1.0);

    cO.exp();

    } else

    if (metodo.equals("pm2")){

    cN.abs();

    cN.divide((double) threshold);

    cN.elevaQuadrado();

    cN.adiciona(1.0);

  • 7/29/2019 Anisostropic diffusion java implementation

    20/50

    Jos Iguelmar Miranda

    19

    cN.inverteElemento();

    cS.abs();

    cS.divide((double) threshold);cS.elevaQuadrado();

    cS.adiciona(1.0);

    cS.inverteElemento();

    cL.abs();

    cL.divide((double) threshold);

    cL.elevaQuadrado();

    cL.adiciona(1.0);

    cL.inverteElemento();

    cO.abs();

    cO.divide((double) threshold);

    cO.elevaQuadrado();

    cO.adiciona(1.0);

    cO.inverteElemento();

    }

    if (sigma2 > 0.0){

    mGradienteN = j0.copy();

    mGradienteS = j0.copy();

    mGradienteL = j0.copy();

    mGradienteO = j0.copy();

    // Compute filtered image gradient in direction N, S, L (E) and O (W)

    mGradienteN.gradiente(4);

    mGradienteS.gradiente(3);

    mGradienteL.gradiente(2);

    mGradienteO.gradiente(1);

    matrizPM = j0.copy();

    }

  • 7/29/2019 Anisostropic diffusion java implementation

    21/50

    Jos Iguelmar Miranda

    20

    cN.multiplica(mGradienteN);

    cS.multiplica(mGradienteS);

    cL.multiplica(mGradienteL);cO.multiplica(mGradienteO);

    cN.plusEquals(cS);

    cO.plusEquals(cL);

    cN.plusEquals(cO);

    cN.timesEquals(dt);

    matrizPM.plusEquals(cN);

    }

    imagemD = matrizPM.getArrayReference();

    for (int i = 0; i < h; i++)

    for (int j = 0; j < w; j++)

    bfi[j][i] = (int) imagemD[j][i];

    System.out.println("\n");

    return bfi;

    }

    private BufferedImage criaImagem(int[][] in) {

    int w, h, tipo, pixels[], ind = 0;

    BufferedImage dest = null;

    w = in.length;

    h = in[0].length;

    pixels = new int[w*h];

    tipo = BufferedImage.TYPE_BYTE_GRAY;

    dest = new BufferedImage(w, h, tipo);

    WritableRaster destWR = dest.getRaster();

  • 7/29/2019 Anisostropic diffusion java implementation

    22/50

    Jos Iguelmar Miranda

    21

    for(int lin = 0; lin < h; lin++)

    for(int col = 0; col < w; col++)

    pixels[ind++] = in[col][lin];

    destWR.setPixels(0, 0, w, h, pixels);

    return dest;

    }

    private BufferedImage criaImagem(int[][][] in) {

    int w, h, tipo;

    BufferedImage dest = null;

    w = in[0].length;

    h = in[0][0].length;

    tipo = BufferedImage.TYPE_3BYTE_BGR;

    dest = new BufferedImage(w, h, tipo);

    WritableRaster destWR = dest.getRaster();

    for(int lin = 0; lin < h; lin++)

    for(int col = 0; col < w; col++)

    for(int b = 0; b < 3; b++)

    destWR.setSample(col, lin, b, in[b][col][lin]);

    return dest;

    }

    private int[][] gauss(int[][] in, int ks, double sigma2) {

    int w, h, hks, // half kernel size

    eI[][] = null, tmpVec[];

    double flt[][] = null, x = 0.0, y = 0.0, soma = 0.0, xL = 0.0, xR = 0.0, xU = 0.0, xD = 0.0;

    w = in.length;

    h = in[0].length;

    hks = (int) (ks - 1)/2;

  • 7/29/2019 Anisostropic diffusion java implementation

    23/50

    Jos Iguelmar Miranda

    22

    flt = new double[2*hks+1][2*hks+1];

    if (h < ks) {

    System.out.println ("1D convolution happened");

    } else {// 2D convolution

    for (int y1 = -hks; y1

  • 7/29/2019 Anisostropic diffusion java implementation

    24/50

    Jos Iguelmar Miranda

    23

    eI[w+hks+k][lin] = (int) xR;

    }

    // Copy image to the center of vector eI

    eI[col+hks][lin+hks] = in[col][lin];}

    }

    // Vertical expansion

    int weI = eI.length;

    int heI = eI[0].length;

    for (int col = 0; col < weI; col++){

    xU = mean(retornaPixels(eI, hks, col, hks, "vertical"));

    for (int k = 0; k < hks; k++)

    eI[col][k] = (int) xU;

    xD = mean(retornaPixels(eI, heI-2*hks, col, hks, "vertical"));

    for (int k = 0; k < hks; k++)

    eI[col][heI-hks+k] = (int) xD;

    }

    } else {}

    }

    return convolve(eI, flt);

    }

    private int[][] convolve(int[][] in, double [][]filtro){

    int wI = in.length;

    int hI = in[0].length;

    int wF = filtro.length;

    int hF = filtro[0].length;

    int hks = (wF -1)/2;

    double soma;

    int[][] vecRet = new int[wI-2*hks][hI - 2*hks];

    for(int lin = 0; lin < hI - 2*hks; lin++){

    for(int col = 0; col < wI - 2*hks; col++){

  • 7/29/2019 Anisostropic diffusion java implementation

    25/50

    Jos Iguelmar Miranda

    24

    soma = 0.0;

    for(int linF = 0; linF < hF; linF++){

    for(int colF = 0; colF < wF; colF++){

    soma += in[col+colF][lin+linF]*filtro[linF][colF];}

    }

    soma /= hF*wF;

    vecRet[col][lin] = (int) soma;

    }

    }

    return vecRet;

    }

    //=============== Mean =====================

    private double mean(int[] p) {

    double sum = 0; // sum of all the elements

    for (int i = 0; i < p.length; i++) {

    sum += p[i];

    }

    return sum / p.length;

    }

    // Return pixels values within an image

    private int[] retornaPixels(int[][] in, int lin, int col, int tam, String dir) {

    int i, vec[] = null;

    if (dir.equals("horizontal")){

    if(col + tam

  • 7/29/2019 Anisostropic diffusion java implementation

    26/50

    Jos Iguelmar Miranda

    25

    vec = new int[tam];

    for (i = 0; i < tam; i++)

    vec[i] = in[col][lin+i];

    }}

    return vec;

    }

    } // end of AnisotropicDiffusionFilter

    /***********************************************************************************

    WRITTEN BY: Dr Michael Thomas Flanagan

    DATE: June 2002

    UPDATE: 21 April 2004, 19 January 2005, 1 May 2005

    DOCUMENTATION:

    See Michael Thomas Flanagan's Java library on-line web page:

    Matrix.html

    Copyright (c) April 2004 Michael Thomas Flanagan

    PERMISSION TO COPY:

    Permission to use, copy and modify this software and its documentation for

    NON-COMMERCIAL purposes is granted, without fee, provided that an acknowledgement

    to the author, Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in

    all copies.

    Dr Michael Thomas Flanagan makes no representations about the suitability

    or fitness of the software for any or for a particular purpose.Michael Thomas Flanagan shall not be liable for any damages suffered

    as a result of using, modifying or distributing this software or its derivatives.

    Informaes do CVS:

    $Source$:

    $Revision$:

  • 7/29/2019 Anisostropic diffusion java implementation

    27/50

    Jos Iguelmar Miranda

    26

    $Date$:

    ***********************************************************************************/

    import java.text.DecimalFormat;

    import java.util.Arrays;

    public class Matriz {

    // DATA VARIABLES

    private int nrow = 0; // number of rows

    private int ncol = 0; // number of columns

    private double matriz[][] = null; // 2-D Matrizprivate int index[] = null; // row permutation index

    private double dswap = 1.0D; // row swap index

    private boolean matrizCheck = true; // check on matrix status

    // true - no problems encountered

    // false - attempted a LU decomposition on a singular matrix

    private static final double TINY = 1.0e-30;

    // CONSTRUCTORS

    // Construct a nrow x ncol matrix of complex variables all equal to zero

    public Matriz(int nrow, int ncol){

    this.nrow = nrow;

    this.ncol = ncol;

    this.matriz = new double[nrow][ncol];

    this.index = new int[nrow];

    for (int i = 0; i < nrow; i++)

    this.index[i] = i;}

    // Construct a nrow x ncol matrix of complex variables all equal to

    // the complex number const

    public Matriz(int nrow, int ncol, double constant){

    this.nrow = nrow;

    this.ncol = ncol;

  • 7/29/2019 Anisostropic diffusion java implementation

    28/50

    Jos Iguelmar Miranda

    27

    this.matriz = new double[nrow][ncol];

    for (int i = 0; i < nrow; i++){

    for (int j = 0; j < nrow; j++)

    this.matriz[i][j] = constant;

    }

    this.index = new int[nrow];

    for (int i = 0; i < nrow; i++)

    this.index[i] = i;

    }

    // Construct matrix with a reference to an existing nrow x ncol 2-D

    // array of complex variables

    public Matriz(double[][] twoD){this.nrow = twoD.length;

    this.ncol = twoD[0].length;

    for (int i = 0; i < nrow; i++){

    if (twoD[i].length != ncol)

    throw new IllegalArgumentException("All rows must have the same length");

    }

    this.matriz = twoD;

    this.index = new int[nrow];

    for (int i = 0; i < nrow; i++)

    this.index[i] = i;

    }

    // Construct matrix with a reference to the 2D matrix and

    // permutation index of an existing ComplexMatriz bb.

    public Matriz(Matriz bb){

    this.nrow = bb.nrow;

    this.ncol = bb.ncol;this.matriz = bb.matriz;

    this.index = bb.index;

    this.dswap = bb.dswap;

    }

    // METHODS

  • 7/29/2019 Anisostropic diffusion java implementation

    29/50

    Jos Iguelmar Miranda

    28

    // SET VALUES

    // Set the matrix with a copy of an existing nrow x ncol 2-D matrix of

    // complex variables

    public void setTwoDarray(double[][] aarray){

    String msgA = "row length of this ComplexMatriz differs from that ";

    String msgA1 = "of the 2D array argument";

    String msgB = "column length of this ComplexMatriz differs from that ";

    String msgB1 = "of the 2D array argument";

    String msgC = "All rows must have the same length";

    if (this.nrow != aarray.length)

    throw new IllegalArgumentException(msgA + msgA1);

    if (this.ncol != aarray[0].length)

    throw new IllegalArgumentException(msgB + msgB1);for (int i = 0; i < nrow; i++){

    if (aarray[i].length != ncol)

    throw new IllegalArgumentException(msgC);

    for (int j = 0; j < ncol; j++){

    this.matriz[i][j] = aarray[i][j];

    }

    }

    }

    // Set an individual array element

    // i = row index

    / / j = column index

    // aa = value of the element

    public void setElement(int i, int j, double aa){

    this.matriz[i][j] = aa;

    }

    // Set a sub-matrix starting with column index i, row index j

    // and ending with column index k, row index l

    public void setSubMatriz(int i, int j, int k, int l, double[][] smat){

    if (i > k)

    throw new IllegalArgumentException("row indices inverted");

    if (j > l)

    throw new IllegalArgumentException("column indices inverted");

  • 7/29/2019 Anisostropic diffusion java implementation

    30/50

    Jos Iguelmar Miranda

    29

    int n = k-i+1, m = j-l+1;

    for (int p = 0; p < n; p++){

    for (int q = 0; q < m; p++){

    this.matriz[i+p][j+q] = smat[i][j];

    }

    }

    }

    // Set a sub-matrix

    // row = array of row indices

    // col = array of column indices

    public void setSubMatriz(int[] row, int[] col, double[][] smat){

    int n = row.length;int m = col.length;

    for (int p = 0; p < n; p++){

    for (int q = 0; q < m; p++){

    this.matriz[row[p]][col[q]] = smat[p][q];

    }

    }

    }

    // Get the value of matrixCheck

    public boolean getMatrizCheck(){

    return this.matrizCheck;

    }

    // SPECIAL MATRICES

    // Construct an identity matrix

    public static Matriz identityMatriz(int nrow){

    Matriz u = new Matriz(nrow, nrow);for (int i = 0; i < nrow; i++){

    u.matriz[i][i] = 1.0;

    }

    return u;

    }

    // Construct a complex scalar matrix

  • 7/29/2019 Anisostropic diffusion java implementation

    31/50

    Jos Iguelmar Miranda

    30

    public static Matriz scalarMatriz(int nrow, double diagconst){

    Matriz u = new Matriz(nrow, nrow);

    double[][] uarray = u.getArrayReference();

    for (int i = 0; i < nrow; i++){

    for (int j = i; j < nrow; j++){

    if (i == j){

    uarray[i][j] = diagconst;

    }

    }

    }

    return u;

    }

    // Construct a diagonal matrix

    public static Matriz diagonalMatriz(int nrow, double[] diag){

    String msgA = "matriz dimension differs from diagonal array length";

    if (diag.length != nrow)

    throw new IllegalArgumentException(msgA);

    Matriz u = new Matriz(nrow, nrow);

    double[][] uarray = u.getArrayReference();

    for (int i = 0; i < nrow; i++){

    uarray[i][i] = diag[i];

    }

    return u;

    }

    // GET VALUES

    // Return the number of rows

    public int getNrow(){

    return this.nrow;}

    // Return the number of columns

    public int getNcol(){

    return this.ncol;

    }

  • 7/29/2019 Anisostropic diffusion java implementation

    32/50

    Jos Iguelmar Miranda

    31

    // Return a reference to the internal 2-D array

    public double[][] getArrayReference(){

    return this.matriz;

    }

    // Return a reference to the internal 2-D array

    // included for backward compatibility with incorrect earlier documentation

    public double[][] getArrayPointer(){

    return this.matriz;

    }

    // Return a copy of the internal 2-D array

    public double[][] getArrayCopy(){double[][] c = new double[this.nrow][this.ncol];

    for (int i = 0; i < nrow; i++){

    for (int j = 0; j < ncol; j++){

    c[i][j] = this.matriz[i][j];

    }

    }

    return c;

    }

    // Return a single element of the internal 2-D array

    public double getElement(int i, int j){

    return this.matriz[i][j];

    }

    // Return a single element of the internal 2-D array

    // included for backward compatibility with incorrect earlier documentation

    public double getElementCopy(int i, int j){return this.matriz[i][j];

    }

    // Return a single element of the internal 2-D array

    // included for backward compatibility with incorrect earlier documentation

    public double getElementPointer(int i, int j){

    return this.matriz[i][j];

  • 7/29/2019 Anisostropic diffusion java implementation

    33/50

    Jos Iguelmar Miranda

    32

    }

    // Return a sub-matrix starting with column index i, row index j

    // and ending with column index k, row index l

    public Matriz getSubMatriz(int i, int j, int k, int l){

    if (i > k)

    throw new IllegalArgumentException("row indices inverted");

    if (j > l)

    throw new IllegalArgumentException("column indices inverted");

    int n = k-i+1, m = j-l+1;

    Matriz smat = new Matriz(n, m);

    double[][] sarray = this.getArrayReference();

    for (int p = 0; p < n; p++){for (int q = 0; q < m; p++){

    sarray[p][q] = this.matriz[i+p][j+q];

    }

    }

    return smat;

    }

    // Return a sub-matrix

    // row = array of row indices

    // col = array of column indices

    public Matriz getSubMatriz(int[] row, int[] col){

    int n = row.length;

    int m = col.length;

    Matriz smat = new Matriz(n, m);

    double[][] sarray = this.getArrayReference();

    for (int i = 0; i < n; i++){

    for (int j = 0; j < m; j++){sarray[i][j] = this.matriz[row[i]][col[j]];

    }

    }

    return smat;

    }

    // Return a reference to the permutation index array

  • 7/29/2019 Anisostropic diffusion java implementation

    34/50

    Jos Iguelmar Miranda

    33

    public int[] getIndexReference(){

    return this.index;

    }

    // Return a reference to the permutation index array

    // included for backward compatibility with incorrect earlier documentation

    public int[] getIndexPointer(){

    return this.index;

    }

    // Return a copy of the permutation index array

    public int[] getIndexCopy(){

    int[] indcopy = new int[this.nrow];for (int i = 0; i < this.nrow; i++){

    indcopy[i] = this.index[i];

    }

    return indcopy;

    }

    // Return the row swap index

    public double getSwap(){

    return this.dswap;

    }

    // COPY

    // Copy a Matriz [static method]

    public static Matriz copy(Matriz a){

    if (a == null){

    return null;

    } else {int nr = a.getNrow();

    int nc = a.getNcol();

    double[][] aarray = a.getArrayReference();

    Matriz b = new Matriz(nr,nc);

    b.nrow = nr;

    b.ncol = nc;

    double[][] barray = b.getArrayReference();

  • 7/29/2019 Anisostropic diffusion java implementation

    35/50

    Jos Iguelmar Miranda

    34

    for (int i = 0; i < nr; i++){

    for (int j = 0; j < nc; j++){

    barray[i][j] = aarray[i][j];

    }

    }

    for (int i = 0; i < nr; i++)

    b.index[i] = a.index[i];

    return b;

    }

    }

    // Copy a Matriz [instance method]public Matriz copy(){

    if (this == null){

    return null;

    } else {

    int nr = this.nrow;

    int nc = this.ncol;

    Matriz b = new Matriz(nr,nc);

    double[][] barray = b.getArrayReference();

    b.nrow = nr;

    b.ncol = nc;

    for (int i = 0; i < nr; i++){

    for (int j = 0; j < nc; j++){

    barray[i][j] = this.matriz[i][j];

    }

    }

    for (int i = 0; i < nr; i++)

    b.index[i] = this.index[i];

    return b;

    }

    }

    // Clone a Matriz

    public Object clone(){

  • 7/29/2019 Anisostropic diffusion java implementation

    36/50

    Jos Iguelmar Miranda

    35

    if (this == null){

    return null;

    } else {

    int nr = this.nrow;

    int nc = this.ncol;

    Matriz b = new Matriz(nr,nc);

    double[][] barray = b.getArrayReference();

    b.nrow = nr;

    b.ncol = nc;

    for (int i = 0; i < nr; i++){

    for (int j = 0; j < nc; j++){

    barray[i][j] = this.matriz[i][j];

    }}

    for (int i = 0; i < nr; i++)

    b.index[i] = this.index[i];

    return (Object) b;

    }

    }

    // ADDITION

    // Add this matrix to matrix B. This matrix remains unaltered [instance method]

    public Matriz plus(Matriz bmat){

    if ((this.nrow != bmat.nrow)||(this.ncol != bmat.ncol)){

    throw new IllegalArgumentException("Array dimensions do not agree");

    }

    int nr = bmat.nrow;

    int nc = bmat.ncol;

    Matriz cmat = new Matriz(nr,nc);

    double[][] carray = cmat.getArrayReference();for (int i = 0; i < nr; i++){

    for (int j = 0; j < nc; j++){

    carray[i][j] = this.matriz[i][j] + bmat.matriz[i][j];

    }

    }

    return cmat;

    }

  • 7/29/2019 Anisostropic diffusion java implementation

    37/50

    Jos Iguelmar Miranda

    36

    // Add matrices A and B [static method]

    public static Matriz plus(Matriz amat, Matriz bmat){

    if ((amat.nrow != bmat.nrow)||(amat.ncol != bmat.ncol)){

    throw new IllegalArgumentException("Array dimensions do not agree");

    }

    int nr = amat.nrow;

    int nc = amat.ncol;

    Matriz cmat = new Matriz(nr,nc);

    double[][] carray = cmat.getArrayReference();

    for (int i = 0; i < nr; i++){

    for (int j = 0; j < nc; j++){

    carray[i][j] = amat.matriz[i][j] + bmat.matriz[i][j];}

    }

    return cmat;

    }

    // Add matrix B to this matrix [equivalence of +=]

    public void plusEquals(Matriz bmat){

    if ((this.nrow != bmat.nrow)||(this.ncol != bmat.ncol)){

    throw new IllegalArgumentException("Array dimensions do not agree");

    }

    int nr = bmat.nrow;

    int nc = bmat.ncol;

    for (int i = 0; i < nr; i++){

    for (int j = 0; j < nc; j++){

    this.matriz[i][j] += bmat.matriz[i][j];

    }

    }}

    // SUBTRACTION

    // Subtract matrix B from this matrix.

    // This matrix remains unaltered [instance method]

    public Matriz minus(Matriz bmat){

    if ((this.nrow != bmat.nrow)||(this.ncol != bmat.ncol)){

  • 7/29/2019 Anisostropic diffusion java implementation

    38/50

    Jos Iguelmar Miranda

    37

    throw new IllegalArgumentException("Array dimensions do not agree");

    }

    int nr = this.nrow;

    int nc = this.ncol;

    Matriz cmat = new Matriz(nr,nc);

    double[][] carray = cmat.getArrayReference();

    for (int i = 0; i < nr; i++){

    for (int j = 0; j < nc; j++){

    carray[i][j] = this.matriz[i][j] - bmat.matriz[i][j];

    }

    }

    return cmat;

    }

    // Subtract matrix B from matrix A [static method]

    public static Matriz minus(Matriz amat, Matriz bmat){

    if ((amat.nrow != bmat.nrow)||(amat.ncol != bmat.ncol)){

    throw new IllegalArgumentException("Array dimensions do not agree");

    }

    int nr = amat.nrow;

    int nc = amat.ncol;

    Matriz cmat = new Matriz(nr,nc);

    double[][] carray = cmat.getArrayReference();

    for (int i = 0; i < nr; i++){

    for (int j = 0; j < nc; j++){

    carray[i][j] = amat.matriz[i][j] - bmat.matriz[i][j];

    }

    }

    return cmat;

    }

    // Subtract matrix B from this matrix [equivlance of -=]

    public void minusEquals(Matriz bmat){

    if ((this.nrow != bmat.nrow)||(this.ncol != bmat.ncol)){

    throw new IllegalArgumentException("Array dimensions do not agree");

    }

    int nr = bmat.nrow;

  • 7/29/2019 Anisostropic diffusion java implementation

    39/50

    Jos Iguelmar Miranda

    38

    int nc = bmat.ncol;

    for (int i = 0; i < nr; i++){

    for (int j = 0; j < nc; j++){

    this.matriz[i][j] -= bmat.matriz[i][j];

    }

    }

    }

    // MULTIPLICATION

    // Multiply this matrix by a matrix. [instance method]

    // This matrix remains unaltered.

    public Matriz times(Matriz bmat){

    if (this.ncol != bmat.nrow)throw new IllegalArgumentException("Nonconformable matrices");

    Matriz cmat = new Matriz(this.nrow, bmat.ncol);

    double[][] carray = cmat.getArrayReference();

    double sum = 0.0D;

    for (int i = 0; i < this.nrow; i++){

    for (int j = 0; j < bmat.ncol; j++){

    sum = 0.0D;

    for (int k = 0; k < this.ncol; k++){

    sum += this.matriz[i][k]*bmat.matriz[k][j];

    }

    carray[i][j] = sum;

    }

    }

    return cmat;

    }

    // Multiply this matrix by a constant [instance method]

    // This matrix remains unaltered

    public Matriz times(double constant){

    Matriz cmat = new Matriz(this.nrow, this.ncol);

    double [][] carray = cmat.getArrayReference();

    for (int i = 0; i < this.nrow; i++){

  • 7/29/2019 Anisostropic diffusion java implementation

    40/50

    Jos Iguelmar Miranda

    39

    for (int j = 0; j < this.ncol; j++){

    carray[i][j] = this.matriz[i][j]*constant;

    }

    }

    return cmat;

    }

    // Multiply two complex matrices {static method]

    public static Matriz times(Matriz amat, Matriz bmat){

    if (amat.ncol != bmat.nrow)

    throw new IllegalArgumentException("Nonconformable matrices");

    Matriz cmat = new Matriz(amat.nrow, bmat.ncol);double [][] carray = cmat.getArrayReference();

    double sum = 0.0D;

    for (int i = 0; i < amat.nrow; i++){

    for (int j = 0; j < bmat.ncol; j++){

    sum = 0.0D;

    for (int k = 0; k < amat.ncol; k++){

    sum += (amat.matriz[i][k]*bmat.matriz[k][j]);

    }

    carray[i][j] = sum;

    }

    }

    return cmat;

    }

    // Multiply a matrix by a constant [static method]

    public static Matriz times(Matriz amat, double constant){Matriz cmat = new Matriz(amat.nrow, amat.ncol);

    double [][] carray = cmat.getArrayReference();

    for (int i = 0; i < amat.nrow; i++){

    for (int j = 0; j < amat.ncol; j++){

    carray[i][j] = amat.matriz[i][j]*constant;

    }

  • 7/29/2019 Anisostropic diffusion java implementation

    41/50

    Jos Iguelmar Miranda

    40

    }

    return cmat;

    }

    // Multiply this matrix by a matrix [equivalence of *=]

    public void timesEquals(Matriz bmat){

    if (this.ncol != bmat.nrow)

    throw new IllegalArgumentException("Nonconformable matrices");

    double sum = 0.0D;

    for (int i = 0; i < this.nrow; i++){

    for (int j = 0; j < bmat.ncol; j++){

    sum = 0.0D;for (int k = 0; k < this.ncol; k++){

    sum += (this.matriz[i][k]*bmat.matriz[k][j]);

    }

    this.matriz[i][j] = sum;

    }

    }

    }

    // Multiply this matrix by a constant [equivalence of *=]

    public void timesEquals(double constant){

    for (int i = 0; i < this.nrow; i++){

    for (int j = 0; j < this.ncol; j++){

    this.matriz[i][j] *= constant;

    }

    }

    }

    // TRANSPOSE

    // Transpose of a complex matrix [instance method]

    public Matriz transpose(){

    Matriz tmat = new Matriz(this.ncol, this.nrow);

    double[][] tarray = tmat.getArrayReference();

    for (int i = 0; i < this.ncol; i++){

  • 7/29/2019 Anisostropic diffusion java implementation

    42/50

    Jos Iguelmar Miranda

    41

    for (int j = 0; j < this.nrow; j++){

    tarray[i][j] = this.matriz[j][i];

    }

    }

    return tmat;

    }

    // Transpose of a matrix [static method]

    public static Matriz transpose(Matriz amat){

    Matriz tmat = new Matriz(amat.ncol, amat.nrow);

    double[][] tarray = tmat.getArrayReference();

    for (int i = 0; i < amat.ncol; i++){

    for (int j = 0; j < amat.nrow; j++){tarray[i][j] = amat.matriz[j][i];

    }

    }

    return tmat;

    }

    // OPPOSITE

    // Opposite of a matrix [instance method]

    public Matriz opposite(){

    Matriz opp = Matriz.copy(this);

    for (int i = 0; i < this.nrow; i++){

    for (int j = 0; j < this.ncol; j++){

    opp.matriz[i][j] =- this.matriz[i][j];

    }

    }

    return opp;

    }

    // Opposite of a matrix [static method]

    public static Matriz opposite(Matriz amat){

    Matriz opp = Matriz.copy(amat);

    for (int i = 0; i < amat.nrow; i++){

    for (int j = 0; j < amat.ncol; j++){

    opp.matriz[i][j] =- amat.matriz[i][j];

  • 7/29/2019 Anisostropic diffusion java implementation

    43/50

    Jos Iguelmar Miranda

    42

    }

    }

    return opp;

    }

    // TRACE

    // Trace of a matrix [instance method]

    public double trace(){

    double trac = 0.0D;

    for (int i = 0; i < Math.min(this.ncol,this.ncol); i++){

    trac += this.matriz[i][i];

    }

    return trac;}

    // Trace of a matrix [static method]

    public static double trace(Matriz amat){

    double trac = 0.0D;

    for (int i = 0; i < Math.min(amat.ncol,amat.ncol); i++){

    trac += amat.matriz[i][i];

    }

    return trac;

    }

    /*

    ******************************************************************

    */

    // MTODOS NECESSRIOS PARA O ALGORITMO Perona-Malik

    // Implementao: Joo Camargo Neto & Jos Iguelmar Miranda.

    // METHODS USED BY Perona-Malik ALGORITHM

    // Construct matrix with a reference to an existing nrow x ncol 2-D

    // array of int variables (Joo 7/8/2006).

    public Matriz(int[][] twoI){

    // nmero de colunas da matriz = num linhas twoI (w)

    this.nrow = twoI.length;

    // (h)

  • 7/29/2019 Anisostropic diffusion java implementation

    44/50

    Jos Iguelmar Miranda

    43

    this.ncol = twoI[0].length;

    this.matriz = new double[nrow][ncol];

    for (int i = 0; i < ncol; i++){

    for (int j = 0; j < nrow; j++){

    this.matriz[j][i] = (double) twoI[j][i];

    }

    }

    this.index = new int[nrow];

    for (int i = 0; i < nrow; i++)

    this.index[i] = i;

    }

    // Divide cada elemento da matriz por uma constante.// Divide each matrix element by a constant

    public void divide(double constant){

    for (int i = 0; i < this.nrow; i++){

    for (int j = 0; j < this.ncol; j++){

    if (constant != 0.0)

    this.matriz[i][j] /= constant;

    else {

    String st = "Matriz::divide(double constant) -> divide by zero.";

    System.out.println(st);

    }

    }

    }

    }

    // Multiplica cada um dos elementos de duas matrizes (imagens).

    // Altera os valores de 'this.'// Multiply each one of matrixes elements

    public void multiplica(Matriz bMat){

    for (int i = 0; i < this.nrow; i++){

    for (int j = 0; j < this.ncol; j++){

    this.matriz[i][j] *= bMat.matriz[i][j];

    }

  • 7/29/2019 Anisostropic diffusion java implementation

    45/50

    Jos Iguelmar Miranda

    44

    }

    }

    // Eleva ao quadrado cada elemento da matriz.

    // Square each one of matrixes elements

    public void elevaQuadrado(){

    for (int i = 0; i < this.nrow; i++){

    for (int j = 0; j < this.ncol; j++){

    this.matriz[i][j] *= this.matriz[i][j];

    }

    }

    }

    // Retorna o valor absoluto de cada elemento da matriz.

    // Return the absolute value of each one of matrixes elements

    public void abs(){

    for (int i = 0; i < this.nrow; i++){

    for (int j = 0; j < this.ncol; j++){

    this.matriz[i][j] = Math.abs(this.matriz[i][j]);

    }

    }

    }

    // Retorna o exponencial de cada elemento da matriz.

    // Return the exponential value of each one of matrixes elements

    public void exp(){

    for (int i = 0; i < this.nrow; i++){

    for (int j = 0; j < this.ncol; j++){

    this.matriz[i][j] = Math.exp(this.matriz[i][j]);

    }}

    }

    // Retorna o inverso de cada elemento da matriz.

    // Return the inverse value of each one of matrixes elements

    public void inverteElemento(){

    for (int i = 0; i < this.nrow; i++){

  • 7/29/2019 Anisostropic diffusion java implementation

    46/50

    Jos Iguelmar Miranda

    45

    for (int j = 0; j < this.ncol; j++){

    this.matriz[i][j] = 1/this.matriz[i][j];

    }

    }

    }

    // Adiciona um valor a cada elemento da matriz.

    // Add a value to each one of matrixes elements

    public void adiciona(double valor){

    for (int i = 0; i < this.nrow; i++){

    for (int j = 0; j < this.ncol; j++){

    this.matriz[i][j] = this.matriz[i][j] + valor;

    }}

    }

    // Gradient calculation

    // Calcula gradiente da imagem

    // Parmetro: (Joo 7/8/2006)

    // dir = 1 ==> direo norte (north)

    // dir = 2 ==> direo sul (south)

    // dir = 3 ==> direo leste (east)

    // dir = 4 ==> direo oeste (west)

    public void gradiente(int dir) {

    double pReA, pReG;

    int lin, col;

    lin = this.nrow;

    col = this.ncol;

    switch(dir){// direo norte para matriz e oeste para imagem

    // North for matrix and west for image

    case 1:

    for(int i = 0; i < col; i++){

    for(int j = lin - 1; j > 0; j--){

    pReA = this.matriz[j][i];

    pReG = this.matriz[j-1][i];

  • 7/29/2019 Anisostropic diffusion java implementation

    47/50

    Jos Iguelmar Miranda

    46

    this.matriz[j][i] = pReG - pReA;

    }

    }

    for(int i = 0; i < col; i++){

    this.matriz[0][i] = 0.0;

    }

    break;

    // direo sul para matriz e leste para imagem

    // South for matrix and east for image

    case 2:

    for(int i = 0; i < col; i++){

    for(int j = 0; j < lin - 1; j++){

    pReA = this.matriz[j][i];pReG = this.matriz[j+1][i];

    this.matriz[j][i] = pReG - pReA;

    }

    }

    for(int i = 0; i < col; i++){

    this.matriz[lin-1][i] = 0.0;

    }

    break;

    // direo leste para matriz e norte para imagen

    // East for matrix and north for image

    case 3:

    for(int i = 0; i < col - 1; i++){

    for(int j = 0; j < lin; j++){

    pReA = this.matriz[j][i];

    pReG = this.matriz[j][i+1];

    this.matriz[j][i] = pReG - pReA;

    }

    }

    for(int j = 0; j < lin; j++){

    this.matriz[j][col-1] = 0.0;

    }

    break;

    // direo oeste para matriz e sul para imagem

  • 7/29/2019 Anisostropic diffusion java implementation

    48/50

    Jos Iguelmar Miranda

    47

    // West for matrix and south for image

    case 4:

    for(int i = col - 1; i > 0; i--){

    for(int j = 0; j < lin; j++){

    pReA = this.matriz[j][i];

    pReG = this.matriz[j][i-1];

    this.matriz[j][i] = pReG - pReA;

    }

    }

    for(int j = 0; j < lin; j++){

    this.matriz[j][0] = 0.0;

    }break;

    }

    }

    // Imprime a matriz com 'decimais' casas decimais

    // Print matrix with 'decimals' decimals

    public void imprimeMatriz(int decimais) {

    String padrao = "#.";

    for (int i = 0; i < decimais; i++)

    padrao += "#";

    DecimalFormat formato = null;

    formato = new DecimalFormat(padrao);

    String elemento;

    System.out.println();

    if (this.matriz == null){System.out.println("Matriz vazia.");

    } else {

    int nr = this.getNrow();

    int nc = this.getNcol();

    for (int i = 0; i < nr; i++){

    for (int j = 0; j < nc; j++){

    elemento = formato.format(this.matriz[i][j]);

  • 7/29/2019 Anisostropic diffusion java implementation

    49/50

    Jos Iguelmar Miranda

    48

    System.out.print(elemento+ "\t");

    }

    System.out.println();

    }

    }

    }

    } // end of Matriz

    Source code is also available in the site:

    http://repositorio.agrolivre.gov.br/projects/pid .

    Look for CT_072_06.

    Please note: if you intend to use this material in any publication, please give credits to:

    MIRANDA, J. I.; CAMARGO NETO, J. Modelo de difuso anisotrpica para deteco de

    bordas. Campinas: Embrapa Informtica Agropecuria, 2006. Pginas: 4 (Embrapa

    Informtica Agropecuria. Comunicado Tcnico, 72). Available in:

    .

    FOR ANY additional information, please contact:

    [email protected]

    Bibliography

    PARKER, J. R. Algorithms for image processing and computer vision. New York, NY:

    John Wiley & Sons, 1997. 417 p.

    CHUNG, D. H.; SAPIRO, G. S. Segmenting skin lesions with partial differential equations

    based image processing algorithm. IEEE Transactions on Medical Imaging, 19(7):763-

    767, 2000.

    PERONA, P.; MALIK, J. Scale-space and edge detection using anisotropic diffusion. IEEE

    Transactions on Patterns Analysis and Machine Intelligence, 12(7):629-639, 1990.

  • 7/29/2019 Anisostropic diffusion java implementation

    50/50

    Jos Iguelmar Miranda

    DEMIRKAYA, O. Anisotropic diffusion filtering of PET attenuation data to improve

    emission images.Physics in Medicine and Biology, 47:271-278, 2002.

    GIBOU, F. et al. Partial differential equations-based segmentation for radiotherapy treatment

    planning.Mathematical Biosciences and Engineering, 2(2):209-226, 2005.

    KARANTZALOS, K. G.; ARGIALAS, D. P. Towards automatic olive tree extraction from

    satellite imagery. Istanbul, ISPRS 2004 12-23 July 2004, Congress title: Geo-Imagery

    Bridging Continents, XXth ISPRS Congress, 12-23 July 2004 Istanbul, Turkey.

    KOENDERINK, J. J. The structure of images.Biological Cybernetics, 50:363-370, 1984.