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.
20 #include "gstsparrow.h"
25 #define STUPID_DEBUG_TRICK 0
26 #define WAIT_TIME CALIBRATE_MAX_T + 5
28 typedef struct sparrow_find_screen_s
{
35 } sparrow_find_screen_t
;
38 /* Floodfill for find screen */
40 expand_one_mono(int x
, int y
, int c
,
41 CvPoint
*nexts
, int *n_nexts
, guint8
*im
, guint8
*mask
, int w
, int h
){
42 guint8 p
= im
[y
* w
+ x
];
43 guint8
*m
= &mask
[y
* w
+ x
];
46 nexts
[*n_nexts
].x
= x
;
47 nexts
[*n_nexts
].y
= y
;
53 im: the image to be analysed
54 mim: the mask image to be written
55 start: a point of the right colour.
59 floodfill_mono_superfast(IplImage
*im
, IplImage
*mim
, CvPoint start
)
61 guint8
* data
= (guint8
*)im
->imageData
;
62 guint8
* mdata
= (guint8
*)mim
->imageData
;
70 //malloc 2 lists of points. These *could* be as large as the image (but never should be)
71 void * mem
= malloc_or_die(w
* h
* 2 * sizeof(CvPoint
));
73 nexts
= starts
+ w
* h
;
80 for (i
= 0; i
< n_starts
; i
++){
83 int c
= data
[y
* w
+ x
];
85 expand_one_mono(x
- 1, y
, c
, nexts
, &n_nexts
, data
, mdata
, w
, h
);
88 expand_one_mono(x
+ 1, y
, c
, nexts
, &n_nexts
, data
, mdata
, w
, h
);
91 expand_one_mono(x
, y
- 1, c
, nexts
, &n_nexts
, data
, mdata
, w
, h
);
94 expand_one_mono(x
, y
+ 1, c
, nexts
, &n_nexts
, data
, mdata
, w
, h
);
97 CvPoint
*tmp
= starts
;
106 static inline IplImage
*
107 extract_green_channel(GstSparrow
*sparrow
, sparrow_find_screen_t
*finder
, guint8
*in
)
109 IplImage
*im
= finder
->im
;
110 IplImage
*green
= finder
->green
;
111 im
->imageData
= (char*)in
;
112 guint32 gshift
= sparrow
->in
.gshift
;
113 GST_DEBUG("gshift is %d, green is %p, data is %p, im data is %p",
114 gshift
, green
, green
->imageData
, im
->imageData
);
116 (gshift
== 24) ? green
: NULL
,
117 (gshift
== 16) ? green
: NULL
,
118 (gshift
== 8) ? green
: NULL
,
119 (gshift
== 0) ? green
: NULL
);
120 GST_DEBUG("returning green %p, data %p",
121 green
, green
->imageData
);
126 #define SIGNAL_THRESHOLD 100
127 /*see whether there seems to be activity: */
129 check_for_signal(GstSparrow
*sparrow
, sparrow_find_screen_t
*finder
, guint8
*in
){
130 IplImage
*green
= extract_green_channel(sparrow
, finder
, in
);
131 IplImage
*working
= finder
->working
;
133 gboolean answer
= FALSE
;
134 cvAbsDiff(green
, finder
->working
, finder
->signal
);
135 for (i
= 0; i
< sparrow
->in
.pixcount
; i
++){
136 if (finder
->signal
->imageData
[i
] > SIGNAL_THRESHOLD
){
141 memcpy(working
->imageData
, green
->imageData
, sparrow
->in
.pixcount
);
142 //char *tmp = working->imageData;
143 //working->imageData = green->imageData;
144 //green->imageData = tmp;
145 GST_DEBUG("answering %d", answer
);
150 /* a minature state progression within this one, in case the processing is too
151 much for one frame.*/
152 INVISIBLE sparrow_state
153 mode_find_screen(GstSparrow
*sparrow
, GstBuffer
*inbuf
, GstBuffer
*outbuf
){
154 guint8
*in
= GST_BUFFER_DATA(inbuf
);
155 guint8
*out
= GST_BUFFER_DATA(outbuf
);
156 sparrow
->countdown
--;
157 GST_DEBUG("in find_screen with countdown %d\n", sparrow
->countdown
);
158 sparrow_find_screen_t
*finder
= (sparrow_find_screen_t
*)sparrow
->helper_struct
;
160 IplImage
*working
= finder
->working
;
161 IplImage
*mask
= finder
->mask
;
162 /* size is 1 byte per pixel, not 4! */
163 size_t size
= sparrow
->in
.pixcount
;
164 CvPoint middle
, corner
;
165 switch (sparrow
->countdown
){
170 /*send white and wait for the picture to arrive back. */
173 /* time to look and see if the screen is there.
174 Look at the histogram of a single channel. */
175 green
= extract_green_channel(sparrow
, finder
, in
);
176 cvCanny(green
, mask
, 100, 170, 3);
177 cvDilate(mask
, mask
, NULL
, 1);
178 MAYBE_DEBUG_IPL(mask
);
181 /* floodfill where the screen is, removing outlying bright spots*/
182 middle
= (CvPoint
){sparrow
->in
.width
/ 2, sparrow
->in
.height
/ 2};
183 memset(working
->imageData
, 255, size
);
184 floodfill_mono_superfast(mask
, working
, middle
);
185 MAYBE_DEBUG_IPL(working
);
188 /* floodfill the border, removing onscreen dirt.*/
189 corner
= (CvPoint
){0, 0};
190 memset(mask
->imageData
, 255, size
);
191 floodfill_mono_superfast(working
, mask
, corner
);
192 #if STUPID_DEBUG_TRICK
193 cvErode(mask
, mask
, NULL
, 9);
195 cvDilate(mask
, mask
, NULL
, 1);
196 MAYBE_DEBUG_IPL(mask
);
199 GST_DEBUG("checking for signal. sparrow countdown is %d", sparrow
->countdown
);
200 if (check_for_signal(sparrow
, finder
, in
)){
201 sparrow
->countdown
= sparrow
->lag
+ WAIT_TIME
;
206 memset(out
, 255, sparrow
->out
.size
);
207 return SPARROW_STATUS_QUO
;
209 memset(out
, 0, sparrow
->out
.size
);
210 return SPARROW_STATUS_QUO
;
212 memset(out
, 0, sparrow
->out
.size
);
213 return SPARROW_NEXT_STATE
;
217 finalise_find_screen(GstSparrow
*sparrow
){
218 sparrow_find_screen_t
*finder
= (sparrow_find_screen_t
*)sparrow
->helper_struct
;
219 GST_DEBUG("finalise_find_screen: green %p, working %p, mask %p, im %p finder %p\n",
220 finder
->green
, finder
->working
, finder
->mask
, finder
->im
, finder
);
221 cvReleaseImage(&finder
->signal
);
222 cvReleaseImage(&finder
->green
);
223 cvReleaseImage(&finder
->working
);
224 cvReleaseImageHeader(&finder
->mask
);
225 cvReleaseImageHeader(&finder
->im
);
230 init_find_screen(GstSparrow
*sparrow
){
231 sparrow_find_screen_t
*finder
= zalloc_aligned_or_die(sizeof(sparrow_find_screen_t
));
232 sparrow
->helper_struct
= (void *)finder
;
233 sparrow
->countdown
= sparrow
->lag
+ WAIT_TIME
;
234 finder
->waiting
= TRUE
;
235 CvSize size
= {sparrow
->in
.width
, sparrow
->in
.height
};
236 finder
->green
= cvCreateImage(size
, IPL_DEPTH_8U
, 1);
237 finder
->working
= cvCreateImage(size
, IPL_DEPTH_8U
, 1);
238 finder
->signal
= cvCreateImage(size
, IPL_DEPTH_8U
, 1);
239 finder
->im
= init_ipl_image(&sparrow
->in
, PIXSIZE
);
240 finder
->mask
= init_ipl_image(&sparrow
->in
, 1);
242 finder
->mask
->imageData
= (char *)sparrow
->screenmask
;
243 GST_DEBUG("init_find_screen: green %p, working %p, mask %p, im %p finder %p\n",
244 finder
->green
, finder
->working
, finder
->mask
, finder
->im
, finder
);