My favorites | Sign in
Project Home Wiki Issues Source
Checkout   Browse   Changes    
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
Copyright (c) 2011 Michael Zucchi

This file is part of socles, an OpenCL image processing library.

socles is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

socles is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with socles. If not, see <http://www.gnu.org/licenses/>.
*/
package au.notzed.socle.image;

import au.notzed.socle.SOCLECommand;
import com.jogamp.opencl.CLCommandQueue;
import com.jogamp.opencl.CLContext;
import com.jogamp.opencl.CLImage2d;
import com.jogamp.opencl.CLImageFormat;
import com.jogamp.opencl.CLKernel;
import com.jogamp.opencl.CLProgram;
import java.util.HashMap;

/**
* Calculate an integral image and an integral^2 image at the same time.
*
* @author notzed
*/
public class IntegralImage extends SOCLECommand {

final private CLKernel kIntegralX;
final private CLKernel kIntegralY;
final private int lwsX;
final private int lwsY;
final private boolean doii;

protected IntegralImage(CLContext cl, int sizex, int sizey, boolean doii) {
super(cl);

IntegralImageGenerator gen = new IntegralImageGenerator();

this.doii = doii;
lwsX = gen.createKernelX(sizex, doii);
lwsY = gen.createKernelY(sizey, doii);

CLProgram prog = build("", gen.toString(), "generated integral image");

kIntegralX = prog.createCLKernel("integral_" + sizex + "_III_x");
kIntegralY = prog.createCLKernel("integral_" + sizey + "_III_y");
}
private static HashMap<String, IntegralImage> map = new HashMap<String, IntegralImage>();

/**
* Create a program to perform a specific sized integral image calculation.
* @param cl
* @param sizex
* @param sizey
* @return
*/
public synchronized static IntegralImage get(CLContext cl, int sizex, int sizey) {
return get(cl, sizex, sizey, true);
}

/**
* Create a program to perform a specific sized integral image calculation.
* @param cl
* @param sizex
* @param sizey
* @param doii whether I*I should be also calculated.
* @return
*/
public synchronized static IntegralImage get(CLContext cl, int sizex, int sizey, boolean doii) {
String key = String.format("%08x:%dx%d:%s", cl.hashCode(), sizex, sizey, doii);

IntegralImage conv = map.get(key);
if (conv == null) {
conv = new IntegralImage(cl, sizex, sizey, doii);
map.put(key, conv);
}

return conv;
}

/**
* Create an integral image from a greyscale input image.
*
* @param q
* @param src Image in float-compatible format (i.e. one for which
* read_imagef() works). Assumed to be normalised.
* @param tmp Temporary work image, must be (at least) two-channel,
* unsigned int 32 format. May possibly be the same image as dstII,
* (which might also improve cache performance), although that may be
* implementation dependent.
* @param dstI destination integral image. Must be unsigned int 32.
* @param dstII destination integral squared image. Must be 2 channel
* unsigned int32 at least. Result is stored as (uint4) { lo, hi, 0, 0 }
*/
public void imageToIntegral(CLCommandQueue q, CLImage2d src, CLImage2d tmp, CLImage2d dstI, CLImage2d dstII) {
assert (tmp.getFormat().getImageChannelOrder() == CLImageFormat.ChannelOrder.BGRA
|| tmp.getFormat().getImageChannelOrder() == CLImageFormat.ChannelOrder.RG
|| tmp.getFormat().getImageChannelOrder() == CLImageFormat.ChannelOrder.RGBA);
if (!doii)
throw new RuntimeException("Trying to calculate I*I integral image with wrong generator");
synchronized (kIntegralX) {
kIntegralX.setArg(0, src);
kIntegralX.setArg(1, tmp);
q.put2DRangeKernel(kIntegralX, 0, 0, lwsX, src.height, lwsX, 1);

kIntegralY.setArg(0, tmp);
kIntegralY.setArg(1, dstI);
kIntegralY.setArg(2, dstII);
q.put2DRangeKernel(kIntegralY, 0, 0, lwsY, src.width, lwsY, 1);
}
}

/**
* Generate an integral image from a source image.
*
* Only call for IntegralImage where "doii" was specified.
* @param q
* @param src Float-compatible input image (e.g. UNORM_INT8)
* @param tmp Must be an uint32 type image, with at least 1 channel.
* @param dstI Destination image, format must be uint32.
*/
public void imageToIntegral(CLCommandQueue q, CLImage2d src, CLImage2d tmp, CLImage2d dstI) {
if (doii)
throw new RuntimeException("Trying to calculate I integral image with wrong generator");
synchronized (kIntegralX) {
kIntegralX.setArg(0, src);
kIntegralX.setArg(1, tmp);
q.put2DRangeKernel(kIntegralX, 0, 0, lwsX, src.height, lwsX, 1);

kIntegralY.setArg(0, tmp);
kIntegralY.setArg(1, dstI);
q.put2DRangeKernel(kIntegralY, 0, 0, lwsY, src.width, lwsY, 1);
}
}
}

Change log

r56 by notzed on Today (12 hours ago)   Diff
Got the SURF code working.
Changed to use socles integral image
generator.
Changed to use integer integral images
rather than float.
Tweaked integral image calculator so I^2
table is optional.
Tried alternative implementation of
createDescriptors.
Added demo that runs SURF
Added SURF to webcamfx
Changed webcamfx so detectors are run
...
Go to: 
Project members, sign in to write a code review

Older revisions

r49 by notzed on Mar 2, 2012   Diff
A bit of a redesign of the generator
code.
And ensure copyright notices are
included explicitly.

r15 by notzed on May 26, 2011   Diff
2-pass Integral image calculator.
All revisions of this file

File info

Size: 4996 bytes, 144 lines
Powered by Google Project Hosting