motioncells: Use no network API if not required
[platform/upstream/gstreamer.git] / ext / opencv / MotionCells.cpp
1 /*
2  * GStreamer
3  * Copyright (C) 2011 Robert Jobbagy <jobbagy.robert@gmail.com>
4  * Copyright (C) 2011 Nicola Murino <nicola.murino@gmail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Alternatively, the contents of this file may be used under the
25  * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
26  * which case the following provisions apply instead of the ones
27  * mentioned above:
28  *
29  * This library is free software; you can redistribute it and/or
30  * modify it under the terms of the GNU Library General Public
31  * License as published by the Free Software Foundation; either
32  * version 2 of the License, or (at your option) any later version.
33  *
34  * This library is distributed in the hope that it will be useful,
35  * but WITHOUT ANY WARRANTY; without even the implied warranty of
36  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
37  * Library General Public License for more details.
38  *
39  * You should have received a copy of the GNU Library General Public
40  * License along with this library; if not, write to the
41  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
42  * Boston, MA 02110-1301, USA.
43  */
44
45 /* This breaks the build for reasons that aren't entirely clear to me yet */
46 #if 0
47 //#ifdef HAVE_CONFIG_H
48 //#include "config.h"
49 //#endif
50 #endif
51
52 #include <cstdlib>
53 #include <errno.h>
54 #include <math.h>
55 #include <gst/gst.h>
56 #include "MotionCells.h"
57
58 MotionCells::MotionCells ()
59 {
60   m_framecnt = 0;
61   m_motioncells_idx_count = 0;
62   m_motioncellsidxcstr = NULL;
63   m_saveInDatafile = false;
64   mc_savefile = NULL;
65   m_pcurFrame = NULL;
66   m_pprevFrame = NULL;
67   transparencyimg = NULL;
68   m_pdifferenceImage = NULL;
69   m_pbwImage = NULL;
70   m_initdatafilefailed = new char[BUSMSGLEN];
71   m_savedatafilefailed = new char[BUSMSGLEN];
72   m_initerrorcode = 0;
73   m_saveerrorcode = 0;
74   m_alpha = 0.5;
75   m_beta = 0.5;
76   m_useAlpha = false;
77   m_isVisible = false;
78
79 }
80
81 MotionCells::~MotionCells ()
82 {
83   if (mc_savefile) {
84     fclose (mc_savefile);
85     mc_savefile = NULL;
86   }
87   delete[]m_initdatafilefailed;
88   delete[]m_savedatafilefailed;
89   if (m_motioncellsidxcstr)
90     delete[]m_motioncellsidxcstr;
91   if (m_pcurFrame)
92     cvReleaseImage (&m_pcurFrame);
93   if (m_pprevFrame)
94     cvReleaseImage (&m_pprevFrame);
95   if (transparencyimg)
96     cvReleaseImage (&transparencyimg);
97   if (m_pdifferenceImage)
98     cvReleaseImage (&m_pdifferenceImage);
99   if (m_pbwImage)
100     cvReleaseImage (&m_pbwImage);
101 }
102
103 int
104 MotionCells::performDetectionMotionCells (IplImage * p_frame,
105     double p_sensitivity, double p_framerate, int p_gridx, int p_gridy,
106     gint64 timestamp_millisec, bool p_isVisible, bool p_useAlpha,
107     int motionmaskcoord_count, motionmaskcoordrect * motionmaskcoords,
108     int motionmaskcells_count, motioncellidx * motionmaskcellsidx,
109     cellscolor motioncellscolor, int motioncells_count,
110     motioncellidx * motioncellsidx, gint64 starttime, char *p_datafile,
111     bool p_changed_datafile, int p_thickness)
112 {
113
114   int sumframecnt = 0;
115   int ret = 0;
116   p_framerate >= 1 ? p_framerate <= 5 ? sumframecnt = 1
117       : p_framerate <= 10 ? sumframecnt = 2
118       : p_framerate <= 15 ? sumframecnt = 3
119       : p_framerate <= 20 ? sumframecnt = 4
120       : p_framerate <= 25 ? sumframecnt = 5
121       : p_framerate <= 30 ? sumframecnt = 6 : sumframecnt = 0 : sumframecnt = 0;
122
123   m_framecnt++;
124   m_changed_datafile = p_changed_datafile;
125   if (m_framecnt >= sumframecnt) {
126     m_useAlpha = p_useAlpha;
127     m_gridx = p_gridx;
128     m_gridy = p_gridy;
129     if (m_changed_datafile) {
130       ret = initDataFile (p_datafile, starttime);
131       if (ret != 0)
132         return ret;
133     }
134
135     m_frameSize = cvGetSize (p_frame);
136     m_frameSize.width /= 2;
137     m_frameSize.height /= 2;
138     setMotionCells (m_frameSize.width, m_frameSize.height);
139     m_sensitivity = 1 - p_sensitivity;
140     m_isVisible = p_isVisible;
141     m_pcurFrame = cvCloneImage (p_frame);
142     IplImage *m_pcurgreyImage = cvCreateImage (m_frameSize, IPL_DEPTH_8U, 1);
143     IplImage *m_pprevgreyImage = cvCreateImage (m_frameSize, IPL_DEPTH_8U, 1);
144     IplImage *m_pgreyImage = cvCreateImage (m_frameSize, IPL_DEPTH_8U, 1);
145     IplImage *m_pcurDown =
146         cvCreateImage (m_frameSize, m_pcurFrame->depth, m_pcurFrame->nChannels);
147     IplImage *m_pprevDown = cvCreateImage (m_frameSize, m_pprevFrame->depth,
148         m_pprevFrame->nChannels);
149     m_pbwImage = cvCreateImage (m_frameSize, IPL_DEPTH_8U, 1);
150     cvPyrDown (m_pprevFrame, m_pprevDown);
151     cvCvtColor (m_pprevDown, m_pprevgreyImage, CV_RGB2GRAY);
152     cvPyrDown (m_pcurFrame, m_pcurDown);
153     cvCvtColor (m_pcurDown, m_pcurgreyImage, CV_RGB2GRAY);
154     m_pdifferenceImage = cvCloneImage (m_pcurgreyImage);
155     //cvSmooth(m_pcurgreyImage, m_pcurgreyImage, CV_GAUSSIAN, 3, 0);//TODO camera noise reduce,something smoothing, and rethink runningavg weights
156
157     //Minus the current gray frame from the 8U moving average.
158     cvAbsDiff (m_pprevgreyImage, m_pcurgreyImage, m_pdifferenceImage);
159
160     //Convert the image to black and white.
161     cvAdaptiveThreshold (m_pdifferenceImage, m_pbwImage, 255,
162         CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, 7);
163
164     // Dilate and erode to get object blobs
165     cvDilate (m_pbwImage, m_pbwImage, NULL, 2);
166     cvErode (m_pbwImage, m_pbwImage, NULL, 2);
167
168     //mask-out the overlay on difference image
169     if (motionmaskcoord_count > 0)
170       performMotionMaskCoords (motionmaskcoords, motionmaskcoord_count);
171     if (motionmaskcells_count > 0)
172       performMotionMask (motionmaskcellsidx, motionmaskcells_count);
173     if (getIsNonZero (m_pbwImage)) {    //detect Motion
174       if (m_MotionCells.size () > 0)    //it contains previous motioncells what we used when frames dropped
175         m_MotionCells.clear ();
176       if (transparencyimg)
177         cvReleaseImage (&transparencyimg);
178       (motioncells_count > 0) ?
179           calculateMotionPercentInMotionCells (motioncellsidx,
180           motioncells_count)
181           : calculateMotionPercentInMotionCells (motionmaskcellsidx, 0);
182
183       transparencyimg = cvCreateImage (cvGetSize (p_frame), p_frame->depth, 3);
184       cvSetZero (transparencyimg);
185       if (m_motioncellsidxcstr)
186         delete[]m_motioncellsidxcstr;
187       m_motioncells_idx_count = m_MotionCells.size () * MSGLEN; //one motion cell idx: (lin idx : col idx,) it's 4 character except last motion cell idx
188       m_motioncellsidxcstr = new char[m_motioncells_idx_count];
189       char *tmpstr = new char[MSGLEN];
190       for (int i = 0; i < MSGLEN; i++)
191         tmpstr[i] = ' ';
192       for (unsigned int i = 0; i < m_MotionCells.size (); i++) {
193         CvPoint pt1, pt2;
194         pt1.x = m_MotionCells.at (i).cell_pt1.x * 2;
195         pt1.y = m_MotionCells.at (i).cell_pt1.y * 2;
196         pt2.x = m_MotionCells.at (i).cell_pt2.x * 2;
197         pt2.y = m_MotionCells.at (i).cell_pt2.y * 2;
198         if (m_useAlpha && m_isVisible) {
199           cvRectangle (transparencyimg,
200               pt1,
201               pt2,
202               CV_RGB (motioncellscolor.B_channel_value,
203                   motioncellscolor.G_channel_value,
204                   motioncellscolor.R_channel_value), CV_FILLED);
205         } else if (m_isVisible) {
206           cvRectangle (p_frame,
207               pt1,
208               pt2,
209               CV_RGB (motioncellscolor.B_channel_value,
210                   motioncellscolor.G_channel_value,
211                   motioncellscolor.R_channel_value), p_thickness);
212         }
213
214         if (i < m_MotionCells.size () - 1) {
215           snprintf (tmpstr, MSGLEN, "%d:%d,", m_MotionCells.at (i).lineidx,
216               m_MotionCells.at (i).colidx);
217         } else {
218           snprintf (tmpstr, MSGLEN, "%d:%d", m_MotionCells.at (i).lineidx,
219               m_MotionCells.at (i).colidx);
220         }
221         if (i == 0)
222           strncpy (m_motioncellsidxcstr, tmpstr, m_motioncells_idx_count);
223         else
224           strcat (m_motioncellsidxcstr, tmpstr);
225       }
226       if (m_MotionCells.size () == 0)
227         strncpy (m_motioncellsidxcstr, " ", m_motioncells_idx_count);
228
229       if (m_useAlpha && m_isVisible) {
230         if (m_MotionCells.size () > 0)
231           blendImages (p_frame, transparencyimg, m_alpha, m_beta);
232       }
233
234       delete[]tmpstr;
235
236       if (mc_savefile && m_saveInDatafile) {
237         ret = saveMotionCells (timestamp_millisec);
238         if (ret != 0)
239           return ret;
240       }
241     } else {
242       m_motioncells_idx_count = 0;
243       if (m_MotionCells.size () > 0)
244         m_MotionCells.clear ();
245       if (transparencyimg)
246         cvReleaseImage (&transparencyimg);
247     }
248
249     if (m_pprevFrame)
250       cvReleaseImage (&m_pprevFrame);
251     m_pprevFrame = cvCloneImage (m_pcurFrame);
252     m_framecnt = 0;
253     if (m_pcurFrame)
254       cvReleaseImage (&m_pcurFrame);
255     if (m_pdifferenceImage)
256       cvReleaseImage (&m_pdifferenceImage);
257     if (m_pcurgreyImage)
258       cvReleaseImage (&m_pcurgreyImage);
259     if (m_pprevgreyImage)
260       cvReleaseImage (&m_pprevgreyImage);
261     if (m_pgreyImage)
262       cvReleaseImage (&m_pgreyImage);
263     if (m_pbwImage)
264       cvReleaseImage (&m_pbwImage);
265     if (m_pprevDown)
266       cvReleaseImage (&m_pprevDown);
267     if (m_pcurDown)
268       cvReleaseImage (&m_pcurDown);
269     if (m_pCells) {
270       for (int i = 0; i < m_gridy; ++i) {
271         delete[]m_pCells[i];
272       }
273       delete[]m_pCells;
274     }
275
276     if (p_framerate <= 5) {
277       if (m_MotionCells.size () > 0)
278         m_MotionCells.clear ();
279       if (transparencyimg)
280         cvReleaseImage (&transparencyimg);
281     }
282   } else {                      //we do frame drop
283     m_motioncells_idx_count = 0;
284     ret = -2;
285     for (unsigned int i = 0; i < m_MotionCells.size (); i++) {
286       CvPoint pt1, pt2;
287       pt1.x = m_MotionCells.at (i).cell_pt1.x * 2;
288       pt1.y = m_MotionCells.at (i).cell_pt1.y * 2;
289       pt2.x = m_MotionCells.at (i).cell_pt2.x * 2;
290       pt2.y = m_MotionCells.at (i).cell_pt2.y * 2;
291       if (m_useAlpha && m_isVisible) {
292         cvRectangle (transparencyimg,
293             pt1,
294             pt2,
295             CV_RGB (motioncellscolor.B_channel_value,
296                 motioncellscolor.G_channel_value,
297                 motioncellscolor.R_channel_value), CV_FILLED);
298       } else if (m_isVisible) {
299         cvRectangle (p_frame,
300             pt1,
301             pt2,
302             CV_RGB (motioncellscolor.B_channel_value,
303                 motioncellscolor.G_channel_value,
304                 motioncellscolor.R_channel_value), p_thickness);
305       }
306
307     }
308     if (m_useAlpha && m_isVisible) {
309       if (m_MotionCells.size () > 0)
310         blendImages (p_frame, transparencyimg, m_alpha, m_beta);
311     }
312   }
313   return ret;
314 }
315
316 int
317 MotionCells::initDataFile (char *p_datafile, gint64 starttime)  //p_date is increased with difference between current and previous buffer ts
318 {
319   MotionCellData mcd;
320   if (strncmp (p_datafile, " ", 1)) {
321     mc_savefile = fopen (p_datafile, "w");
322     if (mc_savefile == NULL) {
323       //fprintf(stderr, "%s %d:initDataFile:fopen:%d (%s)\n", __FILE__, __LINE__, errno,
324       //strerror(errno));
325       strncpy (m_initdatafilefailed, strerror (errno), BUSMSGLEN - 1);
326       m_initerrorcode = errno;
327       return 1;
328     } else {
329       m_saveInDatafile = true;
330     }
331   } else
332     mc_savefile = NULL;
333   memset (&m_header, 0, sizeof (MotionCellHeader));
334   m_header.headersize = GINT32_TO_BE (MC_HEADER);
335   m_header.type = GINT32_TO_BE (MC_TYPE);
336   m_header.version = GINT32_TO_BE (MC_VERSION);
337   //it needs these bytes
338   m_header.itemsize =
339       GINT32_TO_BE ((int) ceil (ceil (m_gridx * m_gridy / 8.0) / 4.0) * 4 +
340       sizeof (mcd.timestamp));
341   m_header.gridx = GINT32_TO_BE (m_gridx);
342   m_header.gridy = GINT32_TO_BE (m_gridy);
343   m_header.starttime = GINT64_TO_BE (starttime);
344
345   snprintf (m_header.name, sizeof (m_header.name), "%s %dx%d", MC_VERSIONTEXT,
346       GINT32_FROM_BE (m_header.gridx), GINT32_FROM_BE (m_header.gridy));
347   m_changed_datafile = false;
348   return 0;
349 }
350
351 int
352 MotionCells::saveMotionCells (gint64 timestamp_millisec)
353 {
354
355   MotionCellData mc_data;
356   mc_data.timestamp = GINT32_TO_BE (timestamp_millisec);
357   mc_data.data = NULL;
358   //There is no datafile
359   if (mc_savefile == NULL)
360     return 0;
361
362   if (ftello (mc_savefile) == 0) {
363     //cerr << "Writing out file header"<< m_header.headersize <<":" << sizeof(MotionCellHeader) << " itemsize:"
364     //<< m_header.itemsize << endl;
365     if (fwrite (&m_header, sizeof (MotionCellHeader), 1, mc_savefile) != 1) {
366       //fprintf(stderr, "%s %d:saveMotionCells:fwrite:%d (%s)\n", __FILE__, __LINE__, errno,
367       //strerror(errno));
368       strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
369       m_saveerrorcode = errno;
370       return -1;
371     }
372   }
373
374   mc_data.data =
375       (char *) calloc (1,
376       GINT32_FROM_BE (m_header.itemsize) - sizeof (mc_data.timestamp));
377   if (mc_data.data == NULL) {
378     //fprintf(stderr, "%s %d:saveMotionCells:calloc:%d (%s)\n", __FILE__, __LINE__, errno,
379     //strerror(errno));
380     strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
381     m_saveerrorcode = errno;
382     return -1;
383   }
384
385   for (unsigned int i = 0; i < m_MotionCells.size (); i++) {
386     int bitnum =
387         m_MotionCells.at (i).lineidx * GINT32_FROM_BE (m_header.gridx) +
388         m_MotionCells.at (i).colidx;
389     int bytenum = (int) floor (bitnum / 8.0);
390     int shift = bitnum - bytenum * 8;
391     mc_data.data[bytenum] = mc_data.data[bytenum] | (1 << shift);
392     //cerr << "Motion Detected " <<  "line:" << m_MotionCells.at(i).lineidx << " col:" << m_MotionCells.at(i).colidx;
393     //cerr << "    bitnum " << bitnum << " bytenum " << bytenum << " shift " << shift << " value " << (int)mc_data.data[bytenum] << endl;
394   }
395
396   if (fwrite (&mc_data.timestamp, sizeof (mc_data.timestamp), 1,
397           mc_savefile) != 1) {
398     //fprintf(stderr, "%s %d:saveMotionCells:fwrite:%d (%s)\n", __FILE__, __LINE__, errno,
399     //strerror(errno));
400     strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
401     m_saveerrorcode = errno;
402     return -1;
403   }
404
405   if (fwrite (mc_data.data,
406           GINT32_FROM_BE (m_header.itemsize) - sizeof (mc_data.timestamp), 1,
407           mc_savefile) != 1) {
408     //fprintf(stderr, "%s %d:saveMotionCells:fwrite:%d (%s)\n", __FILE__, __LINE__, errno,
409     //strerror(errno));
410     strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
411     m_saveerrorcode = errno;
412     return -1;
413   }
414
415   free (mc_data.data);
416   return 0;
417 }
418
419 double
420 MotionCells::calculateMotionPercentInCell (int p_row, int p_col,
421     double *p_cellarea, double *p_motionarea)
422 {
423   double cntpixelsnum = 0;
424   double cntmotionpixelnum = 0;
425
426   int ybegin = floor ((double) p_row * m_cellheight);
427   int yend = floor ((double) (p_row + 1) * m_cellheight);
428   int xbegin = floor ((double) (p_col) * m_cellwidth);
429   int xend = floor ((double) (p_col + 1) * m_cellwidth);
430   int cellw = xend - xbegin;
431   int cellh = yend - ybegin;
432   int cellarea = cellw * cellh;
433   *p_cellarea = cellarea;
434   int thresholdmotionpixelnum = floor ((double) cellarea * m_sensitivity);
435
436   for (int i = ybegin; i < yend; i++) {
437     for (int j = xbegin; j < xend; j++) {
438       cntpixelsnum++;
439       if ((((uchar *) (m_pbwImage->imageData + m_pbwImage->widthStep * i))[j]) >
440           0) {
441         cntmotionpixelnum++;
442         if (cntmotionpixelnum >= thresholdmotionpixelnum) {     //we dont needs calculate anymore
443           *p_motionarea = cntmotionpixelnum;
444           return (cntmotionpixelnum / cntpixelsnum);
445         }
446       }
447       int remainingpixelsnum = cellarea - cntpixelsnum;
448       if ((cntmotionpixelnum + remainingpixelsnum) < thresholdmotionpixelnum) { //moving pixels number will be less than threshold
449         *p_motionarea = 0;
450         return 0;
451       }
452     }
453   }
454
455   return (cntmotionpixelnum / cntpixelsnum);
456 }
457
458 void
459 MotionCells::calculateMotionPercentInMotionCells (motioncellidx *
460     p_motioncellsidx, int p_motioncells_count)
461 {
462   if (p_motioncells_count == 0) {
463     for (int i = 0; i < m_gridy; i++) {
464       for (int j = 0; j < m_gridx; j++) {
465         m_pCells[i][j].MotionPercent = calculateMotionPercentInCell (i, j,
466             &m_pCells[i][j].CellArea, &m_pCells[i][j].MotionArea);
467         m_pCells[i][j].hasMotion =
468             m_sensitivity < m_pCells[i][j].MotionPercent ? true : false;
469         if (m_pCells[i][j].hasMotion) {
470           MotionCellsIdx mci;
471           mci.lineidx = i;
472           mci.colidx = j;
473           mci.cell_pt1.x = floor ((double) j * m_cellwidth);
474           mci.cell_pt1.y = floor ((double) i * m_cellheight);
475           mci.cell_pt2.x = floor ((double) (j + 1) * m_cellwidth);
476           mci.cell_pt2.y = floor ((double) (i + 1) * m_cellheight);
477           int w = mci.cell_pt2.x - mci.cell_pt1.x;
478           int h = mci.cell_pt2.y - mci.cell_pt1.y;
479           mci.motioncell = cvRect (mci.cell_pt1.x, mci.cell_pt1.y, w, h);
480           m_MotionCells.push_back (mci);
481         }
482       }
483     }
484   } else {
485     for (int k = 0; k < p_motioncells_count; ++k) {
486
487       int i = p_motioncellsidx[k].lineidx;
488       int j = p_motioncellsidx[k].columnidx;
489       m_pCells[i][j].MotionPercent =
490           calculateMotionPercentInCell (i, j,
491           &m_pCells[i][j].CellArea, &m_pCells[i][j].MotionArea);
492       m_pCells[i][j].hasMotion =
493           m_pCells[i][j].MotionPercent > m_sensitivity ? true : false;
494       if (m_pCells[i][j].hasMotion) {
495         MotionCellsIdx mci;
496         mci.lineidx = p_motioncellsidx[k].lineidx;
497         mci.colidx = p_motioncellsidx[k].columnidx;
498         mci.cell_pt1.x = floor ((double) j * m_cellwidth);
499         mci.cell_pt1.y = floor ((double) i * m_cellheight);
500         mci.cell_pt2.x = floor ((double) (j + 1) * m_cellwidth);
501         mci.cell_pt2.y = floor ((double) (i + 1) * m_cellheight);
502         int w = mci.cell_pt2.x - mci.cell_pt1.x;
503         int h = mci.cell_pt2.y - mci.cell_pt1.y;
504         mci.motioncell = cvRect (mci.cell_pt1.x, mci.cell_pt1.y, w, h);
505         m_MotionCells.push_back (mci);
506       }
507     }
508   }
509 }
510
511 void
512 MotionCells::performMotionMaskCoords (motionmaskcoordrect * p_motionmaskcoords,
513     int p_motionmaskcoords_count)
514 {
515   CvPoint upperleft;
516   upperleft.x = 0;
517   upperleft.y = 0;
518   CvPoint lowerright;
519   lowerright.x = 0;
520   lowerright.y = 0;
521   for (int i = 0; i < p_motionmaskcoords_count; i++) {
522     upperleft.x = p_motionmaskcoords[i].upper_left_x;
523     upperleft.y = p_motionmaskcoords[i].upper_left_y;
524     lowerright.x = p_motionmaskcoords[i].lower_right_x;
525     lowerright.y = p_motionmaskcoords[i].lower_right_y;
526     cvRectangle (m_pbwImage, upperleft, lowerright, CV_RGB (0, 0, 0),
527         CV_FILLED);
528   }
529 }
530
531 void
532 MotionCells::performMotionMask (motioncellidx * p_motionmaskcellsidx,
533     int p_motionmaskcells_count)
534 {
535   for (int k = 0; k < p_motionmaskcells_count; k++) {
536     int beginy = p_motionmaskcellsidx[k].lineidx * m_cellheight;
537     int beginx = p_motionmaskcellsidx[k].columnidx * m_cellwidth;
538     int endx =
539         (double) p_motionmaskcellsidx[k].columnidx * m_cellwidth + m_cellwidth;
540     int endy =
541         (double) p_motionmaskcellsidx[k].lineidx * m_cellheight + m_cellheight;
542     for (int i = beginy; i < endy; i++)
543       for (int j = beginx; j < endx; j++) {
544         ((uchar *) (m_pbwImage->imageData + m_pbwImage->widthStep * i))[j] = 0;
545       }
546   }
547 }
548
549 ///BGR if we use only OpenCV
550 //RGB if we use gst+OpenCV
551 void
552 MotionCells::blendImages (IplImage * p_actFrame, IplImage * p_cellsFrame,
553     float p_alpha, float p_beta)
554 {
555
556   int height = p_actFrame->height;
557   int width = p_actFrame->width;
558   int step = p_actFrame->widthStep / sizeof (uchar);
559   int channels = p_actFrame->nChannels;
560   int cellstep = p_cellsFrame->widthStep / sizeof (uchar);
561   uchar *curImageData = (uchar *) p_actFrame->imageData;
562   uchar *cellImageData = (uchar *) p_cellsFrame->imageData;
563
564   for (int i = 0; i < height; i++)
565     for (int j = 0; j < width; j++)
566       for (int k = 0; k < channels; k++)
567         if (cellImageData[i * cellstep + j * channels + k] > 0) {
568           curImageData[i * step + j * channels + k] =
569               round ((double) curImageData[i * step + j * channels +
570                   k] * p_alpha + ((double) cellImageData[i * cellstep +
571                       j * channels + k] * p_beta));
572         }
573 }