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