CR2RE Pipeline Reference Manual 1.6.7
hdrl_cat_apclust.c
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 2017 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include "hdrl_cat_apclust.h"
21
22#include "hdrl_cat_terminate.h"
23
24
25/*** Prototypes ***/
26static void minmax_xy( cpl_size np, plstruct *plstr,
27 cpl_size *ix1, cpl_size *ix2,
28 cpl_size *iy1, cpl_size *iy2);
29
30
31/*----------------------------------------------------------------------------*/
39/*----------------------------------------------------------------------------*/
40
43/* ---------------------------------------------------------------------------*/
59/* ---------------------------------------------------------------------------*/
60void hdrl_apclust(ap_t *ap, cpl_size np, plstruct *plstr)
61{
62 /* A couple of useful things */
63 double i2compare = ap->thresh;
64 double icompare = i2compare * (double)ap->multiply;
65
66 /* Get the min and max positions. Create a raster with the IDs of the
67 * pixels in the pixel list (algorithm prefers data to be in a raster) */
68 cpl_size ix1, ix2, iy1, iy2;
69 minmax_xy(np, plstr, &ix1, &ix2, &iy1, &iy2);
70
71 cpl_size nx = ix2 - ix1 + 1;
72 cpl_size ny = iy2 - iy1 + 1;
73
74 cpl_size nwork = nx * ny;
75 cpl_size *work = cpl_malloc(nwork * sizeof(cpl_size));
76
77 for (cpl_size i = 0; i < nwork; i++) {
78 work[i] = -1;
79 }
80
81 for (cpl_size k = 0; k < np; k++) {
82
83 cpl_size i = plstr[k].x - 1;
84 cpl_size j = plstr[k].y - 1;
85
86 cpl_size kk = (j - iy1) * nx + i - ix1;
87 work[kk] = k;
88 }
89
90 /* Now do the job */
91 for (cpl_size j = iy1; j <= iy2; j++) {
92
93 for (cpl_size i = ix1; i <= ix2; i++) {
94
95 cpl_size kk = (j - iy1) * nx + i - ix1;
96 cpl_size k = work[kk];
97
98 if (k < 0) {
99
100 ap->lastline[i + 1] = 0;
101
102 } else {
103
104 if (plstr[k].zsm > icompare) {
105
106 /* Pixel is above threshold, find which parent it belongs to. */
107 cpl_size is = ap->lastline[i]; /* Parent last pixel this line */
108 cpl_size ip = ap->lastline[i + 1]; /* Guess belongs to above line */
109
110 if (ip == 0) {
111
112 /* New parent, or, horizontal slice: */
113 if (is == 0) {
114
115 /* Ah - new parent. */
116 if (ap->ipstack > ap->maxpa * 3 / 4) {
117 for (cpl_size ik = 0; ik < ap->maxpa * 3 / 8; ik++) {
118 hdrl_apfu(ap);
119 }
120 }
121
122 ip = ap->pstack[ap->ipstack++];
123
124 ap->parent[ip].first = ap->bstack[ap->ibstack];
125 ap->parent[ip].pnop = 0;
126 ap->parent[ip].pnbp = 0;
127 ap->parent[ip].growing = 0;
128
129 if (j == 0) {
130 ap->parent[ip].touch = 1; /* It touches first line */
131 } else {
132 ap->parent[ip].touch = 0;
133 }
134
135 /* For hunt thru list for terminates: */
136 if (ip > ap->maxip) {
137 ap->maxip = ip;
138 }
139
140 } else {
141
142 /* Slice with no vertical join: */
143 ip = is;
144 }
145
146 } else if ((ip > 0 && is > 0) && (ip != is)) {
147
148 /* Merge: Join linked lists: */
149 ap->blink[ap->parent[ip].last] = ap->parent[is].first;
150
151 /* Copy `last block': */
152 ap->parent[ip].last = ap->parent[is].last;
153 ap->parent[ip].pnop += ap->parent[is].pnop;
154 ap->parent[ip].pnbp += ap->parent[is].pnbp;
155
156 /* Fix `lastline' correlator array: */
157 cpl_size ib = ap->parent[is].first;
158
159 cpl_size loop = 1;
160 while (loop) {
161
162 cpl_size i1 = ap->plessey[ib].x;
163
164 if (ap->lastline[i1 + 1] == is) {
165 ap->lastline[i1 + 1] = ip;
166 }
167
168 if (ap->parent[is].last == ib) {
169 loop = 0;
170 } else {
171 ib = ap->blink[ib];
172 }
173 }
174
175 /* Mark parent inactive: */
176 ap->parent[is].pnop = -1;
177 ap->parent[is].pnbp = -1;
178
179 /* return name to stack: */
180 ap->pstack[--ap->ipstack] = is;
181 }
182
183 /* Add in pixel to linked list: */
184 cpl_size ib = ap->bstack[ap->ibstack++];
185
186 /* Patch forward link into last data block: */
187 if (ap->parent[ip].pnop > 0) {
188 ap->blink[ap->parent[ip].last] = ib;
189 }
190
191 /* Remember last block in chain: */
192 ap->parent[ip].last = ib;
193
194 /* Store the data: */
195 ap->plessey[ib].x = i;
196 ap->plessey[ib].y = j;
197 ap->plessey[ib].z = plstr[k].z;
198 ap->plessey[ib].zsm = plstr[k].zsm;
199
200 /* increment active count: */
201 ap->parent[ip].pnop++;
202
203 /* remember which parent this pixel was for next line: */
204 ap->lastline[i + 1] = ip;
205
206 } else {
207
208 /* Pixel was below threshold, mark lastline: */
209 ap->lastline[i + 1] = 0;
210 }
211 }
212 }
213 }
214
215 /* Check for images touching left & right edges:
216 * OR the touch flag with 2 for left, 4 for right: */
217
218 if (ap->lastline[1] > 0) {
219 ap->parent[ap->lastline[1]].touch |= 2;
220 }
221
222 if (ap->lastline[ap->lsiz] > 0) {
223 ap->parent[ap->lastline[ap->lsiz]].touch |= 4;
224 }
225
226 cpl_free(work);
227}
228
231/* ---------------------------------------------------------------------------*/
250/* ---------------------------------------------------------------------------*/
251static void minmax_xy( cpl_size np, plstruct *plstr,
252 cpl_size *ix1, cpl_size *ix2,
253 cpl_size *iy1, cpl_size *iy2)
254{
255
256 /* Get the minmax of the positions of the pixels in a plstruct.
257 * Take 1 away from each position so that it runs from 0 rather than 1 */
258
259 *ix1 = plstr[0].x - 1;
260 *ix2 = plstr[0].x - 1;
261
262 *iy1 = plstr[0].y - 1;
263 *iy2 = plstr[0].y - 1;
264
265 for (cpl_size i = 1; i < np; i++) {
266
267 *ix1 = CPL_MIN(*ix1, plstr[i].x - 1);
268 *ix2 = CPL_MAX(*ix2, plstr[i].x - 1);
269 *iy1 = CPL_MIN(*iy1, plstr[i].y - 1);
270 *iy2 = CPL_MAX(*iy2, plstr[i].y - 1);
271 }
272}
void hdrl_apclust(ap_t *ap, cpl_size np, plstruct *plstr)
Detect multiple objects from a given Plessey array.
void hdrl_apfu(ap_t *ap)
Get rid of the largest contributor in an ap structure.