13

How to implement a simple motion detector using the front camera and Android SDK?

An example scenario would be like this: a device is standing on a stand and plays a movie. If a person appears in front of it, without even touching it - it changes the movie.

Yar
  • 4,543
  • 2
  • 35
  • 42
  • 1
    Let me just add that finally I never did it, as my customer resigned of this functionality and I had no time to deal with it on my own. – Yar Sep 16 '14 at 16:52

3 Answers3

23

Here is my open source motion detection app for Android.

https://github.com/phishman3579/android-motion-detection

Justin
  • 4,196
  • 4
  • 24
  • 48
16

Here is a Tutorial on how to take a photo with the camera.

If your take a photo every second, and then scale it down to something like 8x8 pixels, you can easily compare two photos and find out if something has happened, to trigger you action.

The reason why you should scale it down are the following:

  1. It is less error prone to noise introduced by the camera
  2. It will be much faster than doing a comparison of the whole image
mostar
  • 4,723
  • 2
  • 28
  • 45
devsnd
  • 7,382
  • 3
  • 42
  • 50
  • I like your answer. Thanks. Just need to figure out to use the front camera. And, how to scale the image (do an average of colors to create one pixel of the scaled image?). – Yar Mar 19 '12 at 17:21
  • Yes, thats it, just average multiple pixels of the source image. but keep in mind that the average must be calculated by summing up multiple pixels, which means that the numbers might become quite huge. so remember to use a `long` for calculations. also, it might suffice to operate on a black & white image... – devsnd Mar 19 '12 at 18:30
  • The link is not working. Could you update it please? – Noobification Sep 02 '15 at 23:35
  • Up-to-date link to the tutorial: https://newcircle.com/s/post/39/using__the_camera_api?page=3 – mostar Oct 15 '15 at 07:20
2

I solved that taking pictures every n seconds and scaling it to 10*10 pixels and finding the difference between them. Here is the kotlin implementation:

private fun detectMotion(bitmap1: Bitmap, bitmap2: Bitmap) {
    val difference =
        getDifferencePercent(bitmap1.apply { scale(16, 12) }, bitmap2.apply { scale(16, 12) })
    if (difference > 10) { // customize accuracy
        // motion detected
    }
}

private fun getDifferencePercent(img1: Bitmap, img2: Bitmap): Double {
    if (img1.width != img2.width || img1.height != img2.height) {
        val f = "(%d,%d) vs. (%d,%d)".format(img1.width, img1.height, img2.width, img2.height)
        throw IllegalArgumentException("Images must have the same dimensions: $f")
    }
    var diff = 0L
    for (y in 0 until img1.height) {
        for (x in 0 until img1.width) {
            diff += pixelDiff(img1.getPixel(x, y), img2.getPixel(x, y))
        }
    }
    val maxDiff = 3L * 255 * img1.width * img1.height
    return 100.0 * diff / maxDiff
}

private fun pixelDiff(rgb1: Int, rgb2: Int): Int {
    val r1 = (rgb1 shr 16) and 0xff
    val g1 = (rgb1 shr 8) and 0xff
    val b1 = rgb1 and 0xff
    val r2 = (rgb2 shr 16) and 0xff
    val g2 = (rgb2 shr 8) and 0xff
    val b2 = rgb2 and 0xff
    return abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2)
}
Rainmaker
  • 10,294
  • 9
  • 54
  • 89