]> www.vanbest.org Git - motioneye-debian/commitdiff
mask file now uses the dimensions from the actual frame picture
authorCalin Crisan <ccrisan@gmail.com>
Tue, 4 Oct 2016 16:21:43 +0000 (19:21 +0300)
committerCalin Crisan <ccrisan@gmail.com>
Tue, 4 Oct 2016 16:23:10 +0000 (19:23 +0300)
motioneye/config.py
motioneye/handlers.py
motioneye/server.py
motioneye/static/css/main.css
motioneye/static/js/main.js
motioneye/templates/main.html
motioneye/utils.py

index f303736777b3568511970ffc376ad5c21095c2b3..03e5386bddb17ed5286579c8b24c43b10a76ed79 100644 (file)
@@ -874,7 +874,7 @@ def motion_camera_ui_to_dict(ui, old_config=None):
             data['smart_mask_speed'] = 10 - int(ui['smart_mask_slugginess'])
 
         elif ui['mask_type'] == 'editable':
-            data['mask_file'] = utils.build_editable_mask_file(old_config['@id'], data.get('width'), data.get('height'), ui['mask_lines'])
+            data['mask_file'] = utils.build_editable_mask_file(old_config['@id'], ui['mask_lines'], data.get('width'), data.get('height'))
 
     # working schedule
     if ui['working_schedule']:
index 40d51d4154131b10a410b401807ceb6063e8afae..85ea8d09b199994aa501400e609619a5340980cc 100644 (file)
@@ -208,8 +208,7 @@ class MainHandler(BaseHandler):
                 has_streaming_auth=motionctl.has_streaming_auth(),
                 has_new_movie_format_support=motionctl.has_new_movie_format_support(),
                 has_motion=bool(motionctl.find_motion()),
-                mask_width=utils.MASK_WIDTH,
-                mask_default_resolution=utils.MASK_DEFAULT_RESOLUTION)
+                mask_width=utils.MASK_WIDTH)
 
 
 class ConfigHandler(BaseHandler):
index 3b65296d0bc940de852c4508fb3514373a048ac3..8f1aef17c07ab0b36ab34b86ee2f7ff185f90bf0 100644 (file)
@@ -331,7 +331,11 @@ def start_motion():
 
         io_loop.add_timeout(datetime.timedelta(seconds=settings.MOTION_CHECK_INTERVAL), checker)
     
-    motionctl.start()
+    try:
+        motionctl.start()
+    
+    except Exception as e:
+        logging.error(str(e), exc_info=True)
         
     io_loop.add_timeout(datetime.timedelta(seconds=settings.MOTION_CHECK_INTERVAL), checker)
 
index 48034172cb56cdedb32a9ccf2b4a45c50ddce5cf..4d448fa21713b5622fd3cdafee3b9b95839450d0 100644 (file)
@@ -241,7 +241,7 @@ div.hostname {
 div.settings {
     background-color: #313131;
     position: fixed;
-    z-index: 1;
+    z-index: 2;
     top: 50px;
     left: 0px;
     width: 0px;
index c9871a934f815aa123bd1c18f37764b8640bc238..b978106dd3a955eb2817ef4c859d0901025473f1 100644 (file)
@@ -895,27 +895,12 @@ function initUI() {
     /* mask editor buttons */
     $('div#editMaskButton').click(function () {
         var cameraId = $('#cameraSelect').val();
-        var resolution = $('#resolutionSelect').val();
-        if (!cameraId) {
-            return;
+        var img = getCameraFrame(cameraId).find('img.camera')[0];
+        if (!img.naturalWidth || !img.naturalHeight) {
+            return runAlertDialog('Cannot edit the mask without a valid camera image!');
         }
-        
-        if (!resolution) {
-            /*
-             * motion requires the mask file to be the same size as the
-             * captured images; however for netcams we have no means to know in
-             * advance the size of the stream; therefore, for netcams, we impose
-             * here a standard fixed mask size, which WILL NOT WORK for netcam
-             * streams of a different resolution, unless motion is patched accordingly
-             */
-            resolution = maskDefaultResolution; 
-        }
-
-        resolution = resolution.split('x');
-        var width = resolution[0];
-        var height = resolution[1];
-
-        enableMaskEdit(cameraId, width, height);
+
+        enableMaskEdit(cameraId, img.naturalWidth, img.naturalHeight);
     });
     $('div#saveMaskButton').click(function () {
         disableMaskEdit();
@@ -1099,6 +1084,9 @@ function enableMaskEdit(cameraId, width, height) {
         var maskLines = [];
         var bits, line;
         
+        maskLines.push(width);
+        maskLines.push(height);
+
         for (y = 0; y < ny; y++) {
             bits = [];
             for (x = 0; x < nx; x++) { 
@@ -1135,10 +1123,10 @@ function enableMaskEdit(cameraId, width, height) {
                     line |= 1 << (maskWidth - 1 - i);
                 }
             });
+
+            maskLines.push(line);
         }
         
-        maskLines.push(line);
-
         $('#maskLinesEntry').val(maskLines.join(',')).change();
     }
     
@@ -1219,7 +1207,8 @@ function enableMaskEdit(cameraId, width, height) {
     /* use mask lines to initialize the element matrix */
     var line;
     var maskLines = $('#maskLinesEntry').val() ? $('#maskLinesEntry').val().split(',').map(function (v) {return parseInt(v);}) : [];
-    
+    maskLines = maskLines.slice(2);
+
     for (y = 0; y < ny; y++) {
         line = maskLines[y];
         for (x = 0; x < nx; x++) { 
index 924f14b355f05e028577289017273d9f6181b74d..1f180229d12405e2ce3d890ce4e22b9d0c9a2297 100644 (file)
@@ -71,7 +71,6 @@
         var hasNetCamSupport = {% if has_motion %}true{% else %}false{% endif %};
         {% if mask_width %}
         var maskWidth = {{mask_width}};
-        var maskDefaultResolution = '{{mask_default_resolution[0]}}x{{mask_default_resolution[1]}}';
         {% endif %}
     </script>
 {% endblock %}
index fbeb0919a384027ada57429ba64e4c5389a08aaa..d6a7309560053436cdd466d7d7d864bafbbd49a7 100644 (file)
@@ -48,7 +48,6 @@ _SIGNATURE_REGEX = re.compile('[^a-zA-Z0-9/?_.=&{}\[\]":, _-]')
 _SPECIAL_COOKIE_NAMES = {'expires', 'domain', 'path', 'secure', 'httponly'}
 
 MASK_WIDTH = 32
-MASK_DEFAULT_RESOLUTION = (640, 480)
 
 DEV_NULL = open('/dev/null', 'w')
 
@@ -787,13 +786,14 @@ def urlopen(*args, **kwargs):
     return urllib2.urlopen(*args, **kwargs)
 
 
-def build_editable_mask_file(camera_id, width, height, mask_lines):
+def build_editable_mask_file(camera_id, mask_lines, capture_width=None, capture_height=None):
+    width = mask_lines[0]
+    height = mask_lines[1]
+    mask_lines = mask_lines[2:]
+    
     logging.debug('building editable mask for camera with id %s (%sx%s)' %
             (camera_id, width, height))
 
-    width = width or MASK_DEFAULT_RESOLUTION[0]
-    height = height or MASK_DEFAULT_RESOLUTION[1]
-    
     # horizontal rectangles
     nx = MASK_WIDTH # number of rectangles
     if width % nx:
@@ -851,20 +851,54 @@ def build_editable_mask_file(camera_id, width, height, mask_lines):
             dr.rectangle((nx * rw, ny * rh, nx * rw + rx - 1, ny * rh + ry - 1), fill=0)
 
     file_name = os.path.join(settings.CONF_PATH, 'mask_%s.pgm' % camera_id)
-    im.save(file_name, 'ppm')
     
+    # resize the image if necessary
+    if capture_width and capture_height and im.size != (capture_width, capture_height):
+        logging.debug('editable mask needs resizing from %sx%s to %sx%s' %
+                (im.size[0], im.size[1], capture_width, capture_height))
+
+        im = im.resize((capture_width, capture_height))
+
+    im.save(file_name, 'ppm')
+
     return file_name
 
 
-def parse_editable_mask_file(camera_id, width, height):
-    logging.debug('parsing editable mask for camera with id %s (%sx%s)' %
-            (camera_id, width, height))
+def parse_editable_mask_file(camera_id, capture_width=None, capture_height=None):
+    # capture_width and capture_height arguments represent the current size
+    # of the camera image, as it might be different from that of the associated mask;
+    # they can be null (e.g. netcams)
+
+    file_name = os.path.join(settings.CONF_PATH, 'mask_%s.pgm' % camera_id)
+
+    logging.debug('parsing editable mask for camera with id %s: %s' % (camera_id, file_name))
+
+    # read the image file
+    try:
+        im = Image.open(file_name)
+
+    except Exception as e:
+        logging.error('failed to read mask file %s: %s' % (file_name, e))
+
+        # empty mask        
+        return [0] * (MASK_WIDTH * 10)
+
+    if capture_width and capture_height:
+        # resize the image if necessary
+        if im.size != (capture_width, capture_height):
+            logging.debug('editable mask needs resizing from %sx%s to %sx%s' %
+                    (im.size[0], im.size[1], capture_width, capture_height))
 
-    # width and height arguments represent the current size of the camera image,
-    # as it might be different from that of the associated mask
+            im = im.resize((capture_width, capture_height))
+            
+        width, height = capture_width, capture_height
+
+    else:
+        logging.debug('using mask size from file: %sx%s' % (im.size[0], im.size[1]))
 
-    width = width or MASK_DEFAULT_RESOLUTION[0]
-    height = height or MASK_DEFAULT_RESOLUTION[1]
+        width, height = im.size
+
+    pixels = list(im.getdata())
 
     # horizontal rectangles
     nx = MASK_WIDTH # number of rectangles
@@ -878,7 +912,7 @@ def parse_editable_mask_file(camera_id, width, height):
     rw = width / nx # rectangle width
 
     # vertical rectangles
-    ny = mask_height = height * MASK_WIDTH / width # number of rectangles
+    ny = height * MASK_WIDTH / width # number of rectangles
     if height % ny:
         ny -= 1
         ry = height % ny # remainder
@@ -888,29 +922,8 @@ def parse_editable_mask_file(camera_id, width, height):
 
     rh = height / ny # rectangle height
 
-    file_name = os.path.join(settings.CONF_PATH, 'mask_%s.pgm' % camera_id)
-
-    # read the image file
-    try:
-        im = Image.open(file_name)
-
-    except Exception as e:
-        logging.error('failed to read mask file %s: %s' % (file_name, e))
-
-        # empty mask        
-        return [0] * mask_height
-    
-    # resize the image if necessary
-    if im.size != (width, height):
-        logging.debug('editable mask needs resizing from %sx%s to %sx%s' %
-                (im.size[0], im.size[1], width, height))
-
-        im = im.resize((width, height))
-
-    pixels = list(im.getdata())
-
     # parse the image contents and build the mask lines
-    mask_lines = []
+    mask_lines = [width, height]
     for y in xrange(ny):
         bits = []
         for x in xrange(nx):