blob: 26a3ac1370ab55eb4f5e7010df26056c2a128426 [file] [log] [blame]
# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import matplotlib.pyplot as pyplot
import numpy as np
from optofidelity.util import nputil
from optofidelity.videoproc import Canvas, Shape
from ._detector import Detector
from .events import FingerEvent
_log = logging.getLogger(__name__)
class FingerDetector(Detector):
"""Detects Finger movement events."""
NAME = "finger"
FINGER_PROFILE_HEIGHT = 30
"""Height of area on top of the screen on which to calculate the profile."""
LOW_PASS_KERNEL_SIZE = 3
"""Kernel size of time-series low pass for smoothing finger location."""
MIN_FINGER_WEIGHT = 0.5
def Preprocess(self, calib_frame, debugger):
def log(msg, *params):
_log.debug("%04d: " + msg, calib_frame.frame_index, *params)
# Calculate profile at top edge of the screen
shape = Shape.FromRectangle(calib_frame.screen_space_shape,
bottom=self.FINGER_PROFILE_HEIGHT)
profile = shape.CalculateProfile(calib_frame.screen_space_normalized)
profile = 1 - calib_frame.CompensatePWMProfile(profile)
confidence = np.max(profile)
if confidence < 0.01:
return 0.0, 0.0
profile = nputil.Normalize(profile)
profile[profile < 0.5] = 0
# calculate weighted center location (the brighter the profile pixel is,
# the more it counts to the center location)
location = np.average(range(len(profile)), weights=profile)
if debugger:
debugger.screen_space_canvas.PlotProfile(Canvas.BLUE, profile)
debugger.screen_space_canvas.DrawMask(Canvas.GREEN, shape.contour)
debugger.screen_space_canvas.DrawVLine(Canvas.GREEN, int(location))
log("location=%.2f, confidence=%.2f", location, confidence)
return location, confidence
def GenerateEvents(self, preprocessed_data, debug=False):
if debug:
print "preprocessed_data = ["
for location, confidence in preprocessed_data:
print " (%.4f,%.4f)," % (location, confidence)
print "]"
# Return low-pass filtered finger events
data = np.asarray(preprocessed_data, dtype=np.float)
locations = data[:, 0]
confidences = nputil.NormalizeStates(data[:, 1])
smoothed = nputil.LowPass(locations, self.LOW_PASS_KERNEL_SIZE)
for frame_index in range(len(smoothed)):
if confidences[frame_index] > 0.5:
yield FingerEvent(frame_index, location=locations[frame_index])
if debug:
pyplot.figure()
pyplot.plot(locations)
pyplot.plot(smoothed)
pyplot.figure()
pyplot.plot(locations / np.max(locations))
pyplot.plot(confidences)
pyplot.show()