Skip to content

Commit 409e687

Browse files
committed
Updating photometric filters
- Updating photometric filters in android project
1 parent 6dc6189 commit 409e687

File tree

9 files changed

+1755
-107
lines changed

9 files changed

+1755
-107
lines changed

Catalano.Android.Image/src/Catalano/Imaging/Filters/Photometric/DifferenceOfGaussian.java

Lines changed: 87 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949

5050
import Catalano.Imaging.Filters.*;
5151
import Catalano.Imaging.FastBitmap;
52+
import Catalano.Imaging.Tools.ImageUtils;
53+
import Catalano.Imaging.Tools.Kernel;
5254
import Catalano.Math.Functions.Gaussian;
5355
import Catalano.Math.Matrix;
5456

@@ -62,11 +64,51 @@
6264
*/
6365
public class DifferenceOfGaussian implements IPhotometricFilter{
6466

65-
private double sigma1 = 1.4D, sigma2 = 1.4D;
66-
private boolean normalize = true;
67+
private double sigma1;
68+
private double sigma2;
69+
private double[][] gv1;
70+
private double[][] gv2;
71+
72+
/**
73+
* Get sigma 1.
74+
* @return Sigma value.
75+
*/
76+
public double getSigma1() {
77+
return sigma1;
78+
}
79+
80+
/**
81+
* Set sigma 1.
82+
* @param sigma1 Sigma value.
83+
*/
84+
public void setSigma1(double sigma1) {
85+
this.sigma1 = sigma1;
86+
BuildKernels();
87+
}
88+
89+
/**
90+
* Get sigma 2.
91+
* @return Sigma value.
92+
*/
93+
public double getSigma2() {
94+
return sigma2;
95+
}
96+
97+
/**
98+
* Set sigma 2.
99+
* @param sigma2 Sigma value.
100+
*/
101+
public void setSigma2(double sigma2) {
102+
this.sigma2 = sigma2;
103+
BuildKernels();
104+
}
67105

68106
/**
69107
* Initialize a new instance of the DifferenceOfGaussian class.
108+
* <br>
109+
* <br> Default:
110+
* <br> Sigma 1: 1
111+
* <br> Sigma 2: 2
70112
*/
71113
public DifferenceOfGaussian() {
72114
this(1,2);
@@ -80,18 +122,12 @@ public DifferenceOfGaussian() {
80122
* @param sigma2 Second sigma value.
81123
*/
82124
public DifferenceOfGaussian(double sigma1, double sigma2) {
83-
this(sigma1,sigma2,true);
84-
}
85-
86-
public DifferenceOfGaussian(double sigma1, double sigma2, boolean normalize){
87125
this.sigma1 = sigma1;
88126
this.sigma2 = sigma2;
89-
this.normalize = normalize;
127+
BuildKernels();
90128
}
91-
92-
@Override
93-
public void applyInPlace(FastBitmap fastBitmap) {
94-
129+
130+
private void BuildKernels(){
95131
int size1 = 2 * (int)Math.ceil(3*sigma1) + 1;
96132
Gaussian ga = new Gaussian(sigma1);
97133
double[][] g1 = ga.Kernel2D(size1);
@@ -100,9 +136,21 @@ public void applyInPlace(FastBitmap fastBitmap) {
100136
ga.setSigma(sigma2);
101137
double[][] g2 = ga.Kernel2D(size2);
102138

139+
//Decompose kernels
140+
gv1 = Kernel.Decompose(g1);
141+
gv2 = Kernel.Decompose(g2);
142+
}
143+
144+
@Override
145+
public void applyInPlace(FastBitmap fastBitmap) {
146+
103147
if(fastBitmap.isGrayscale()){
104-
double[][] im1 = operateGray(fastBitmap, g1);
105-
double[][] im2 = operateGray(fastBitmap, g2);
148+
149+
double[][] image = fastBitmap.toMatrixGrayAsDouble();
150+
ImageUtils.Normalize(image);
151+
152+
double[][] im1 = ImageUtils.Convolution(image, gv1[0], gv1[1], true);
153+
double[][] im2 = ImageUtils.Convolution(image, gv2[0], gv2[1], true);
106154

107155
im1 = Matrix.Subtract(im1, im2);
108156

@@ -121,15 +169,14 @@ public void applyInPlace(FastBitmap fastBitmap) {
121169
fastBitmap.setGray(i, j, (int)Catalano.Math.Tools.Scale(min, max, 0, 255, im1[i][j]));
122170
}
123171
}
124-
125-
if(normalize){
126-
HistogramAdjust ha = new HistogramAdjust();
127-
ha.applyInPlace(fastBitmap);
128-
}
172+
129173
}
130174
else if(fastBitmap.isRGB()){
131-
double[][][] im1 = operateRGB(fastBitmap, g1);
132-
double[][][] im2 = operateRGB(fastBitmap, g2);
175+
176+
double[][][] image = fastBitmap.toMatrixRGBAsDouble();
177+
178+
double[][][] im1 = ImageUtils.Convolution(image, gv1[0], gv1[1], true);
179+
double[][][] im2 = ImageUtils.Convolution(image, gv2[0], gv2[1], true);
133180

134181
//Subtract operation
135182
for (int i = 0; i < im1.length; i++) {
@@ -168,100 +215,33 @@ else if(fastBitmap.isRGB()){
168215
}
169216
}
170217

171-
if(normalize){
172-
HistogramAdjust ha = new HistogramAdjust();
173-
ha.applyInPlace(fastBitmap);
174-
}
175-
}
176-
}
177-
178-
private double[][] operateGray(FastBitmap fastBitmap, double[][] kernel){
179-
//Perform the convolution
180-
int width = fastBitmap.getWidth();
181-
int height = fastBitmap.getHeight();
182-
double[][] response = new double[height][width];
183-
184-
int Xline,Yline;
185-
int lines = (kernel.length - 1)/2;
186-
double gray;
187-
188-
for (int x = 0; x < height; x++) {
189-
for (int y = 0; y < width; y++) {
190-
gray = 0;
191-
for (int i = 0; i < kernel.length; i++) {
192-
Xline = x + (i-lines);
193-
for (int j = 0; j < kernel[0].length; j++) {
194-
Yline = y + (j-lines);
195-
if ((Xline >= 0) && (Xline < height) && (Yline >=0) && (Yline < width)) {
196-
gray += kernel[i][j] * fastBitmap.getGray(Xline, Yline);
197-
}
198-
else {
199-
200-
int r = x + i - lines;
201-
int c = y + j - lines;
218+
HistogramAdjust ha = new HistogramAdjust();
219+
ha.applyInPlace(fastBitmap);
202220

203-
if (r < 0) r = 0;
204-
if (r >= height) r = height - 1;
205-
206-
if (c < 0) c = 0;
207-
if (c >= width) c = width - 1;
208-
209-
gray += kernel[i][j] * fastBitmap.getGray(r, c);
210-
}
211-
}
212-
}
213-
response[x][y] = gray;
214-
}
215221
}
216-
217-
return response;
218222
}
219223

220-
private double[][][] operateRGB(FastBitmap fastBitmap, double[][] kernel){
221-
//Perform the convolution
222-
int width = fastBitmap.getWidth();
223-
int height = fastBitmap.getHeight();
224-
double[][][] response = new double[height][width][3];
224+
/**
225+
* Process the image as matrix.
226+
* @param image Image.
227+
* @param normalize True if the image needs to be normalized.
228+
* @return DoG of the image.
229+
*/
230+
public double[][] Process(double[][] image, boolean normalize){
225231

226-
int Xline,Yline;
227-
int lines = (kernel.length - 1)/2;
228-
double red,green,blue;
232+
double[][] copy = Matrix.Copy(image);
229233

230-
for (int x = 0; x < height; x++) {
231-
for (int y = 0; y < width; y++) {
232-
red = green = blue = 0;
233-
for (int i = 0; i < kernel.length; i++) {
234-
Xline = x + (i-lines);
235-
for (int j = 0; j < kernel[0].length; j++) {
236-
Yline = y + (j-lines);
237-
if ((Xline >= 0) && (Xline < height) && (Yline >=0) && (Yline < width)) {
238-
red += kernel[i][j] * fastBitmap.getRed(Xline, Yline);
239-
green += kernel[i][j] * fastBitmap.getGreen(Xline, Yline);
240-
blue += kernel[i][j] * fastBitmap.getBlue(Xline, Yline);
241-
}
242-
else {
243-
244-
int r = x + i - lines;
245-
int c = y + j - lines;
246-
247-
if (r < 0) r = 0;
248-
if (r >= height) r = height - 1;
249-
250-
if (c < 0) c = 0;
251-
if (c >= width) c = width - 1;
234+
ImageUtils.Normalize(copy);
235+
236+
double[][] im1 = ImageUtils.Convolution(copy, gv1[0], gv1[1]);
237+
double[][] im2 = ImageUtils.Convolution(copy, gv2[0], gv2[1]);
252238

253-
red += kernel[i][j] * fastBitmap.getRed(r, c);
254-
green += kernel[i][j] * fastBitmap.getGreen(r, c);
255-
blue += kernel[i][j] * fastBitmap.getBlue(r, c);
256-
}
257-
}
258-
}
259-
response[x][y][0] = red;
260-
response[x][y][1] = green;
261-
response[x][y][2] = blue;
262-
}
239+
im1 = Matrix.Subtract(im1, im2);
240+
241+
if(normalize){
242+
ImageUtils.Normalize(im1);
263243
}
264244

265-
return response;
245+
return im1;
266246
}
267-
}
247+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Catalano Imaging Library
2+
// The Catalano Framework
3+
//
4+
// Copyright © Diego Catalano, 2012-2016
5+
// diego.catalano at live.com
6+
//
7+
// Copyright (c) 2011, Vitomir Struc
8+
// Copyright (c) 2009, Gabriel Peyre
9+
// All rights reserved.
10+
//
11+
// Redistribution and use in source and binary forms, with or without
12+
// modification, are permitted provided that the following conditions are
13+
// met:
14+
//
15+
// * Redistributions of source code must retain the above copyright
16+
// notice, this list of conditions and the following disclaimer.
17+
// * Redistributions in binary form must reproduce the above copyright
18+
// notice, this list of conditions and the following disclaimer in
19+
// the documentation and/or other materials provided with the distribution
20+
//
21+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31+
// POSSIBILITY OF SUCH DAMAGE.
32+
//
33+
// This library is free software; you can redistribute it and/or
34+
// modify it under the terms of the GNU Lesser General Public
35+
// License as published by the Free Software Foundation; either
36+
// version 2.1 of the License, or (at your option) any later version.
37+
//
38+
// This library is distributed in the hope that it will be useful,
39+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
40+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41+
// Lesser General Public License for more details.
42+
//
43+
// You should have received a copy of the GNU Lesser General Public
44+
// License along with this library; if not, write to the Free Software
45+
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
46+
//
47+
48+
package Catalano.Imaging.Filters.Photometric;
49+
50+
import Catalano.Imaging.FastBitmap;
51+
import Catalano.Imaging.Tools.ImageUtils;
52+
import Catalano.Math.Matrix;
53+
54+
/**
55+
* Multi scale retinex.
56+
* @author Diego Catalano
57+
*/
58+
public class MultiscaleRetinex implements IPhotometricFilter{
59+
60+
private int[] scales;
61+
62+
/**
63+
* Get scales.
64+
* @return scales.
65+
*/
66+
public int[] getScales() {
67+
return scales;
68+
}
69+
70+
/**
71+
* Set scales.
72+
* @param scales scales.
73+
*/
74+
public void setScales(int[] scales) {
75+
this.scales = scales;
76+
}
77+
78+
/**
79+
* Initializes a new instance of the MultiScaleRetinex class.
80+
* <br>
81+
* <br> Default:
82+
* <br> Scales = 7, 15, 21
83+
*/
84+
public MultiscaleRetinex() {
85+
this(new int[] {7,15,21});
86+
}
87+
88+
/**
89+
* Initializes a new instance of the MultiScaleRetinex class.
90+
* @param scales Scales.
91+
*/
92+
public MultiscaleRetinex(int[] scales) {
93+
this.scales = scales;
94+
}
95+
96+
@Override
97+
public void applyInPlace(FastBitmap fastBitmap) {
98+
99+
//Convert to matrix
100+
double[][] image = fastBitmap.toMatrixGrayAsDouble();
101+
102+
//Process the filter
103+
double[][] r = Process(image,true);
104+
105+
//Convert to the image.
106+
fastBitmap.matrixToImage(r);
107+
108+
}
109+
110+
/**
111+
* Process the image.
112+
* @param image Image to be processed.
113+
* @param normalize Normalize the image [0..255].
114+
* @return Response of the filter.
115+
*/
116+
public double[][] Process(double[][] image, boolean normalize){
117+
118+
SingleScaleRetinex ssr = new SingleScaleRetinex(scales[0]);
119+
double[][] r = ssr.Process(image, normalize);
120+
121+
for (int i = 1; i < scales.length; i++) {
122+
ssr.setScale(scales[i]);
123+
Matrix.Add(r, ssr.Process(image, normalize));
124+
}
125+
126+
if(normalize)
127+
ImageUtils.Normalize(r);
128+
129+
return r;
130+
}
131+
}

0 commit comments

Comments
 (0)