"detect_match" and "detect_motion" implemented using the OpenCV Python bindings

...instead of listening for messages from the GStreamer elements
stbt-templatematch and stbt-motiondetect.

ADVANTAGES:

* Much simpler implementation (see the commit where we remove the
  GStreamer elements, later in this commit series). In particular the
  communication between the GStreamer element and the python code has
  caused us difficulties; see for example the implementation of
  "process_all_frames" in https://github.com/drothlis/stb-tester/pull/8

* Much more flexible: We'll be able to expose the sequence of frames as
  OpenCV images directly to the user script, for arbitrary image
  processing (for example you might want to detect black screens to
  measure channel change times; this is a trivial image processing
  operation of mask + threshold + count non-zero pixels).

REGRESSIONS IN FUNCTIONALITY:

* The GObject main loop isn't run, so we don't receive GStreamer
  over-/under-run signals, nor GObject timeouts.
* No red/yellow rectangle drawn on the output video.
* stbt-debug debug images aren't saved.

These will be addressed in subsequent commits in this series.

PERFORMANCE:

The script "tests/run-performance-test.sh" prints the frames-per-second
processed by "detect_match" against a video provided by the user (not
committed to the repository). Using a 720p video captured via the
Hauppauge HD PVR, on my dual-core Intel Core i7 MacBook Air this script
reports on average 3.6 frames per second with the python version, versus
3.8 frames per second with the original version (from 20 runs each).
stbt.py: Log intermediate images to disk

This brings back the "stbt run -vv" behaviour that was lost in commit
0f0dc1a6.
stbt._log_image: Scale "matchTemplate" image to visible range

The result of "cv2.matchTemplate" is a matrix with each pixel in the
range [0.0, 1.0]. This change scales the debug image saved to disk
to the grayscale range [0, 255].

Note that "_log_image" reassigns the name "image" to the scaled version,
but this name is local to the function. The scaling isn't done in-place,
so the original image isn't modified (otherwise the
"first_pass_certainty" comparison in "_match_template" would fail).
stbt.get_frame and stbt.save_frame return/operate on OpenCV format

"stbt.get_frame" returns an OpenCV image (i.e. a numpy array) instead of
a GStreamer buffer. The OpenCV image doesn't have any timestamp
information, unlike the GStreamer buffer; but I don't think anyone was
using that timestamp (if you wanted the timestamp you would have been
using "detect_match" or "detect_motion" instead).

"stbt.save_frame" takes an OpenCV image instead of a GStreamer buffer, and
uses the much simpler "cv2.imwrite" to save it to disk.

Note that "stbt.get_frame()" can no longer be used in a boolean context;
stbt-run's "if e.screenshot" would now fail with:

    ValueError: The truth value of an array with more than one element
    is ambiguous. Use a.any() or a.all()
test_get_frame_and_save_frame: Clearer error message

Instead of an obscure error message from the following "stbt-run"
command.

Note that "fail", which is to be used from test cases, can safely use
"exit" because each test case is run inside a sub-shell.
stbt.py: Run GLib main loop continuously, and wait on appsink "new-buffer" signals

...instead of polling appsink's "last-buffer" property.

Now we will monitor pipeline signals & messages like "underrun" all the
time, not just when inside a call to "wait_for_match" (or "detect_match",
"wait_for_motion", etc). So, for example, we will restart the pipeline
when we lose video input (see b6135eca) as soon as we detect video loss,
not just at the next "wait_for_match".

The GLib main loop is now running in a separate thread (not in the main
application thread, which runs the user's script), so "sys.exit" doesn't
work (it only raises a SystemExit exception, which terminates the thread
but isn't propagated to the main application thread). So we use the same
synchronised Queue that we use to communicate new frames to the main
application thread, for also communicating errors (in the form of
Exception objects).
stbt.py: Restart video pipeline as many times as it takes

We restart the source pipeline whenever video signal is lost to work
around the HD PVR behaviour where the device stops delivering video
when it loses input signal momentarily; see b6135eca.

With this commit, instead of giving up after 3 restart attempts, we rely
on the timeout in "Display.frames".

Before commit 78f3b221, video loss *outside* of a "wait_for_match" (or
"detect_match", "wait_for_motion", etc) didn't trigger the
pipeline-restart mechanism nor the exit-after-3-restarts. It was only
when you called "wait_for_match" (etc) that the 3 restarts were
attempted. We have test scripts that restart the system-under-test, and
it takes longer than the 3 restart attempts before the rebooted system
starts delivering video again, so our test scripts looked like this:

    restart_the_system_under_test()
    time.sleep(30)
    stbt.wait_for_match(...)

Since commit 78f3b221, we restart the video pipeline as soon as we
detect that we have lost video. This is desirable behaviour, because it
means that the next "wait_for_match" after a "sleep" (or other
processing) can start consuming video immediately, but the above script
would now exit during the "time.sleep" call. With this current commit,
the script will only exit due to "no video available" when it is inside
"wait_for_match" etc.  Note that you can set your own timeout to
"wait_for_match":

    restart_the_system_under_test()
    stbt.wait_for_match(..., timeout_secs=30)
stbt.py: Cleanup: Rename appsink element from "screenshot" to "appsink"

"Screenshot" is the purpose of the element, but it is potentially
confusing because "screenshot" usually means a single frame once
captured. If you know GStreamer then you know what "appsink" is.
stbt.Display.__init__: Remove unneeded member variables

"self.bus", "self.queue" and "self.mainloop_thread" aren't used outside
of this function.
stbt.detect_motion: Fix invalid argument on some versions of numpy

On travis-ci's Ubuntu 12.04 (?) the test
"test_wait_for_motion_with_mask_reports_motion" was complaining:
"TypeError: <unknown> is not a numpy array".
stbt-record: Update to use new stbt.py

"stbt record" stopped working since ef12d130.

This commit fixes that, and also takes advantage of the same
recover-from-video-loss capability that "stbt run" has (see commit
801d912f). It's also a lot less code!
Remove GStreamer plugin files

All image processing is now done in stbt.py, using the OpenCV python
bindings (see commit 0f0dc1a6).
Cleanup: Split tests/test-stbt-run.sh into test-{match,motion,stbt-py}.sh

"test-stbt-run.sh" was getting quite long (650 lines) and the
motion-related tests weren't all grouped together, so it seemed a good
idea to clean this up.
Remove tests for GStreamer temlatematch and motiondetect elements

The GStreamer elements were removed in commit a35848f2.

Added tests to "test-motion.sh" for functionality that was only covered
in the GStreamer element tests.
tests/known-fail-source.png: Crop to 228px wide

"stbt.gst_to_opencv" doesn't take into account any padding at the end of
each row in the GStreamer buffer. If we assume that each row is aligned to
4 bytes, then the "stbt.py" patch shown below in this comment does work
correctly with the original version of "known-fail-source.png" (231px wide)
but *fails* if I crop the image to 230px wide:

    ValueError: strides is incompatible with shape of requested array
    and size of buffer

Instead of fixing this now, I've just resized the test image
"known-fail-source.png" to a multiple of 4, so that the test
"test_wait_for_match_confirm_methods_produce_different_results" passes.
This problem doesn't affect template images, only the source video
frames taken from GStreamer; so this shouldn't affect real-world stbt
usage, where our input width is always a multiple of 4 (1280, 1080,
etc).

The afore-mentioned patch to stbt.py:

    diff --git a/stbt.py b/stbt.py
    index 8e0ae3d..1a3772f 100644
    --- a/stbt.py
    +++ b/stbt.py
    @@ -14,6 +14,7 @@
     import errno
     import functools
     import inspect
    +import math
     import os
     import Queue
     import re
    @@ -876,10 +877,12 @@

     def gst_to_opencv(gst_buffer):
    +    height = gst_buffer.get_caps().get_structure(0)["height"]
    +    width = gst_buffer.get_caps().get_structure(0)["width"]
    +    channels = 3
         return numpy.ndarray(
    -        (gst_buffer.get_caps().get_structure(0)["height"],
    -         gst_buffer.get_caps().get_structure(0)["width"],
    -         3),
    +        (height, width, channels),
    +        strides=(4 * math.ceil(width / 4.0) * channels, channels, 1),
             buffer=gst_buffer.data,
             dtype=numpy.uint8)
Fake out "stbt.Display.frames" for flaky tests

These tests test a video stream with "half motion", i.e. where each
second frame is identical to the previous frame (A A B B C C D D etc).
This happens a lot in CCTV footage, in cartoons, etc. (see 84a795e8).

Unfortunately the "videorate" GStreamer element used by these tests
interacts badly with the new appsink-based mechanism introduced in
0f0dc1a6. The thread running the handler for the appsink "new-buffer"
signal (this thread populates "stbt.Display.last_buffer") was getting
called in very quick succession with both of the identical frames,
pushing them both onto "last_buffer" before the user code (in a separate
thread) managed to read from "last_buffer". Halving the effective frame
rate just meant that the "new-buffer" thread processed *four* frames for
every frame processed by the user code, etc.

To make these tests robust, I used a fake "stbt.Display.frames"
function. This avoids GStreamer interactions entirely and focuses on
testing the wait_for_motion "consecutive_frames" handling.
Install Python OpenCV bindings on our Travis test runner

It seems I have to explicitly specify python-opencv's dependency on
python-numpy.
README: Update to match ef12d130

This commit is the result of running "make doc" after the docstring
changes in commit ef12d130.
README.rst: Note opencv-python dependency; don't mention GStreamer elements

All image processing is now done in python code in stbt.py (0f0dc1a6),
and we no longer use any custom GStreamer elements (a35848f2).

Our image processing algorithm was always a custom one we developed
ourselves; the original GStreamer templatematch element merely called
the OpenCV "matchTemplate" function. So we no longer have any code
originating from the gstreamer-opencv project.
Travis CI: Install OpenCV 2.4

from this PPA:
https://launchpad.net/~limparissoft/+archive/opencv-ppa

instead of Ubuntu 12.04's default OpenCV version (2.3), which seems to
have an intermittent bug: http://answers.opencv.org/question/15279/

that causes the following test to fail:
test_wait_for_motion_with_mask_does_not_report_motion