Anisotropic Diffusion Model for Edge Detection: a Java implementation

49
12/11/2008 Anisotropic Diffusion Model for Edge Detection: a Java Implementation José Iguelmar Miranda

description

This document presents the Java implementation of the anisotropic diffusion filter, as described by Perona & Malik (1990).

Transcript of Anisotropic Diffusion Model for Edge Detection: a Java implementation

Page 1: Anisotropic Diffusion Model for Edge Detection: a Java implementation

12/11/2008

Anisotropic Diffusion Model for Edge Detection: a Java Implementation

José Iguelmar Miranda

Page 2: Anisotropic Diffusion Model for Edge Detection: a Java implementation

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 object’s 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, target’s

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

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

Page 3: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

2

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 processing

communities. 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):

tyxetyxG 2)( 22

21);,(

(1)

Page 4: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

3

Where:

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

The “time” t is a scale parameter: increases in t yield simpler images representations or coarse

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

is called scale-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):

2

2

2

2

yf

xfII t

(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

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

blurring is required to be space invariant.

Page 5: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

4

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 of c(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 anisotropic

diffusion equation:

It = div(c(x, y; t)I) = c(x, y; t)I + c I (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 equation It = cI if c(x, y; t) is a constant.

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.

Page 6: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

5

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 of g(), 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:

t jiWWEESsNNt

jit

ji IcIcIcIcII ,,1

, (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:

jijijiW

jijijiE

jijijiS

jijijiN

IIIIII

IIIIII

,,1,

,,1,

,1,,

,1,,

(7)

Page 7: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

6

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:

t

jiWtW

tjiE

tE

tjiS

tS

tjiN

tN

Igc

Igc

Igc

Igc

ji

ji

ji

ji

,

,

,

,

,

,

,

,

(8)

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

conduction tensor is diagonal with input values g(|Ix|) and g(|Iy|) instead of g(||Ix||) and g(||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 for g() yielded similar results. Images produced in this document used g() as:

))/)(( 2

)( KIeIg (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

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

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

Page 8: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

7

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

The source code

Page 9: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

8

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

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 & João Camargo Neto.

DATE: November 2006

DOCUMENTATION:

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

Copyright (c) 2006 Embrapa Informática Agropecuária

PERMISSION TO COPY:

This program is free software, under the GNU General Public License (GPL); 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 authors, José Iguelmar Miranda & João Camargo Neto, at www.cnptia.embrapa.br, appears in all copies.

Embrapa Informática Agropecuária makes no representations about the suitability or fitness of the software for any or for a particular purpose. Embrapa Informática Agropecuária shall not be liable for any damages suffered as 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.,

Page 10: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

9

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

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

Description:

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 on Pattern 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(.)' is monotonically decreasing; as a result, smoothes small discontinuities and enhance edges. For instance, threshold = 15.

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

Output:

JFrame with source and filtered images.

Page 11: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

10

Informações do CVS:

$Source$:

$Revision$:

$Date$:

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

// generic packages

import 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?

Page 12: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

11

if (args.length != 5) {

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

String msgb = "<image> <iterations>";

String msgc = " <type Perona-Malik function: 1 | 2> <threshold> ";

String msgd = "<sigma2>";

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";

Page 13: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

12

System.out.println(st);

System.exit(0);

}

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

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);

Page 14: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

13

eq_time = System.currentTimeMillis() - eq_time;

String msg = "AnisotropicDiffusionFilter: run time ";

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

// Close application clicking on "close"

c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

c.setVisible(true);

}

public AnisotropicDiffusionFilter(String aFile, int iterations, int typePM, int threshold, double sigma2) {

// Define BufferedImage

BufferedImage src = null, dest = null;

int w, h, tipo, nBandas, pixels[][], bordas[][], bordasTriplo[][][];

JLabel img1, img2;

// Does image exist?

File file = new File(aFile);

try {

src = ImageIO.read(file);

} catch(Exception e) {

System.out.println("Imagem '" + aFile + "' nao existe.");

System.exit(0);

}

// Identify frame

setTitle("Anisotropic diffusion: " + file.getName());

w = src.getWidth();

h = src.getHeight();

nBandas = src.getSampleModel().getNumBands();

System.out.println("Number of image bands: " + nBandas + "\n");

Page 15: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

14

// If imagem is gray level ...

if (nBandas == 1) {

pixels = lePixels(src, 0);

if (typePM == 1)

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

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 {

Page 16: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

15

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");

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){

Page 17: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

16

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

double dt, imagemD[][];

Matriz matrizPM = new Matriz(in);

// Gradient copies

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);

Page 18: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

17

mGradienteL.gradiente(2);

mGradienteO.gradiente(1);

// Save copy of images with gradient for further calculations

cN = mGradienteN.copy();

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

Page 19: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

18

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

cN.abs();

cN.divide((double) threshold);

cN.elevaQuadrado();

cN.adiciona(1.0);

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);

Page 20: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

19

mGradienteL.gradiente(2);

mGradienteO.gradiente(1);

matrizPM = j0.copy();

}

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;

Page 21: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

20

h = in[0].length;

pixels = new int[w*h];

tipo = BufferedImage.TYPE_BYTE_GRAY;

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

WritableRaster destWR = dest.getRaster();

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[];

Page 22: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

21

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;

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 <= hks; y1++){

for (int x1 = -hks; x1 <= hks; x1++) {

x = (double) x1*x1;

y = (double) y1*y1;

// 2D Gaussian

flt[y1+hks][x1+hks] = Math.exp(-1*(x + y)/(2*sigma2));

soma += flt[y1+hks][x1+hks];

}

}

// Normalize values in flt

for (int y1 = 0; y1 <= 2*hks; y1++)

for (int x1 = 0; x1 <= 2*hks; x1++)

flt[y1][x1] /= soma;

tmpVec = new int[hks];

if (hks > 1) {

eI = new int[w+2*hks][h+2*hks];

// Horizontal expansion

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

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

// First column of image

if (col == 0){

xL = mean(retornaPixels(in, lin, col, hks, "horizontal"));

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

eI[k][lin] = (int) xL;

Page 23: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

22

}

// Last column if image

if (col == w - 1){

xR = mean(retornaPixels(in, lin, w - hks, hks, "horizontal"));

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

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;

Page 24: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

23

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++){

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 <= in.length) {

vec = new int[tam];

Page 25: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

24

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

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

}

} else { // vertical

if (lin + tam <= in[0].length) {

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.

Page 26: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

25

Informações do CVS:

$Source$:

$Revision$:

$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 Matriz

private 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;

}

Page 27: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

26

// 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;

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;

Page 28: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

27

this.dswap = bb.dswap;

}

// METHODS

// 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

Page 29: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

28

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");

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;

Page 30: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

29

}

return u;

}

// Construct a complex scalar matrix

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;

}

Page 31: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

30

// Return the number of columns

public int getNcol(){

return this.ncol;

}

// 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];

}

Page 32: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

31

// 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];

}

// 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]];

}

Page 33: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

32

}

return smat;

}

// Return a reference to the permutation index array

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();

Page 34: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

33

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

Matriz b = new Matriz(nr,nc);

b.nrow = nr;

b.ncol = nc;

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

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;

Page 35: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

34

}

}

// Clone a Matriz

public Object clone(){

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++){

Page 36: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

35

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

}

}

return cmat;

}

// 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];

}

}

}

Page 37: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

36

// 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)){

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 -=]

Page 38: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

37

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;

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

Page 39: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

38

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++){

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();

Page 40: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

39

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

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

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

}

}

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

Page 41: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

40

// 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++){

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]

Page 42: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

41

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];

}

}

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;

}

/*

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

*/

// MÉTODOS NECESSÁRIOS PARA O ALGORITMO Perona-Malik

// Implementação: João Camargo Neto & José Iguelmar Miranda.

// METHODS USED BY Perona-Malik ALGORITHM

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

Page 43: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

42

// array of int variables (João 7/8/2006).

public Matriz(int[][] twoI){

// número de colunas da matriz = num linhas twoI (w)

this.nrow = twoI.length;

// (h)

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){

Page 44: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

43

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

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

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

}

}

}

// 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]);

}

}

}

Page 45: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

44

// 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++){

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

// Parâmetro: (João 7/8/2006)

// dir = 1 ==> direção norte (north)

// dir = 2 ==> direção sul (south)

// dir = 3 ==> direção leste (east)

// dir = 4 ==> direção oeste (west)

public void gradiente(int dir) {

double pReA, pReG;

int lin, col;

lin = this.nrow;

col = this.ncol;

switch(dir){

// direção norte para matriz e oeste para imagem

// North for matrix and west for image

Page 46: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

45

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];

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

}

}

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

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

}

break;

// direção 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;

// direção 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;

}

Page 47: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

46

}

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

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

}

break;

// direção oeste para matriz e sul para imagem

// 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 {

Page 48: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

47

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]);

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 difusão anisotrópica para detecção de

bordas. Campinas: Embrapa Informática Agropecuária, 2006. Páginas: 4 (Embrapa

Informática Agropecuária. Comunicado Técnico, 72). Available in:

<http://www.cnptia.embrapa.br/files/ct72.pdf>.

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.

Page 49: Anisotropic Diffusion Model for Edge Detection: a Java implementation

José Iguelmar Miranda

48

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.

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.