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