1 /*
2  * GStreamer
3  * Copyright (C) 2011 Robert Jobbagy <jobbagy.robert@gmail.com>
4  * Copyright (C) 2011 - 2018 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 #ifndef MOTIONCELLS_H_
46 #define MOTIONCELLS_H_
47 
48 #include <opencv2/core.hpp>
49 #include <fstream>
50 #include <vector>
51 #include <glib.h>
52 
53 //MotionCells defines
54 #define MC_HEADER 64
55 #define MC_TYPE 1
56 #define MC_VERSION 1
57 #define MC_VERSIONTEXT "MotionCells-1"
58 #define MSGLEN 6
59 #define BUSMSGLEN 20
60 
61 using namespace std;
62 
63 struct MotionCellHeader{
64 	gint32 headersize;
65 	gint32 type;
66 	gint32 version;
67 	gint32 itemsize;
68 	gint32 gridx;
69 	gint32 gridy;
70 	gint64 starttime;
71 	char name[MC_HEADER - 32];
72 };
73 
74 struct MotionCellData{
75 	gint32 timestamp;
76 	char *data;
77 };
78 
79 typedef struct {
80 	int upper_left_x;
81 	int upper_left_y;
82 	int lower_right_x;
83 	int lower_right_y;
84 } motionmaskcoordrect;
85 
86 typedef struct {
87 	int R_channel_value;
88 	int G_channel_value;
89 	int B_channel_value;
90 } cellscolor;
91 
92 typedef struct {
93 	int lineidx;
94 	int columnidx;
95 } motioncellidx;
96 
97 struct Cell
98 {
99   double MotionArea;
100   double CellArea;
101   double MotionPercent;
102   bool hasMotion;
103 };
104 
105 struct MotionCellsIdx
106 {
107   cv::Rect motioncell;
108   //Points for the edges of the rectangle.
109   cv::Point cell_pt1;
110   cv::Point cell_pt2;
111   int lineidx;
112   int colidx;
113 };
114 
115 struct OverlayRegions
116 {
117   cv::Point upperleft;
118   cv::Point lowerright;
119 };
120 
121 class MotionCells
122 {
123 public:
124 
125   MotionCells ();
126   virtual ~ MotionCells ();
127 
128   int performDetectionMotionCells (cv::Mat p_frame, double p_sensitivity,
129       double p_framerate, int p_gridx, int p_gridy, gint64 timestamp_millisec,
130       bool p_isVisble, bool p_useAlpha, int motionmaskcoord_count,
131       motionmaskcoordrect * motionmaskcoords, int motionmaskcells_count,
132       motioncellidx * motionmaskcellsidx, cellscolor motioncellscolor,
133       int motioncells_count, motioncellidx * motioncellsidx, gint64 starttime,
134       char *datafile, bool p_changed_datafile, int p_thickness);
135 
setPrevFrame(cv::Mat p_prevframe)136   void setPrevFrame (cv::Mat p_prevframe)
137   {
138     m_pprevFrame = p_prevframe.clone();
139   }
getMotionCellsIdx()140   char *getMotionCellsIdx ()
141   {
142     return m_motioncellsidxcstr;
143   }
144 
getMotionCellsIdxCount()145   int getMotionCellsIdxCount ()
146   {
147     return m_motioncells_idx_count;
148   }
149 
getChangedDataFile()150   bool getChangedDataFile ()
151   {
152     return m_changed_datafile;
153   }
154 
getDatafileInitFailed()155   char *getDatafileInitFailed ()
156   {
157     return m_initdatafilefailed;
158   }
159 
getDatafileSaveFailed()160   char *getDatafileSaveFailed ()
161   {
162     return m_savedatafilefailed;
163   }
164 
getInitErrorCode()165   int getInitErrorCode ()
166   {
167     return m_initerrorcode;
168   }
169 
getSaveErrorCode()170   int getSaveErrorCode ()
171   {
172     return m_saveerrorcode;
173   }
174 
freeDataFile()175   void freeDataFile ()
176   {
177     if (mc_savefile) {
178       fclose (mc_savefile);
179       mc_savefile = NULL;
180       m_saveInDatafile = false;
181     }
182   }
183 
184 private:
185 
186   double calculateMotionPercentInCell (int p_row, int p_col, double *p_cellarea,
187       double *p_motionarea);
188   void performMotionMaskCoords (motionmaskcoordrect * p_motionmaskcoords,
189       int p_motionmaskcoords_count);
190   void performMotionMask (motioncellidx * p_motionmaskcellsidx,
191       int p_motionmaskcells_count);
192   void calculateMotionPercentInMotionCells (motioncellidx *
193       p_motionmaskcellsidx, int p_motionmaskcells_count = 0);
194   int saveMotionCells (gint64 timestamp_millisec);
195   int initDataFile (char *p_datafile, gint64 starttime);
196   void blendImages (cv::Mat p_actFrame, cv::Mat p_cellsFrame,
197       float p_alpha, float p_beta);
198 
setData(cv::Mat img,int lin,int col,uchar valor)199   void setData (cv::Mat img, int lin, int col, uchar valor)
200   {
201     ((uchar *) (img.data + img.step[0] * lin))[col] = valor;
202   }
203 
getData(cv::Mat img,int lin,int col)204   uchar getData (cv::Mat img, int lin, int col)
205   {
206     return ((uchar *) (img.data + img.step[0] * lin))[col];
207   }
208 
getIsNonZero(cv::Mat img)209   bool getIsNonZero (cv::Mat img)
210   {
211     int lin, col;
212 
213     for (lin = 0; lin < img.size().height; lin++)
214       for (col = 0; col < img.size().width; col++) {
215         if ((((uchar *) (img.data + img.step[0] * lin))[col]) > 0)
216           return true;
217       }
218     return false;
219   }
220 
setMotionCells(int p_frameWidth,int p_frameHeight)221   void setMotionCells (int p_frameWidth, int p_frameHeight)
222   {
223     int i, j;
224 
225     m_cellwidth = (double) p_frameWidth / (double) m_gridx;
226     m_cellheight = (double) p_frameHeight / (double) m_gridy;
227     m_pCells = new Cell *[m_gridy];
228     for (i = 0; i < m_gridy; i++)
229       m_pCells[i] = new Cell[m_gridx];
230 
231     //init cells
232     for (i = 0; i < m_gridy; i++)
233       for (j = 0; j < m_gridx; j++) {
234         m_pCells[i][j].MotionArea = 0;
235         m_pCells[i][j].CellArea = 0;
236         m_pCells[i][j].MotionPercent = 0;
237         m_pCells[i][j].hasMotion = false;
238       }
239   }
240 
241   cv::Mat m_pprevFrame, m_pdifferenceImage, m_pbwImage, m_pcurFrame,
242     transparencyimg;
243   bool m_isVisible, m_changed_datafile, m_useAlpha, m_saveInDatafile;
244   Cell **m_pCells;
245   vector < MotionCellsIdx > m_MotionCells;
246   vector < OverlayRegions > m_OverlayRegions;
247   int m_gridx, m_gridy;
248   double m_cellwidth, m_cellheight;
249   double m_alpha, m_beta;
250   double m_sensitivity;
251   int m_framecnt, m_motioncells_idx_count, m_initerrorcode, m_saveerrorcode;
252   char *m_motioncellsidxcstr, *m_initdatafilefailed, *m_savedatafilefailed;
253   FILE *mc_savefile;
254   MotionCellHeader m_header;
255 
256 };
257 
258 #endif /* MOTIONCELLS_H_ */
259