debug messages in play
[sparrow.git] / floodfill.c
blob5511dca305c7f722e574974da1dfcad625e74168
1 /* Copyright (C) <2010> Douglas Bagnall <douglas@halo.gen.nz>
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Library General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Library General Public License for more details.
13 * You should have received a copy of the GNU Library General Public
14 * License along with this library; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 02111-1307, USA.
19 #include "sparrow.h"
20 #include "gstsparrow.h"
22 #include <string.h>
23 #include <math.h>
25 #define STUPID_DEBUG_TRICK 1
27 typedef struct sparrow_find_screen_s {
28 IplImage *green;
29 IplImage *working;
30 IplImage *mask;
31 IplImage *im;
32 } sparrow_find_screen_t;
35 /* Floodfill for find screen */
36 static inline void
37 expand_one_mono(int x, int y, int c,
38 CvPoint *nexts, int *n_nexts, guint8 *im, guint8 *mask, int w, int h){
39 guint8 p = im[y * w + x];
40 guint8 *m = &mask[y * w + x];
41 if (*m && (p == c)){
42 *m = 0;
43 nexts[*n_nexts].x = x;
44 nexts[*n_nexts].y = y;
45 (*n_nexts)++;
50 im: the image to be analysed
51 mim: the mask image to be written
52 start: a point of the right colour.
55 static IplImage*
56 floodfill_mono_superfast(IplImage *im, IplImage *mim, CvPoint start)
58 guint8 * data = (guint8 *)im->imageData;
59 guint8 * mdata = (guint8 *)mim->imageData;
60 int w = im->width;
61 int h = im->height;
62 int n_starts;
63 int n_nexts = 0;
64 CvPoint *starts;
65 CvPoint *nexts;
67 //malloc 2 lists of points. These *could* be as large as the image (but never should be)
68 void * mem = malloc_or_die(w * h * 2 * sizeof(CvPoint));
69 starts = mem;
70 nexts = starts + w * h;
71 n_starts = 1;
72 starts[0] = start;
74 while(n_starts){
75 n_nexts = 0;
76 int i;
77 for (i = 0; i < n_starts; i++){
78 int x = starts[i].x;
79 int y = starts[i].y;
80 int c = data[y * w + x];
81 if (x > 0){
82 expand_one_mono(x - 1, y, c, nexts, &n_nexts, data, mdata, w, h);
84 if (x < w - 1){
85 expand_one_mono(x + 1, y, c, nexts, &n_nexts, data, mdata, w, h);
87 if (y > 0){
88 expand_one_mono(x, y - 1, c, nexts, &n_nexts, data, mdata, w, h);
90 if (y < h - 1){
91 expand_one_mono(x, y + 1, c, nexts, &n_nexts, data, mdata, w, h);
94 CvPoint *tmp = starts;
95 starts = nexts;
96 nexts = tmp;
97 n_starts = n_nexts;
99 free(mem);
100 return im;
104 /* a minature state progression within this one, in case the processing is too
105 much for one frame.*/
106 INVISIBLE sparrow_state
107 mode_find_screen(GstSparrow *sparrow, guint8 *in, guint8 *out){
108 sparrow->countdown--;
109 GST_DEBUG("in find_screen with countdown %d\n", sparrow->countdown);
110 sparrow_find_screen_t *finder = (sparrow_find_screen_t *)sparrow->helper_struct;
111 IplImage *im = finder->im;
112 IplImage *green = finder->green;
113 IplImage *working = finder->working;
114 IplImage *mask = finder->mask;
115 /* size is 1 byte per pixel, not 4! */
116 size_t size = sparrow->in.pixcount;
117 CvPoint middle, corner;
118 switch (sparrow->countdown){
119 case 2:
120 /* time to look and see if the screen is there.
121 Look at the histogram of a single channel. */
122 im->imageData = (char*)in;
123 guint32 gshift = sparrow->in.gshift;
124 cvSplit(im,
125 (gshift == 24) ? green : NULL,
126 (gshift == 16) ? green : NULL,
127 (gshift == 8) ? green : NULL,
128 (gshift == 0) ? green : NULL);
129 //int best_t = find_edges_threshold(green);
130 /*XXX if best_t is wrong, add to sparrow->countdown: probably the light is
131 not really on. But what counts as wrong? */
133 //cvCmpS(green, best_t, mask, CV_CMP_GT);
134 cvCanny(green, mask, 100, 170, 3);
135 MAYBE_DEBUG_IPL(mask);
136 goto black;
137 case 1:
138 /* floodfill where the screen is, removing outlying bright spots*/
139 middle = (CvPoint){sparrow->in.width / 2, sparrow->in.height / 2};
140 memset(working->imageData, 255, size);
141 floodfill_mono_superfast(mask, working, middle);
142 MAYBE_DEBUG_IPL(working);
143 goto black;
144 case 0:
145 /* floodfill the border, removing onscreen dirt.*/
146 corner = (CvPoint){0, 0};
147 memset(mask->imageData, 255, size);
148 floodfill_mono_superfast(working, mask, corner);
149 #if STUPID_DEBUG_TRICK
150 cvErode(mask, mask, NULL, 9);
151 #endif
152 MAYBE_DEBUG_IPL(mask);
153 goto finish;
154 default:
155 /*send white and wait for the picture to arrive back. */
156 memset(out, 255, sparrow->out.size);
157 return SPARROW_STATUS_QUO;
159 black:
160 memset(out, 0, sparrow->out.size);
161 return SPARROW_STATUS_QUO;
162 finish:
163 memset(out, 0, sparrow->out.size);
164 return SPARROW_NEXT_STATE;
167 INVISIBLE void
168 finalise_find_screen(GstSparrow *sparrow){
169 sparrow_find_screen_t *finder = (sparrow_find_screen_t *)sparrow->helper_struct;
170 GST_DEBUG("finalise_find_screen: green %p, working %p, mask %p, im %p finder %p\n",
171 finder->green, finder->working, finder->mask, finder->im, finder);
172 cvReleaseImage(&finder->green);
173 cvReleaseImage(&finder->working);
174 cvReleaseImageHeader(&finder->mask);
175 cvReleaseImageHeader(&finder->im);
176 free(finder);
179 INVISIBLE void
180 init_find_screen(GstSparrow *sparrow){
181 sparrow_find_screen_t *finder = zalloc_aligned_or_die(sizeof(sparrow_find_screen_t));
182 sparrow->helper_struct = (void *)finder;
183 sparrow->countdown = sparrow->lag + 5;
184 CvSize size = {sparrow->in.width, sparrow->in.height};
185 finder->green = cvCreateImage(size, IPL_DEPTH_8U, 1);
186 finder->working = cvCreateImage(size, IPL_DEPTH_8U, 1);
188 finder->im = init_ipl_image(&sparrow->in, PIXSIZE);
189 finder->mask = init_ipl_image(&sparrow->in, 1);
191 finder->mask->imageData = (char *)sparrow->screenmask;
192 GST_DEBUG("init_find_screen: green %p, working %p, mask %p, im %p finder %p\n",
193 finder->green, finder->working, finder->mask, finder->im, finder);