comparison main/image/cordflt2.cc @ 0:6b33357c7561 octave-forge

Initial revision
author pkienzle
date Wed, 10 Oct 2001 19:54:49 +0000
parents
children 82264140e58b
comparison
equal deleted inserted replaced
-1:000000000000 0:6b33357c7561
1 // Copyright (C) 2000 Teemu Ikonen
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
17 #include <octave/oct.h>
18
19 #ifdef HAVE_OCTAVE_20
20 typedef Matrix boolMatrix;
21 #define bool_matrix_value matrix_value
22 #endif
23
24 #define SWAP(a, b) { SWAP_temp = (a); (a)=(b); (b) = SWAP_temp; }
25
26 // Template function for comparison
27 // ET is the type of the matrix element
28 template <class ET>
29 inline bool compare(const ET a, const ET b)
30 {
31 if(a > b)
32 return 1;
33 else
34 return 0;
35 }
36
37 // Explicit template function for complex compare
38 template <> inline bool compare<Complex>(const Complex a, const Complex b)
39 {
40 double anorm2 = a.real() * a.real() + a.imag() * a.imag();
41 double bnorm2 = b.real() * b.real() + b.imag() * b.imag();
42
43 if( anorm2 > bnorm2 ) {
44 return 1;
45 } else {
46 return 0;
47 }
48 }
49
50 // select nth largest member from the array values
51 // Partitioning algorithm, see Numerical recipes chap. 8.5
52 template <class ET>
53 ET selnth(ET *vals, int len, int nth)
54 {
55 ET SWAP_temp;
56 ET hinge;
57 int l, r, mid, i, j;
58
59 l = 0;
60 r = len - 1;
61 for(;;) {
62 // if partition size is 1 or two, then sort and return
63 if(r <= l+1) {
64 if(r == l+1 && compare<ET>(vals[l], vals[r])) {
65 SWAP(vals[l], vals[r]);
66 }
67 return vals[nth];
68 } else {
69 mid = (l+r) >> 1;
70 SWAP(vals[mid], vals[l+1]);
71 // choose median of l, mid, r to be the hinge element
72 // and set up sentinels in the borders (order l, l+1 and r)
73 if(compare<ET>(vals[l], vals[r])) {
74 SWAP(vals[l], vals[r]);
75 }
76 if(compare<ET>(vals[l+1], vals[r])) {
77 SWAP(vals[l+1], vals[r]);
78 }
79 if(compare<ET>(vals[l], vals[l+1])) {
80 SWAP(vals[l], vals[l+1]);
81 }
82 i = l+1;
83 j = r;
84 hinge = vals[l+1];
85 for(;;) {
86 do i++; while(compare<ET>(hinge, vals[i]));
87 do j--; while(compare<ET>(vals[j], hinge));
88 if(i > j)
89 break;
90 SWAP(vals[i], vals[j]);
91 }
92 vals[l+1] = vals[j];
93 vals[j] = hinge;
94 if(j >= nth)
95 r = j - 1;
96 if(j <= nth)
97 l = i;
98 }
99 }
100 }
101
102 // Template function for doing the actual filtering
103 // MT is the type of the matrix to be filtered (Matrix or ComplexMatrix)
104 // ET is the type of the element of the matrix (double or Complex)
105 template <class MT, class ET>
106 octave_value_list do_filtering(MT A, int nth, boolMatrix dom, MT S)
107 {
108 int i, j, c, d;
109
110 int len = 0;
111 for(j = 0; j < dom.columns(); j++) {
112 for(i = 0; i < dom.rows(); i++) {
113 if(dom.elem(i,j))
114 len++;
115 }
116 }
117 if(nth > len - 1) {
118 warning("nth should be less than number of non-zero values in domain");
119 warning("setting nth to largest possible value\n");
120 nth = len - 1;
121 }
122 if(nth < 0) {
123 warning("nth should be non-negative, setting to 1\n");
124 nth = 0; // nth is a c-index
125 }
126
127 int rowoffset = (dom.columns() + 1)/2 - 1;
128 int coloffset = (dom.rows() + 1)/2 - 1;
129
130 //outputs
131 octave_value_list out;
132 const int origx = A.columns() - dom.columns()+1;
133 const int origy = A.rows() - dom.rows()+1;
134 MT retval = MT(origy, origx);
135
136 int *offsets = new int[len];
137 ET *values = new ET[len];
138 ET *adds = new ET[len];
139
140 c = 0;
141 d = A.rows();
142 for(j = 0; j < dom.columns(); j++) {
143 for(i = 0; i < dom.rows(); i++) {
144 if(dom.elem(i,j)) {
145 offsets[c] = (i - coloffset) + (j - rowoffset)*d;
146 adds[c] = S.elem(i,j);
147 c++;
148 }
149 }
150 }
151
152 ET *data = A.fortran_vec();
153 int base = coloffset + A.rows()*rowoffset;
154 for(j = 0; j < retval.columns(); j++) {
155 for(i = 0; i < retval.rows(); i++) {
156 for(c = 0; c < len; c++) {
157 values[c] = data[base + offsets[c]] + adds[c];
158 }
159 base++;
160 retval(i, j) = selnth(values, len, nth);
161 }
162 base += dom.rows() - 1;
163 }
164
165 out(0) = octave_value(retval);
166
167 return out;
168 }
169
170 // instantiate template functions
171 template inline bool compare<double>(const double, const double);
172 template double selnth(double *, int, int);
173 template Complex selnth(Complex *, int, int);
174 template octave_value_list do_filtering<Matrix, double>(Matrix, int, boolMatrix, Matrix);
175 // g++ is broken, explicit instantiation of specialized template function
176 // confuses the compiler.
177 //template int compare<Complex>(const Complex, const Complex);
178 template octave_value_list do_filtering<ComplexMatrix, Complex>(ComplexMatrix, int, boolMatrix, ComplexMatrix);
179
180 DEFUN_DLD(cordflt2, args, ,
181 "function retval = cordflt2(A, nth, domain, S)
182
183 Implementation of two-dimensional ordered filtering. User interface
184 in ordfilt2.m
185 ")
186 {
187 if(args.length() != 4) {
188 print_usage ("ordfilt2");
189 return octave_value_list();
190 }
191
192 // nth is an index to an array, thus - 1
193 int nth = (int) (args(1).vector_value())(0) - 1;
194 boolMatrix dom = args(2).bool_matrix_value();
195
196 octave_value_list retval;
197
198 if(args(0).is_real_matrix()) {
199 Matrix A = args(0).matrix_value();
200 Matrix S = args(3).matrix_value();
201 retval = do_filtering<Matrix, double>(A, nth, dom, S);
202 }
203 else if(args(0).is_complex_matrix()) {
204 ComplexMatrix A = args(0).complex_matrix_value();
205 ComplexMatrix S = args(3).complex_matrix_value();
206 retval = do_filtering<ComplexMatrix, Complex>(A, nth, dom, S);
207 }
208 else {
209 error("A should be real or complex matrix\n");
210 return octave_value_list();
211 }
212
213 return retval;
214
215 }