opencv: Fix build for opencv >= 3.4.2
[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 <errno.h>
53 #include "MotionCells.h"
54 #if (CV_MAJOR_VERSION >= 3)
55 #include <opencv2/imgproc.hpp>
56 #endif
57 #include <opencv2/imgproc/imgproc_c.h>
58
59 MotionCells::MotionCells ()
60 {
61   m_framecnt = 0;
62   m_motioncells_idx_count = 0;
63   m_motioncellsidxcstr = NULL;
64   m_saveInDatafile = false;
65   mc_savefile = NULL;
66   m_pcurFrame = NULL;
67   m_pprevFrame = NULL;
68   transparencyimg = NULL;
69   m_pdifferenceImage = NULL;
70   m_pbwImage = NULL;
71   m_initdatafilefailed = new char[BUSMSGLEN];
72   m_savedatafilefailed = new char[BUSMSGLEN];
73   m_initerrorcode = 0;
74   m_saveerrorcode = 0;
75   m_alpha = 0.5;
76   m_beta = 0.5;
77   m_useAlpha = false;
78   m_isVisible = false;
79   m_pCells = NULL;
80   m_gridx = 0;
81   m_gridy = 0;
82   m_cellwidth = 0;
83   m_cellheight = 0;
84   m_sensitivity = 0;
85   m_changed_datafile = false;
86
87   memset (&m_header, 0, sizeof (MotionCellHeader));
88   m_header.headersize = GINT32_TO_BE (MC_HEADER);
89   m_header.type = GINT32_TO_BE (MC_TYPE);
90   m_header.version = GINT32_TO_BE (MC_VERSION);
91   m_header.itemsize = 0;
92   m_header.gridx = 0;
93   m_header.gridy = 0;
94   m_header.starttime = 0;
95 }
96
97 MotionCells::~MotionCells ()
98 {
99   if (mc_savefile) {
100     fclose (mc_savefile);
101     mc_savefile = NULL;
102   }
103   delete[]m_initdatafilefailed;
104   delete[]m_savedatafilefailed;
105   if (m_motioncellsidxcstr)
106     delete[]m_motioncellsidxcstr;
107   if (m_pcurFrame)
108     cvReleaseImage (&m_pcurFrame);
109   if (m_pprevFrame)
110     cvReleaseImage (&m_pprevFrame);
111   if (transparencyimg)
112     cvReleaseImage (&transparencyimg);
113   if (m_pdifferenceImage)
114     cvReleaseImage (&m_pdifferenceImage);
115   if (m_pbwImage)
116     cvReleaseImage (&m_pbwImage);
117 }
118
119 int
120 MotionCells::performDetectionMotionCells (IplImage * p_frame,
121     double p_sensitivity, double p_framerate, int p_gridx, int p_gridy,
122     gint64 timestamp_millisec, bool p_isVisible, bool p_useAlpha,
123     int motionmaskcoord_count, motionmaskcoordrect * motionmaskcoords,
124     int motionmaskcells_count, motioncellidx * motionmaskcellsidx,
125     cellscolor motioncellscolor, int motioncells_count,
126     motioncellidx * motioncellsidx, gint64 starttime, char *p_datafile,
127     bool p_changed_datafile, int p_thickness)
128 {
129
130   int sumframecnt = 0;
131   int ret = 0;
132   CvSize frameSize;
133
134   p_framerate >= 1 ? p_framerate <= 5 ? sumframecnt = 1
135       : p_framerate <= 10 ? sumframecnt = 2
136       : p_framerate <= 15 ? sumframecnt = 3
137       : p_framerate <= 20 ? sumframecnt = 4
138       : p_framerate <= 25 ? sumframecnt = 5
139       : p_framerate <= 30 ? sumframecnt = 6 : sumframecnt = 0 : sumframecnt = 0;
140
141   m_framecnt++;
142   m_changed_datafile = p_changed_datafile;
143   if (m_framecnt >= sumframecnt) {
144     m_useAlpha = p_useAlpha;
145     m_gridx = p_gridx;
146     m_gridy = p_gridy;
147     if (m_changed_datafile) {
148       ret = initDataFile (p_datafile, starttime);
149       if (ret != 0)
150         return ret;
151     }
152
153     frameSize = cvGetSize (p_frame);
154     frameSize.width /= 2;
155     frameSize.height /= 2;
156     setMotionCells (frameSize.width, frameSize.height);
157     m_sensitivity = 1 - p_sensitivity;
158     m_isVisible = p_isVisible;
159     m_pcurFrame = cvCloneImage (p_frame);
160     IplImage *m_pcurgreyImage = cvCreateImage (frameSize, IPL_DEPTH_8U, 1);
161     IplImage *m_pprevgreyImage = cvCreateImage (frameSize, IPL_DEPTH_8U, 1);
162     IplImage *m_pgreyImage = cvCreateImage (frameSize, IPL_DEPTH_8U, 1);
163     IplImage *m_pcurDown =
164         cvCreateImage (frameSize, m_pcurFrame->depth, m_pcurFrame->nChannels);
165     IplImage *m_pprevDown = cvCreateImage (frameSize, m_pprevFrame->depth,
166         m_pprevFrame->nChannels);
167     m_pbwImage = cvCreateImage (frameSize, IPL_DEPTH_8U, 1);
168     cvPyrDown (m_pprevFrame, m_pprevDown);
169     cvCvtColor (m_pprevDown, m_pprevgreyImage, CV_RGB2GRAY);
170     cvPyrDown (m_pcurFrame, m_pcurDown);
171     cvCvtColor (m_pcurDown, m_pcurgreyImage, CV_RGB2GRAY);
172     m_pdifferenceImage = cvCloneImage (m_pcurgreyImage);
173     //cvSmooth(m_pcurgreyImage, m_pcurgreyImage, CV_GAUSSIAN, 3, 0);//TODO camera noise reduce,something smoothing, and rethink runningavg weights
174
175     //Minus the current gray frame from the 8U moving average.
176     cvAbsDiff (m_pprevgreyImage, m_pcurgreyImage, m_pdifferenceImage);
177
178     //Convert the image to black and white.
179     cvAdaptiveThreshold (m_pdifferenceImage, m_pbwImage, 255,
180         CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, 7);
181
182     // Dilate and erode to get object blobs
183     cvDilate (m_pbwImage, m_pbwImage, NULL, 2);
184     cvErode (m_pbwImage, m_pbwImage, NULL, 2);
185
186     //mask-out the overlay on difference image
187     if (motionmaskcoord_count > 0)
188       performMotionMaskCoords (motionmaskcoords, motionmaskcoord_count);
189     if (motionmaskcells_count > 0)
190       performMotionMask (motionmaskcellsidx, motionmaskcells_count);
191     if (getIsNonZero (m_pbwImage)) {    //detect Motion
192       if (m_MotionCells.size () > 0)    //it contains previous motioncells what we used when frames dropped
193         m_MotionCells.clear ();
194       if (transparencyimg)
195         cvReleaseImage (&transparencyimg);
196       (motioncells_count > 0) ?
197           calculateMotionPercentInMotionCells (motioncellsidx,
198           motioncells_count)
199           : calculateMotionPercentInMotionCells (motionmaskcellsidx, 0);
200
201       transparencyimg = cvCreateImage (cvGetSize (p_frame), p_frame->depth, 3);
202       cvSetZero (transparencyimg);
203       if (m_motioncellsidxcstr)
204         delete[]m_motioncellsidxcstr;
205       m_motioncells_idx_count = m_MotionCells.size () * MSGLEN; //one motion cell idx: (lin idx : col idx,) it's up to 6 character except last motion cell idx
206       m_motioncellsidxcstr = new char[m_motioncells_idx_count];
207       char *tmpstr = new char[MSGLEN+ 1];
208       tmpstr[0] = 0;
209       for (unsigned int i = 0; i < m_MotionCells.size (); i++) {
210         CvPoint pt1, pt2;
211         pt1.x = m_MotionCells.at (i).cell_pt1.x * 2;
212         pt1.y = m_MotionCells.at (i).cell_pt1.y * 2;
213         pt2.x = m_MotionCells.at (i).cell_pt2.x * 2;
214         pt2.y = m_MotionCells.at (i).cell_pt2.y * 2;
215         if (m_useAlpha && m_isVisible) {
216           cvRectangle (transparencyimg,
217               pt1,
218               pt2,
219               CV_RGB (motioncellscolor.B_channel_value,
220                   motioncellscolor.G_channel_value,
221                   motioncellscolor.R_channel_value), CV_FILLED);
222         } else if (m_isVisible) {
223           cvRectangle (p_frame,
224               pt1,
225               pt2,
226               CV_RGB (motioncellscolor.B_channel_value,
227                   motioncellscolor.G_channel_value,
228                   motioncellscolor.R_channel_value), p_thickness);
229         }
230
231         if (i < m_MotionCells.size () - 1) {
232           snprintf (tmpstr, MSGLEN+1, "%d:%d,", m_MotionCells.at (i).lineidx,
233               m_MotionCells.at (i).colidx);
234         } else {
235           snprintf (tmpstr, MSGLEN+1, "%d:%d", m_MotionCells.at (i).lineidx,
236               m_MotionCells.at (i).colidx);
237         }
238         if (i == 0)
239           strncpy (m_motioncellsidxcstr, tmpstr, m_motioncells_idx_count);
240         else
241           strcat (m_motioncellsidxcstr, tmpstr);
242       }
243       if (m_MotionCells.size () == 0)
244         strncpy (m_motioncellsidxcstr, " ", m_motioncells_idx_count);
245
246       if (m_useAlpha && m_isVisible) {
247         if (m_MotionCells.size () > 0)
248           blendImages (p_frame, transparencyimg, m_alpha, m_beta);
249       }
250
251       delete[]tmpstr;
252
253       if (mc_savefile && m_saveInDatafile) {
254         ret = saveMotionCells (timestamp_millisec);
255         if (ret != 0)
256           return ret;
257       }
258     } else {
259       m_motioncells_idx_count = 0;
260       if (m_MotionCells.size () > 0)
261         m_MotionCells.clear ();
262       if (transparencyimg)
263         cvReleaseImage (&transparencyimg);
264     }
265
266     if (m_pprevFrame)
267       cvReleaseImage (&m_pprevFrame);
268     m_pprevFrame = cvCloneImage (m_pcurFrame);
269     m_framecnt = 0;
270     if (m_pcurFrame)
271       cvReleaseImage (&m_pcurFrame);
272     if (m_pdifferenceImage)
273       cvReleaseImage (&m_pdifferenceImage);
274     if (m_pcurgreyImage)
275       cvReleaseImage (&m_pcurgreyImage);
276     if (m_pprevgreyImage)
277       cvReleaseImage (&m_pprevgreyImage);
278     if (m_pgreyImage)
279       cvReleaseImage (&m_pgreyImage);
280     if (m_pbwImage)
281       cvReleaseImage (&m_pbwImage);
282     if (m_pprevDown)
283       cvReleaseImage (&m_pprevDown);
284     if (m_pcurDown)
285       cvReleaseImage (&m_pcurDown);
286     if (m_pCells) {
287       for (int i = 0; i < m_gridy; ++i) {
288         delete[]m_pCells[i];
289       }
290       delete[]m_pCells;
291     }
292
293     if (p_framerate <= 5) {
294       if (m_MotionCells.size () > 0)
295         m_MotionCells.clear ();
296       if (transparencyimg)
297         cvReleaseImage (&transparencyimg);
298     }
299   } else {                      //we do frame drop
300     m_motioncells_idx_count = 0;
301     ret = -2;
302     for (unsigned int i = 0; i < m_MotionCells.size (); i++) {
303       CvPoint pt1, pt2;
304       pt1.x = m_MotionCells.at (i).cell_pt1.x * 2;
305       pt1.y = m_MotionCells.at (i).cell_pt1.y * 2;
306       pt2.x = m_MotionCells.at (i).cell_pt2.x * 2;
307       pt2.y = m_MotionCells.at (i).cell_pt2.y * 2;
308       if (m_useAlpha && m_isVisible) {
309         cvRectangle (transparencyimg,
310             pt1,
311             pt2,
312             CV_RGB (motioncellscolor.B_channel_value,
313                 motioncellscolor.G_channel_value,
314                 motioncellscolor.R_channel_value), CV_FILLED);
315       } else if (m_isVisible) {
316         cvRectangle (p_frame,
317             pt1,
318             pt2,
319             CV_RGB (motioncellscolor.B_channel_value,
320                 motioncellscolor.G_channel_value,
321                 motioncellscolor.R_channel_value), p_thickness);
322       }
323
324     }
325     if (m_useAlpha && m_isVisible) {
326       if (m_MotionCells.size () > 0)
327         blendImages (p_frame, transparencyimg, m_alpha, m_beta);
328     }
329   }
330   return ret;
331 }
332
333 int
334 MotionCells::initDataFile (char *p_datafile, gint64 starttime)  //p_date is increased with difference between current and previous buffer ts
335 {
336   MotionCellData mcd;
337   if (strncmp (p_datafile, " ", 1)) {
338     mc_savefile = fopen (p_datafile, "w");
339     if (mc_savefile == NULL) {
340       //fprintf(stderr, "%s %d:initDataFile:fopen:%d (%s)\n", __FILE__, __LINE__, errno,
341       //strerror(errno));
342       strncpy (m_initdatafilefailed, strerror (errno), BUSMSGLEN - 1);
343       m_initerrorcode = errno;
344       return 1;
345     } else {
346       m_saveInDatafile = true;
347     }
348   } else
349     mc_savefile = NULL;
350
351   //it needs these bytes
352   m_header.itemsize =
353       GINT32_TO_BE ((int) ceil (ceil (m_gridx * m_gridy / 8.0) / 4.0) * 4 +
354       sizeof (mcd.timestamp));
355   m_header.gridx = GINT32_TO_BE (m_gridx);
356   m_header.gridy = GINT32_TO_BE (m_gridy);
357   m_header.starttime = GINT64_TO_BE (starttime);
358
359   snprintf (m_header.name, sizeof (m_header.name), "%s %dx%d", MC_VERSIONTEXT,
360       GINT32_FROM_BE (m_header.gridx), GINT32_FROM_BE (m_header.gridy));
361   m_changed_datafile = false;
362   return 0;
363 }
364
365 int
366 MotionCells::saveMotionCells (gint64 timestamp_millisec)
367 {
368
369   MotionCellData mc_data;
370   mc_data.timestamp = GINT32_TO_BE (timestamp_millisec);
371   mc_data.data = NULL;
372   //There is no datafile
373   if (mc_savefile == NULL)
374     return 0;
375
376   if (ftello (mc_savefile) == 0) {
377     //cerr << "Writing out file header"<< m_header.headersize <<":" << sizeof(MotionCellHeader) << " itemsize:"
378     //<< m_header.itemsize << endl;
379     if (fwrite (&m_header, sizeof (MotionCellHeader), 1, mc_savefile) != 1) {
380       //fprintf(stderr, "%s %d:saveMotionCells:fwrite:%d (%s)\n", __FILE__, __LINE__, errno,
381       //strerror(errno));
382       strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
383       m_saveerrorcode = errno;
384       return -1;
385     }
386   }
387
388   mc_data.data =
389       (char *) calloc (1,
390       GINT32_FROM_BE (m_header.itemsize) - sizeof (mc_data.timestamp));
391   if (mc_data.data == NULL) {
392     //fprintf(stderr, "%s %d:saveMotionCells:calloc:%d (%s)\n", __FILE__, __LINE__, errno,
393     //strerror(errno));
394     strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
395     m_saveerrorcode = errno;
396     return -1;
397   }
398
399   for (unsigned int i = 0; i < m_MotionCells.size (); i++) {
400     int bitnum =
401         m_MotionCells.at (i).lineidx * GINT32_FROM_BE (m_header.gridx) +
402         m_MotionCells.at (i).colidx;
403     int bytenum = (int) floor (bitnum / 8.0);
404     int shift = bitnum - bytenum * 8;
405     mc_data.data[bytenum] = mc_data.data[bytenum] | (1 << shift);
406     //cerr << "Motion Detected " <<  "line:" << m_MotionCells.at(i).lineidx << " col:" << m_MotionCells.at(i).colidx;
407     //cerr << "    bitnum " << bitnum << " bytenum " << bytenum << " shift " << shift << " value " << (int)mc_data.data[bytenum] << endl;
408   }
409
410   if (fwrite (&mc_data.timestamp, sizeof (mc_data.timestamp), 1,
411           mc_savefile) != 1) {
412     //fprintf(stderr, "%s %d:saveMotionCells:fwrite:%d (%s)\n", __FILE__, __LINE__, errno,
413     //strerror(errno));
414     strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
415     m_saveerrorcode = errno;
416     return -1;
417   }
418
419   if (fwrite (mc_data.data,
420           GINT32_FROM_BE (m_header.itemsize) - sizeof (mc_data.timestamp), 1,
421           mc_savefile) != 1) {
422     //fprintf(stderr, "%s %d:saveMotionCells:fwrite:%d (%s)\n", __FILE__, __LINE__, errno,
423     //strerror(errno));
424     strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
425     m_saveerrorcode = errno;
426     return -1;
427   }
428
429   free (mc_data.data);
430   return 0;
431 }
432
433 double
434 MotionCells::calculateMotionPercentInCell (int p_row, int p_col,
435     double *p_cellarea, double *p_motionarea)
436 {
437   double cntpixelsnum = 0;
438   double cntmotionpixelnum = 0;
439
440   int ybegin = floor ((double) p_row * m_cellheight);
441   int yend = floor ((double) (p_row + 1) * m_cellheight);
442   int xbegin = floor ((double) (p_col) * m_cellwidth);
443   int xend = floor ((double) (p_col + 1) * m_cellwidth);
444   int cellw = xend - xbegin;
445   int cellh = yend - ybegin;
446   int cellarea = cellw * cellh;
447   *p_cellarea = cellarea;
448   int thresholdmotionpixelnum = floor ((double) cellarea * m_sensitivity);
449
450   for (int i = ybegin; i < yend; i++) {
451     for (int j = xbegin; j < xend; j++) {
452       cntpixelsnum++;
453       if ((((uchar *) (m_pbwImage->imageData + m_pbwImage->widthStep * i))[j]) >
454           0) {
455         cntmotionpixelnum++;
456         if (cntmotionpixelnum >= thresholdmotionpixelnum) {     //we dont needs calculate anymore
457           *p_motionarea = cntmotionpixelnum;
458           return (cntmotionpixelnum / cntpixelsnum);
459         }
460       }
461       int remainingpixelsnum = cellarea - cntpixelsnum;
462       if ((cntmotionpixelnum + remainingpixelsnum) < thresholdmotionpixelnum) { //moving pixels number will be less than threshold
463         *p_motionarea = 0;
464         return 0;
465       }
466     }
467   }
468
469   return (cntmotionpixelnum / cntpixelsnum);
470 }
471
472 void
473 MotionCells::calculateMotionPercentInMotionCells (motioncellidx *
474     p_motioncellsidx, int p_motioncells_count)
475 {
476   if (p_motioncells_count == 0) {
477     for (int i = 0; i < m_gridy; i++) {
478       for (int j = 0; j < m_gridx; j++) {
479         m_pCells[i][j].MotionPercent = calculateMotionPercentInCell (i, j,
480             &m_pCells[i][j].CellArea, &m_pCells[i][j].MotionArea);
481         m_pCells[i][j].hasMotion =
482             m_sensitivity < m_pCells[i][j].MotionPercent ? true : false;
483         if (m_pCells[i][j].hasMotion) {
484           MotionCellsIdx mci;
485           mci.lineidx = i;
486           mci.colidx = j;
487           mci.cell_pt1.x = floor ((double) j * m_cellwidth);
488           mci.cell_pt1.y = floor ((double) i * m_cellheight);
489           mci.cell_pt2.x = floor ((double) (j + 1) * m_cellwidth);
490           mci.cell_pt2.y = floor ((double) (i + 1) * m_cellheight);
491           int w = mci.cell_pt2.x - mci.cell_pt1.x;
492           int h = mci.cell_pt2.y - mci.cell_pt1.y;
493           mci.motioncell = cvRect (mci.cell_pt1.x, mci.cell_pt1.y, w, h);
494           m_MotionCells.push_back (mci);
495         }
496       }
497     }
498   } else {
499     for (int k = 0; k < p_motioncells_count; ++k) {
500
501       int i = p_motioncellsidx[k].lineidx;
502       int j = p_motioncellsidx[k].columnidx;
503       m_pCells[i][j].MotionPercent =
504           calculateMotionPercentInCell (i, j,
505           &m_pCells[i][j].CellArea, &m_pCells[i][j].MotionArea);
506       m_pCells[i][j].hasMotion =
507           m_pCells[i][j].MotionPercent > m_sensitivity ? true : false;
508       if (m_pCells[i][j].hasMotion) {
509         MotionCellsIdx mci;
510         mci.lineidx = p_motioncellsidx[k].lineidx;
511         mci.colidx = p_motioncellsidx[k].columnidx;
512         mci.cell_pt1.x = floor ((double) j * m_cellwidth);
513         mci.cell_pt1.y = floor ((double) i * m_cellheight);
514         mci.cell_pt2.x = floor ((double) (j + 1) * m_cellwidth);
515         mci.cell_pt2.y = floor ((double) (i + 1) * m_cellheight);
516         int w = mci.cell_pt2.x - mci.cell_pt1.x;
517         int h = mci.cell_pt2.y - mci.cell_pt1.y;
518         mci.motioncell = cvRect (mci.cell_pt1.x, mci.cell_pt1.y, w, h);
519         m_MotionCells.push_back (mci);
520       }
521     }
522   }
523 }
524
525 void
526 MotionCells::performMotionMaskCoords (motionmaskcoordrect * p_motionmaskcoords,
527     int p_motionmaskcoords_count)
528 {
529   CvPoint upperleft;
530   upperleft.x = 0;
531   upperleft.y = 0;
532   CvPoint lowerright;
533   lowerright.x = 0;
534   lowerright.y = 0;
535   for (int i = 0; i < p_motionmaskcoords_count; i++) {
536     upperleft.x = p_motionmaskcoords[i].upper_left_x;
537     upperleft.y = p_motionmaskcoords[i].upper_left_y;
538     lowerright.x = p_motionmaskcoords[i].lower_right_x;
539     lowerright.y = p_motionmaskcoords[i].lower_right_y;
540     cvRectangle (m_pbwImage, upperleft, lowerright, CV_RGB (0, 0, 0),
541         CV_FILLED);
542   }
543 }
544
545 void
546 MotionCells::performMotionMask (motioncellidx * p_motionmaskcellsidx,
547     int p_motionmaskcells_count)
548 {
549   for (int k = 0; k < p_motionmaskcells_count; k++) {
550     int beginy = p_motionmaskcellsidx[k].lineidx * m_cellheight;
551     int beginx = p_motionmaskcellsidx[k].columnidx * m_cellwidth;
552     int endx =
553         (double) p_motionmaskcellsidx[k].columnidx * m_cellwidth + m_cellwidth;
554     int endy =
555         (double) p_motionmaskcellsidx[k].lineidx * m_cellheight + m_cellheight;
556     for (int i = beginy; i < endy; i++)
557       for (int j = beginx; j < endx; j++) {
558         ((uchar *) (m_pbwImage->imageData + m_pbwImage->widthStep * i))[j] = 0;
559       }
560   }
561 }
562
563 ///BGR if we use only OpenCV
564 //RGB if we use gst+OpenCV
565 void
566 MotionCells::blendImages (IplImage * p_actFrame, IplImage * p_cellsFrame,
567     float p_alpha, float p_beta)
568 {
569
570   int height = p_actFrame->height;
571   int width = p_actFrame->width;
572   int step = p_actFrame->widthStep / sizeof (uchar);
573   int channels = p_actFrame->nChannels;
574   int cellstep = p_cellsFrame->widthStep / sizeof (uchar);
575   uchar *curImageData = (uchar *) p_actFrame->imageData;
576   uchar *cellImageData = (uchar *) p_cellsFrame->imageData;
577
578   for (int i = 0; i < height; i++)
579     for (int j = 0; j < width; j++)
580       for (int k = 0; k < channels; k++)
581         if (cellImageData[i * cellstep + j * channels + k] > 0) {
582           curImageData[i * step + j * channels + k] =
583               round ((double) curImageData[i * step + j * channels +
584                   k] * p_alpha + ((double) cellImageData[i * cellstep +
585                       j * channels + k] * p_beta));
586         }
587 }