summaryrefslogtreecommitdiff
path: root/ext/opencv/MotionCells.cpp
diff options
context:
space:
mode:
authorRobert Jobbagy <jobbagy.robert@gmail.com>2011-07-27 18:58:15 +0200
committerStefan Sauer <ensonic@google.com>2011-07-28 10:28:50 +0200
commit4723a5d90ce02cb4d720b1be7ebdf365f81910e4 (patch)
tree7ea506c21a957d8f37f9700aa88424ddef16be83 /ext/opencv/MotionCells.cpp
parent976f4b0bbf8efcd0054fc4c0f9ca74029e85dc69 (diff)
motioncells: new element to detect areas of motion
Diffstat (limited to 'ext/opencv/MotionCells.cpp')
-rw-r--r--ext/opencv/MotionCells.cpp593
1 files changed, 593 insertions, 0 deletions
diff --git a/ext/opencv/MotionCells.cpp b/ext/opencv/MotionCells.cpp
new file mode 100644
index 000000000..2b81b305d
--- /dev/null
+++ b/ext/opencv/MotionCells.cpp
@@ -0,0 +1,593 @@
+/*
+ * GStreamer
+ * Copyright (C) 2011 Robert Jobbagy <jobbagy.robert@gmail.com>
+ * Copyright (C) 2011 Nicola Murino <nicola.murino@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cstdlib>
+#include <errno.h>
+#include <math.h>
+#include <gst/gst.h>
+#include <arpa/inet.h>
+#include "MotionCells.h"
+
+uint64_t ntohl64 (uint64_t val);
+uint64_t htonl64 (uint64_t val);
+
+uint64_t
+ntohl64 (uint64_t val)
+{
+ uint64_t res64;
+ uint32_t low = (uint32_t) (val & 0x00000000FFFFFFFFLL);
+ uint32_t high = (uint32_t) ((val & 0xFFFFFFFF00000000LL) >> 32);
+ low = ntohl (low);
+ high = ntohl (high);
+ res64 = (uint64_t) high + (((uint64_t) low) << 32);
+ return res64;
+}
+
+
+uint64_t
+htonl64 (uint64_t val)
+{
+ uint64_t res64;
+ uint32_t low = (uint32_t) (val & 0x00000000FFFFFFFFLL);
+ uint32_t high = (uint32_t) ((val & 0xFFFFFFFF00000000LL) >> 32);
+ low = htonl (low);
+ high = htonl (high);
+ res64 = (uint64_t) high + (((uint64_t) low) << 32);
+ return res64;
+}
+
+MotionCells::MotionCells ()
+{
+ m_framecnt = 0;
+ m_motioncells_idx_count = 0;
+ m_motioncellsidxcstr = NULL;
+ m_saveInDatafile = false;
+ mc_savefile = NULL;
+ m_pcurFrame = NULL;
+ m_pprevFrame = NULL;
+ transparencyimg = NULL;
+ m_pdifferenceImage = NULL;
+ m_pbwImage = NULL;
+ m_initdatafilefailed = new char[BUSMSGLEN];
+ m_savedatafilefailed = new char[BUSMSGLEN];
+ m_initerrorcode = 0;
+ m_saveerrorcode = 0;
+ m_alpha = 0.5;
+ m_beta = 0.5;
+
+}
+
+MotionCells::~MotionCells ()
+{
+ if (mc_savefile) {
+ fclose (mc_savefile);
+ mc_savefile = NULL;
+ }
+ delete[]m_initdatafilefailed;
+ delete[]m_savedatafilefailed;
+ if (m_motioncellsidxcstr)
+ delete[]m_motioncellsidxcstr;
+ if (m_pcurFrame)
+ cvReleaseImage (&m_pcurFrame);
+ if (m_pprevFrame)
+ cvReleaseImage (&m_pprevFrame);
+ if (transparencyimg)
+ cvReleaseImage (&transparencyimg);
+ if (m_pdifferenceImage)
+ cvReleaseImage (&m_pdifferenceImage);
+ if (m_pbwImage)
+ cvReleaseImage (&m_pbwImage);
+}
+
+int
+MotionCells::performDetectionMotionCells (IplImage * p_frame,
+ double p_sensitivity, double p_framerate, int p_gridx, int p_gridy,
+ gint64 timestamp_millisec, bool p_isVisible, bool p_useAlpha,
+ int motionmaskcoord_count, motionmaskcoordrect * motionmaskcoords,
+ int motionmaskcells_count, motioncellidx * motionmaskcellsidx,
+ cellscolor motioncellscolor, int motioncells_count,
+ motioncellidx * motioncellsidx, gint64 starttime, char *p_datafile,
+ bool p_changed_datafile, int p_thickness)
+{
+
+ int sumframecnt = 0;
+ int ret = 0;
+ p_framerate >= 1 ? p_framerate <= 5 ? sumframecnt = 1
+ : p_framerate <= 10 ? sumframecnt = 2
+ : p_framerate <= 15 ? sumframecnt = 3
+ : p_framerate <= 20 ? sumframecnt = 4
+ : p_framerate <= 25 ? sumframecnt = 5 : sumframecnt = 0 : sumframecnt = 0;
+
+ m_framecnt++;
+ m_changed_datafile = p_changed_datafile;
+ if (m_framecnt >= sumframecnt) {
+ m_useAlpha = p_useAlpha;
+ m_gridx = p_gridx;
+ m_gridy = p_gridy;
+ if (m_changed_datafile) {
+ ret = initDataFile (p_datafile, starttime);
+ if (ret != 0)
+ return ret;
+ }
+
+ m_frameSize = cvGetSize (p_frame);
+ m_frameSize.width /= 2;
+ m_frameSize.height /= 2;
+ setMotionCells (m_frameSize.width, m_frameSize.height);
+ m_sensitivity = 1 - p_sensitivity;
+ m_isVisible = p_isVisible;
+ m_pcurFrame = cvCloneImage (p_frame);
+ IplImage *m_pcurgreyImage = cvCreateImage (m_frameSize, IPL_DEPTH_8U, 1);
+ IplImage *m_pprevgreyImage = cvCreateImage (m_frameSize, IPL_DEPTH_8U, 1);
+ IplImage *m_pgreyImage = cvCreateImage (m_frameSize, IPL_DEPTH_8U, 1);
+ IplImage *m_pcurDown =
+ cvCreateImage (m_frameSize, m_pcurFrame->depth, m_pcurFrame->nChannels);
+ IplImage *m_pprevDown = cvCreateImage (m_frameSize, m_pprevFrame->depth,
+ m_pprevFrame->nChannels);
+ m_pbwImage = cvCreateImage (m_frameSize, IPL_DEPTH_8U, 1);
+ cvPyrDown (m_pprevFrame, m_pprevDown);
+ cvCvtColor (m_pprevDown, m_pprevgreyImage, CV_RGB2GRAY);
+ if (m_pprevFrame)
+ cvReleaseImage (&m_pprevFrame);
+ cvPyrDown (m_pcurFrame, m_pcurDown);
+ cvCvtColor (m_pcurDown, m_pcurgreyImage, CV_RGB2GRAY);
+ m_pdifferenceImage = cvCloneImage (m_pcurgreyImage);
+ //cvSmooth(m_pcurgreyImage, m_pcurgreyImage, CV_GAUSSIAN, 3, 0);//TODO camera noise reduce,something smoothing, and rethink runningavg weights
+
+ //Minus the current gray frame from the 8U moving average.
+ cvAbsDiff (m_pprevgreyImage, m_pcurgreyImage, m_pdifferenceImage);
+
+ //Convert the image to black and white.
+ cvAdaptiveThreshold (m_pdifferenceImage, m_pbwImage, 255,
+ CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, 7);
+
+ // Dilate and erode to get object blobs
+ cvDilate (m_pbwImage, m_pbwImage, NULL, 2);
+ cvErode (m_pbwImage, m_pbwImage, NULL, 2);
+
+ //mask-out the overlay on difference image
+ if (motionmaskcoord_count > 0)
+ performMotionMaskCoords (motionmaskcoords, motionmaskcoord_count);
+ if (motionmaskcells_count > 0)
+ performMotionMask (motionmaskcellsidx, motionmaskcells_count);
+ if (getIsNonZero (m_pbwImage)) { //detect Motion
+ GST_DEBUG ("DETECT MOTION \n");
+ if (m_MotionCells.size () > 0) //it contains previous motioncells what we used when frames dropped
+ m_MotionCells.clear ();
+ if (transparencyimg)
+ cvReleaseImage (&transparencyimg);
+ (motioncells_count > 0) ?
+ calculateMotionPercentInMotionCells (motioncellsidx,
+ motioncells_count)
+ : calculateMotionPercentInMotionCells (motionmaskcellsidx, 0);
+
+ transparencyimg = cvCreateImage (cvGetSize (p_frame), p_frame->depth, 3);
+ cvSetZero (transparencyimg);
+ if (m_motioncellsidxcstr)
+ delete[]m_motioncellsidxcstr;
+ 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
+ m_motioncellsidxcstr = new char[m_motioncells_idx_count];
+ char *tmpstr = new char[MSGLEN];
+ for (int i = 0; i < MSGLEN; i++)
+ tmpstr[i] = ' ';
+ for (unsigned int i = 0; i < m_MotionCells.size (); i++) {
+ CvPoint pt1, pt2;
+ pt1.x = m_MotionCells.at (i).cell_pt1.x * 2;
+ pt1.y = m_MotionCells.at (i).cell_pt1.y * 2;
+ pt2.x = m_MotionCells.at (i).cell_pt2.x * 2;
+ pt2.y = m_MotionCells.at (i).cell_pt2.y * 2;
+ if (m_useAlpha && m_isVisible) {
+ cvRectangle (transparencyimg,
+ pt1,
+ pt2,
+ CV_RGB (motioncellscolor.B_channel_value,
+ motioncellscolor.G_channel_value,
+ motioncellscolor.R_channel_value), CV_FILLED);
+ } else if (m_isVisible) {
+ cvRectangle (p_frame,
+ pt1,
+ pt2,
+ CV_RGB (motioncellscolor.B_channel_value,
+ motioncellscolor.G_channel_value,
+ motioncellscolor.R_channel_value), p_thickness);
+ }
+
+ if (i < m_MotionCells.size () - 1) {
+ snprintf (tmpstr, MSGLEN, "%d:%d,", m_MotionCells.at (i).lineidx,
+ m_MotionCells.at (i).colidx);
+ } else {
+ snprintf (tmpstr, MSGLEN, "%d:%d", m_MotionCells.at (i).lineidx,
+ m_MotionCells.at (i).colidx);
+ }
+ if (i == 0)
+ strncpy (m_motioncellsidxcstr, tmpstr, m_motioncells_idx_count);
+ else
+ strcat (m_motioncellsidxcstr, tmpstr);
+ }
+ if (m_MotionCells.size () == 0)
+ strncpy (m_motioncellsidxcstr, " ", m_motioncells_idx_count);
+
+ if (m_useAlpha && m_isVisible) {
+ if (m_MotionCells.size () > 0)
+ blendImages (p_frame, transparencyimg, m_alpha, m_beta);
+ }
+
+ delete[]tmpstr;
+
+ if (mc_savefile && m_saveInDatafile) {
+ ret = saveMotionCells (timestamp_millisec);
+ if (ret != 0)
+ return ret;
+ }
+ } else {
+ m_motioncells_idx_count = 0;
+ if (m_MotionCells.size () > 0)
+ m_MotionCells.clear ();
+ if (transparencyimg)
+ cvReleaseImage (&transparencyimg);
+ }
+
+ m_pprevFrame = cvCloneImage (m_pcurFrame);
+ m_framecnt = 0;
+ if (m_pcurFrame)
+ cvReleaseImage (&m_pcurFrame);
+ if (m_pdifferenceImage)
+ cvReleaseImage (&m_pdifferenceImage);
+ if (m_pcurgreyImage)
+ cvReleaseImage (&m_pcurgreyImage);
+ if (m_pprevgreyImage)
+ cvReleaseImage (&m_pprevgreyImage);
+ if (m_pgreyImage)
+ cvReleaseImage (&m_pgreyImage);
+ if (m_pbwImage)
+ cvReleaseImage (&m_pbwImage);
+ if (m_pprevDown)
+ cvReleaseImage (&m_pprevDown);
+ if (m_pcurDown)
+ cvReleaseImage (&m_pcurDown);
+ if (m_pCells) {
+ for (int i = 0; i < m_gridy; ++i) {
+ delete[]m_pCells[i];
+ }
+ delete[]m_pCells;
+ }
+
+ if (p_framerate <= 5) {
+ if (m_MotionCells.size () > 0)
+ m_MotionCells.clear ();
+ if (transparencyimg)
+ cvReleaseImage (&transparencyimg);
+ }
+ } else { //we do frame drop
+ m_motioncells_idx_count = 0;
+ ret = -2;
+ for (unsigned int i = 0; i < m_MotionCells.size (); i++) {
+ CvPoint pt1, pt2;
+ pt1.x = m_MotionCells.at (i).cell_pt1.x * 2;
+ pt1.y = m_MotionCells.at (i).cell_pt1.y * 2;
+ pt2.x = m_MotionCells.at (i).cell_pt2.x * 2;
+ pt2.y = m_MotionCells.at (i).cell_pt2.y * 2;
+ if (m_useAlpha && m_isVisible) {
+ cvRectangle (transparencyimg,
+ pt1,
+ pt2,
+ CV_RGB (motioncellscolor.B_channel_value,
+ motioncellscolor.G_channel_value,
+ motioncellscolor.R_channel_value), CV_FILLED);
+ } else if (m_isVisible) {
+ cvRectangle (p_frame,
+ pt1,
+ pt2,
+ CV_RGB (motioncellscolor.B_channel_value,
+ motioncellscolor.G_channel_value,
+ motioncellscolor.R_channel_value), p_thickness);
+ }
+
+ }
+ if (m_useAlpha && m_isVisible) {
+ if (m_MotionCells.size () > 0)
+ blendImages (p_frame, transparencyimg, m_alpha, m_beta);
+ }
+ }
+ return ret;
+}
+
+int
+MotionCells::initDataFile (char *p_datafile, gint64 starttime) //p_date is increased with difference between current and previous buffer ts
+{
+ MotionCellData mcd;
+ if (strncmp (p_datafile, " ", 1)) {
+ mc_savefile = fopen (p_datafile, "w");
+ if (mc_savefile == NULL) {
+ //fprintf(stderr, "%s %d:initDataFile:fopen:%d (%s)\n", __FILE__, __LINE__, errno,
+ //strerror(errno));
+ strncpy (m_initdatafilefailed, strerror (errno), BUSMSGLEN - 1);
+ m_initerrorcode = errno;
+ return 1;
+ } else {
+ m_saveInDatafile = true;
+ }
+ } else
+ mc_savefile = NULL;
+ bzero (&m_header, sizeof (MotionCellHeader));
+ m_header.headersize = htonl (MC_HEADER);
+ m_header.type = htonl (MC_TYPE);
+ m_header.version = htonl (MC_VERSION);
+ //it needs these bytes
+ m_header.itemsize =
+ htonl ((int) ceil (ceil (m_gridx * m_gridy / 8.0) / 4.0) * 4 +
+ sizeof (mcd.timestamp));
+ m_header.gridx = htonl (m_gridx);
+ m_header.gridy = htonl (m_gridy);
+ m_header.starttime = htonl64 (starttime);
+
+ snprintf (m_header.name, sizeof (m_header.name), "%s %dx%d", MC_VERSIONTEXT,
+ ntohl (m_header.gridx), ntohl (m_header.gridy));
+ m_changed_datafile = false;
+ return 0;
+}
+
+int
+MotionCells::saveMotionCells (gint64 timestamp_millisec)
+{
+
+ MotionCellData mc_data;
+ mc_data.timestamp = htonl (timestamp_millisec);
+ mc_data.data = NULL;
+ //There is no datafile
+ if (mc_savefile == NULL)
+ return 0;
+
+ if (ftello (mc_savefile) == 0) {
+ //cerr << "Writing out file header"<< m_header.headersize <<":" << sizeof(MotionCellHeader) << " itemsize:"
+ //<< m_header.itemsize << endl;
+ if (fwrite (&m_header, sizeof (MotionCellHeader), 1, mc_savefile) != 1) {
+ //fprintf(stderr, "%s %d:saveMotionCells:fwrite:%d (%s)\n", __FILE__, __LINE__, errno,
+ //strerror(errno));
+ strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
+ m_saveerrorcode = errno;
+ return -1;
+ }
+ }
+
+ mc_data.data =
+ (char *) calloc (1,
+ ntohl (m_header.itemsize) - sizeof (mc_data.timestamp));
+ if (mc_data.data == NULL) {
+ //fprintf(stderr, "%s %d:saveMotionCells:calloc:%d (%s)\n", __FILE__, __LINE__, errno,
+ //strerror(errno));
+ strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
+ m_saveerrorcode = errno;
+ return -1;
+ }
+
+ for (unsigned int i = 0; i < m_MotionCells.size (); i++) {
+ int bitnum =
+ m_MotionCells.at (i).lineidx * ntohl (m_header.gridx) +
+ m_MotionCells.at (i).colidx;
+ int bytenum = (int) floor (bitnum / 8.0);
+ int shift = bitnum - bytenum * 8;
+ mc_data.data[bytenum] = mc_data.data[bytenum] | (1 << shift);
+ //cerr << "Motion Detected " << "line:" << m_MotionCells.at(i).lineidx << " col:" << m_MotionCells.at(i).colidx;
+ //cerr << " bitnum " << bitnum << " bytenum " << bytenum << " shift " << shift << " value " << (int)mc_data.data[bytenum] << endl;
+ }
+
+ if (fwrite (&mc_data.timestamp, sizeof (mc_data.timestamp), 1,
+ mc_savefile) != 1) {
+ //fprintf(stderr, "%s %d:saveMotionCells:fwrite:%d (%s)\n", __FILE__, __LINE__, errno,
+ //strerror(errno));
+ strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
+ m_saveerrorcode = errno;
+ return -1;
+ }
+
+ if (fwrite (mc_data.data,
+ ntohl (m_header.itemsize) - sizeof (mc_data.timestamp), 1,
+ mc_savefile) != 1) {
+ //fprintf(stderr, "%s %d:saveMotionCells:fwrite:%d (%s)\n", __FILE__, __LINE__, errno,
+ //strerror(errno));
+ strncpy (m_savedatafilefailed, strerror (errno), BUSMSGLEN - 1);
+ m_saveerrorcode = errno;
+ return -1;
+ }
+
+ free (mc_data.data);
+ return 0;
+}
+
+double
+MotionCells::calculateMotionPercentInCell (int p_row, int p_col,
+ double *p_cellarea, double *p_motionarea)
+{
+ double cntpixelsnum = 0;
+ double cntmotionpixelnum = 0;
+
+ int ybegin = floor ((double) p_row * m_cellheight);
+ int yend = floor ((double) (p_row + 1) * m_cellheight);
+ int xbegin = floor ((double) (p_col) * m_cellwidth);
+ int xend = floor ((double) (p_col + 1) * m_cellwidth);
+ int cellw = xend - xbegin;
+ int cellh = yend - ybegin;
+ int cellarea = cellw * cellh;
+ *p_cellarea = cellarea;
+ int thresholdmotionpixelnum = floor ((double) cellarea * m_sensitivity);
+
+ for (int i = ybegin; i < yend; i++) {
+ for (int j = xbegin; j < xend; j++) {
+ cntpixelsnum++;
+ if ((((uchar *) (m_pbwImage->imageData + m_pbwImage->widthStep * i))[j]) >
+ 0) {
+ cntmotionpixelnum++;
+ if (cntmotionpixelnum >= thresholdmotionpixelnum) { //we dont needs calculate anymore
+ *p_motionarea = cntmotionpixelnum;
+ return (cntmotionpixelnum / cntpixelsnum);
+ }
+ }
+ int remainingpixelsnum = cellarea - cntpixelsnum;
+ if ((cntmotionpixelnum + remainingpixelsnum) < thresholdmotionpixelnum) { //moving pixels number will be less than threshold
+ *p_motionarea = 0;
+ return 0;
+ }
+ }
+ }
+
+ return (cntmotionpixelnum / cntpixelsnum);
+}
+
+void
+MotionCells::calculateMotionPercentInMotionCells (motioncellidx *
+ p_motioncellsidx, int p_motioncells_count)
+{
+ if (p_motioncells_count == 0) {
+ for (int i = 0; i < m_gridy; i++) {
+ for (int j = 0; j < m_gridx; j++) {
+ m_pCells[i][j].MotionPercent = calculateMotionPercentInCell (i, j,
+ &m_pCells[i][j].CellArea, &m_pCells[i][j].MotionArea);
+ m_pCells[i][j].hasMotion =
+ m_sensitivity < m_pCells[i][j].MotionPercent ? true : false;
+ if (m_pCells[i][j].hasMotion) {
+ MotionCellsIdx mci;
+ mci.lineidx = i;
+ mci.colidx = j;
+ mci.cell_pt1.x = floor ((double) j * m_cellwidth);
+ mci.cell_pt1.y = floor ((double) i * m_cellheight);
+ mci.cell_pt2.x = floor ((double) (j + 1) * m_cellwidth);
+ mci.cell_pt2.y = floor ((double) (i + 1) * m_cellheight);
+ int w = mci.cell_pt2.x - mci.cell_pt1.x;
+ int h = mci.cell_pt2.y - mci.cell_pt1.y;
+ mci.motioncell = cvRect (mci.cell_pt1.x, mci.cell_pt1.y, w, h);
+ m_MotionCells.push_back (mci);
+ }
+ }
+ }
+ } else {
+ for (int k = 0; k < p_motioncells_count; ++k) {
+
+ int i = p_motioncellsidx[k].lineidx;
+ int j = p_motioncellsidx[k].columnidx;
+ m_pCells[i][j].MotionPercent =
+ calculateMotionPercentInCell (i, j,
+ &m_pCells[i][j].CellArea, &m_pCells[i][j].MotionArea);
+ m_pCells[i][j].hasMotion =
+ m_pCells[i][j].MotionPercent > m_sensitivity ? true : false;
+ if (m_pCells[i][j].hasMotion) {
+ MotionCellsIdx mci;
+ mci.lineidx = p_motioncellsidx[k].lineidx;
+ mci.colidx = p_motioncellsidx[k].columnidx;
+ mci.cell_pt1.x = floor ((double) j * m_cellwidth);
+ mci.cell_pt1.y = floor ((double) i * m_cellheight);
+ mci.cell_pt2.x = floor ((double) (j + 1) * m_cellwidth);
+ mci.cell_pt2.y = floor ((double) (i + 1) * m_cellheight);
+ int w = mci.cell_pt2.x - mci.cell_pt1.x;
+ int h = mci.cell_pt2.y - mci.cell_pt1.y;
+ mci.motioncell = cvRect (mci.cell_pt1.x, mci.cell_pt1.y, w, h);
+ m_MotionCells.push_back (mci);
+ }
+ }
+ }
+}
+
+void
+MotionCells::performMotionMaskCoords (motionmaskcoordrect * p_motionmaskcoords,
+ int p_motionmaskcoords_count)
+{
+ CvPoint upperleft;
+ upperleft.x = 0;
+ upperleft.y = 0;
+ CvPoint lowerright;
+ lowerright.x = 0;
+ lowerright.y = 0;
+ for (int i = 0; i < p_motionmaskcoords_count; i++) {
+ upperleft.x = p_motionmaskcoords[i].upper_left_x;
+ upperleft.y = p_motionmaskcoords[i].upper_left_y;
+ lowerright.x = p_motionmaskcoords[i].lower_right_x;
+ lowerright.y = p_motionmaskcoords[i].lower_right_y;
+ cvRectangle (m_pbwImage, upperleft, lowerright, CV_RGB (0, 0, 0),
+ CV_FILLED);
+ }
+}
+
+void
+MotionCells::performMotionMask (motioncellidx * p_motionmaskcellsidx,
+ int p_motionmaskcells_count)
+{
+ for (int k = 0; k < p_motionmaskcells_count; k++) {
+ int beginy = p_motionmaskcellsidx[k].lineidx * m_cellheight;
+ int beginx = p_motionmaskcellsidx[k].columnidx * m_cellwidth;
+ int endx =
+ (double) p_motionmaskcellsidx[k].columnidx * m_cellwidth + m_cellwidth;
+ int endy =
+ (double) p_motionmaskcellsidx[k].lineidx * m_cellheight + m_cellheight;
+ for (int i = beginy; i < endy; i++)
+ for (int j = beginx; j < endx; j++) {
+ ((uchar *) (m_pbwImage->imageData + m_pbwImage->widthStep * i))[j] = 0;
+ }
+ }
+}
+
+///BGR if we use only OpenCV
+//RGB if we use gst+OpenCV
+void
+MotionCells::blendImages (IplImage * p_actFrame, IplImage * p_cellsFrame,
+ float p_alpha, float p_beta)
+{
+
+ int height = p_actFrame->height;
+ int width = p_actFrame->width;
+ int step = p_actFrame->widthStep / sizeof (uchar);
+ int channels = p_actFrame->nChannels;
+ int cellstep = p_cellsFrame->widthStep / sizeof (uchar);
+ uchar *curImageData = (uchar *) p_actFrame->imageData;
+ uchar *cellImageData = (uchar *) p_cellsFrame->imageData;
+
+ for (int i = 0; i < height; i++)
+ for (int j = 0; j < width; j++)
+ for (int k = 0; k < channels; k++)
+ if (cellImageData[i * cellstep + j * channels + k] > 0) {
+ curImageData[i * step + j * channels + k] =
+ round ((double) curImageData[i * step + j * channels +
+ k] * p_alpha + ((double) cellImageData[i * cellstep +
+ j * channels + k] * p_beta));
+ }
+}