├── .classpath ├── .gitignore ├── .project ├── AndroidManifest.xml ├── LICENSE ├── README.md ├── create_javadocs.sh ├── default.properties ├── javadocs ├── allclasses-frame.html ├── allclasses-noframe.html ├── com │ └── jwetherell │ │ └── motion_detection │ │ ├── GlobalData.html │ │ ├── MotionDetectionActivity.html │ │ ├── Preferences.html │ │ ├── R.attr.html │ │ ├── R.drawable.html │ │ ├── R.html │ │ ├── R.id.html │ │ ├── R.layout.html │ │ ├── R.string.html │ │ ├── SensorsActivity.html │ │ ├── data │ │ ├── GlobalData.html │ │ ├── Preferences.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── data2 │ │ ├── GlobalData.html │ │ ├── Preferences.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── detection │ │ ├── AggregateLumaMotionDetection.html │ │ ├── Comparer.html │ │ ├── IMotionDetection.html │ │ ├── LumaMotionDetection.html │ │ ├── RgbMotionDetection.html │ │ ├── State.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── image │ │ ├── ImageProcessing.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── preferences │ │ ├── Preferences.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html ├── constant-values.html ├── deprecated-list.html ├── help-doc.html ├── index-all.html ├── index.html ├── overview-frame.html ├── overview-summary.html ├── overview-tree.html ├── package-list ├── resources │ └── inherit.gif └── stylesheet.css ├── project.properties ├── res ├── drawable-hdpi │ └── icon.png ├── drawable-ldpi │ └── icon.png ├── drawable-mdpi │ └── icon.png ├── layout │ └── main.xml └── values │ └── strings.xml └── src └── com └── jwetherell └── motion_detection ├── MotionDetectionActivity.java ├── SensorsActivity.java ├── data ├── GlobalData.java └── Preferences.java ├── detection ├── AggregateLumaMotionDetection.java ├── Comparer.java ├── IMotionDetection.java ├── LumaMotionDetection.java ├── RgbMotionDetection.java └── State.java └── image └── ImageProcessing.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /gen 3 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | AndroidMotionDetection 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | android-motion-detection 2 | ======================== 3 | 4 | Android code to detection motion from by comparing two pictures. 5 | 6 | ## Introduction 7 | 8 | Android code to detection motion from by comparing two pictures. It comes with an Activity that initializes a camera and grabs two pictures and compares them. 9 | 10 | * Created by Justin Wetherell 11 | * For questions use: http://groups.google.com/forum/#!forum/android-motion-detection 12 | * Google: http://code.google.com/p/android-motion-detection 13 | * Github: http://github.com/phishman3579/android-motion-detection 14 | * LinkedIn: http://www.linkedin.com/in/phishman3579 15 | * E-mail: phishman3579@gmail.com 16 | * Twitter: http://twitter.com/phishman3579 17 | 18 | ## Support me with a donation 19 | 20 | Donate to this project 21 | 22 | ## Details 23 | 24 | You essentially have to override an onPreviewFrame(byte[] data, Camera cam) method and convert from the default YUV to RGB: 25 | 26 | int[] rgb = ImageProcessing.decodeYUV420SPtoRGB(data, width, height); 27 | 28 | Create an object which you'll use for motion detection code: 29 | 30 | IMotionDetection detector = new RgbMotionDetection(); 31 | 32 | Call the detect() method passing in the parameters obtained above. 33 | 34 | boolean detected = detector.detect(rgb, width, height) 35 | 36 | If the boolean "detected" variable is true then it has detected motion. 37 | 38 | The RGB detection code is located in RgbMotionDetection.java class. The image processing code is located in ImageProcessing.java static class. The Activity to tie it all together is in MotionDetectionActivity.java. 39 | 40 | I have created a MotionDetection class that detects motion comparing RGB values called RgbMotionDetection.java, a class that detects motion comparing Luminance values called LumaMotionDetection.java, and a class that detects motion comparing avergae Luminance values in regions called AggregateLumaMotionDetection.java. 41 | -------------------------------------------------------------------------------- /create_javadocs.sh: -------------------------------------------------------------------------------- 1 | #1/bin/bash 2 | 3 | javadoc -author -linkoffline http://d.android.com/reference file:/usr/local/android-sdk-linux_86/docs/reference -classpath /usr/local/android-sdk-linux_86/platforms/android-4/android.jar -d javadocs/ -sourcepath `find . -name *.java` 4 | -------------------------------------------------------------------------------- /default.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "build.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-7 12 | -------------------------------------------------------------------------------- /javadocs/allclasses-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | All Classes 7 | 8 | 9 | 10 | 11 |

All Classes

12 |
13 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /javadocs/allclasses-noframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | All Classes 7 | 8 | 9 | 10 | 11 |

All Classes

12 |
13 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/R.attr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | R.attr 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 | 77 | 79 | 81 | 82 |
51 | 52 |
83 | 84 | 85 | 86 |
87 | 88 |

89 | 90 | com.jwetherell.motion_detection 91 |
92 | Class R.attr

93 |
 94 | java.lang.Object
 95 |   extended by com.jwetherell.motion_detection.R.attr
 96 | 
97 |
98 |
Enclosing class:
R
99 |
100 |
101 |
102 |
public static final class R.attr
extends Object
103 | 104 | 105 |

106 |


107 | 108 |

109 | 110 | 111 | 112 | 113 | 114 | 115 | 117 | 118 | 119 | 123 | 124 |
116 | Constructor Summary
R.attr() 120 | 121 |
122 |            
125 |   126 | 127 | 128 | 129 | 130 | 131 | 133 | 134 |
132 | Method Summary
135 |   136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 |
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
144 |   145 |

146 | 147 | 148 | 149 | 150 | 151 | 152 | 154 | 155 |
153 | Constructor Detail
156 | 157 |

158 | R.attr

159 |
160 | public R.attr()
161 |
162 |
163 | 164 |
165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 186 | 189 | 190 | 191 | 192 | 195 | 211 | 212 | 213 | 215 | 217 | 218 |
187 | 188 |
219 | 220 | 221 | 222 |
223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/data/GlobalData.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | GlobalData 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 78 | 79 | 80 |
81 |

com.jwetherell.motion_detection.data

82 |

Class GlobalData

83 |
84 |
85 | 93 |
94 | 105 |
106 |
107 | 141 |
142 |
143 | 173 |
174 |
175 | 176 | 177 |
178 | 179 | 180 | 181 | 182 | 191 |
192 | 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/data/Preferences.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Preferences 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 78 | 79 | 80 |
81 |

com.jwetherell.motion_detection.data

82 |

Class Preferences

83 |
84 |
85 | 93 |
94 | 106 |
107 |
108 | 170 |
171 |
172 | 247 |
248 |
249 | 250 | 251 |
252 | 253 | 254 | 255 | 256 | 265 |
266 | 308 | 309 | 310 | 311 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/data/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection.data 7 | 8 | 9 | 10 | 11 |

com.jwetherell.motion_detection.data

12 |
13 |

Classes

14 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/data/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection.data 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package com.jwetherell.motion_detection.data

66 |
67 |
68 | 94 |
95 | 96 |
97 | 98 | 99 | 100 | 101 | 110 |
111 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/data/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection.data Class Hierarchy 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package com.jwetherell.motion_detection.data

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 81 |
82 | 83 |
84 | 85 | 86 | 87 | 88 | 97 |
98 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/data2/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.jwetherell.motion_detection.data2 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | com.jwetherell.motion_detection.data2 20 | 21 | 22 | 29 | 30 |
23 | Classes  24 | 25 |
26 | GlobalData 27 |
28 | Preferences
31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/data2/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.jwetherell.motion_detection.data2 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |

82 | Package com.jwetherell.motion_detection.data2 83 |

84 | 85 | 86 | 87 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
88 | Class Summary
GlobalDataThis class is used to store global data.
PreferencesThis class is used to store preferences on how to decode images and what to save.
99 |   100 | 101 |

102 |

103 |
104 |
105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 126 | 129 | 130 | 131 | 132 | 135 | 151 | 152 |
127 | 128 |
153 | 154 | 155 | 156 |
157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/data2/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.jwetherell.motion_detection.data2 Class Hierarchy 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |
82 |

83 | Hierarchy For Package com.jwetherell.motion_detection.data2 84 |

85 |
86 |
87 |
Package Hierarchies:
All Packages
88 |
89 |

90 | Class Hierarchy 91 |

92 | 96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 118 | 121 | 122 | 123 | 124 | 127 | 143 | 144 |
119 | 120 |
145 | 146 | 147 | 148 |
149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/detection/IMotionDetection.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IMotionDetection 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 78 | 79 | 80 |
81 |

com.jwetherell.motion_detection.detection

82 |

Interface IMotionDetection

83 |
84 |
85 |
86 | 100 |
101 |
102 | 135 |
136 |
137 | 176 |
177 |
178 | 179 | 180 |
181 | 182 | 183 | 184 | 185 | 194 |
195 | 237 | 238 | 239 | 240 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/detection/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection.detection 7 | 8 | 9 | 10 | 11 |

com.jwetherell.motion_detection.detection

12 |
13 |

Interfaces

14 | 17 |

Classes

18 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/detection/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection.detection 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package com.jwetherell.motion_detection.detection

66 |
67 |
68 | 131 |
132 | 133 |
134 | 135 | 136 | 137 | 138 | 147 |
148 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/detection/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection.detection Class Hierarchy 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package com.jwetherell.motion_detection.detection

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 84 |

Interface Hierarchy

85 | 88 |
89 | 90 |
91 | 92 | 93 | 94 | 95 | 104 |
105 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/image/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection.image 7 | 8 | 9 | 10 | 11 |

com.jwetherell.motion_detection.image

12 |
13 |

Classes

14 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/image/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection.image 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package com.jwetherell.motion_detection.image

66 |
67 |
68 | 87 |
88 | 89 |
90 | 91 | 92 | 93 | 94 | 103 |
104 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/image/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection.image Class Hierarchy 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package com.jwetherell.motion_detection.image

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 80 |
81 | 82 |
83 | 84 | 85 | 86 | 87 | 96 |
97 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection 7 | 8 | 9 | 10 | 11 |

com.jwetherell.motion_detection

12 |
13 |

Classes

14 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package com.jwetherell.motion_detection

66 |
67 |
68 | 87 |
88 | 89 |
90 | 91 | 92 | 93 | 94 | 103 |
104 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.jwetherell.motion_detection Class Hierarchy 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package com.jwetherell.motion_detection

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 84 |
85 | 86 |
87 | 88 | 89 | 90 | 91 | 100 |
101 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/preferences/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.jwetherell.motion_detection.preferences 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | com.jwetherell.motion_detection.preferences 20 | 21 | 22 | 27 | 28 |
23 | Classes  24 | 25 |
26 | Preferences
29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/preferences/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.jwetherell.motion_detection.preferences 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |

82 | Package com.jwetherell.motion_detection.preferences 83 |

84 | 85 | 86 | 87 | 89 | 90 | 91 | 92 | 93 | 94 |
88 | Class Summary
PreferencesThis class is used to store preferences on how to decode images and what to save.
95 |   96 | 97 |

98 |

99 |
100 |
101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 122 | 125 | 126 | 127 | 128 | 131 | 147 | 148 |
123 | 124 |
149 | 150 | 151 | 152 |
153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /javadocs/com/jwetherell/motion_detection/preferences/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.jwetherell.motion_detection.preferences Class Hierarchy 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |
82 |

83 | Hierarchy For Package com.jwetherell.motion_detection.preferences 84 |

85 |
86 |
87 |
Package Hierarchies:
All Packages
88 |
89 |

90 | Class Hierarchy 91 |

92 | 96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 118 | 121 | 122 | 123 | 124 | 127 | 143 | 144 |
119 | 120 |
145 | 146 | 147 | 148 |
149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /javadocs/constant-values.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Constant Field Values 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Constant Field Values

66 |

Contents

67 | 70 |
71 |
72 | 73 | 74 |

com.jwetherell.*

75 | 138 |
139 | 140 |
141 | 142 | 143 | 144 | 145 | 154 |
155 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /javadocs/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Deprecated List 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Deprecated API

66 |

Contents

67 |
68 | 69 |
70 | 71 | 72 | 73 | 74 | 83 |
84 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /javadocs/help-doc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | API Help 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

How This API Document Is Organized

66 |

This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.

67 |
68 |
69 | 164 | This help file applies to API documentation generated using the standard doclet.
165 | 166 |
167 | 168 | 169 | 170 | 171 | 180 |
181 | 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /javadocs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Generated Documentation (Untitled) 7 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | <noscript> 61 | <div>JavaScript is disabled on your browser.</div> 62 | </noscript> 63 | <h2>Frame Alert</h2> 64 | <p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.</p> 65 | <br>Link to<a href="overview-summary.html">Non-frame version.</a> 66 | 67 | 68 | -------------------------------------------------------------------------------- /javadocs/overview-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview List 7 | 8 | 9 | 10 | 11 |
All Classes
12 |
13 |

Packages

14 | 20 |
21 |

 

22 | 23 | 24 | -------------------------------------------------------------------------------- /javadocs/overview-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
Packages 
PackageDescription
com.jwetherell.motion_detection 
com.jwetherell.motion_detection.data 
com.jwetherell.motion_detection.detection 
com.jwetherell.motion_detection.image 
90 |
91 | 92 |
93 | 94 | 95 | 96 | 97 | 106 |
107 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /javadocs/overview-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Class Hierarchy 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For All Packages

66 | Package Hierarchies: 67 | 73 |
74 |
75 |

Class Hierarchy

76 | 95 |

Interface Hierarchy

96 | 99 |
100 | 101 |
102 | 103 | 104 | 105 | 106 | 115 |
116 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /javadocs/package-list: -------------------------------------------------------------------------------- 1 | com.jwetherell.motion_detection 2 | com.jwetherell.motion_detection.data 3 | com.jwetherell.motion_detection.detection 4 | com.jwetherell.motion_detection.image 5 | -------------------------------------------------------------------------------- /javadocs/resources/inherit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phishman3579/android-motion-detection/07b246ac742f01a649163c27b79099bd7118d20b/javadocs/resources/inherit.gif -------------------------------------------------------------------------------- /javadocs/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* Javadoc style sheet */ 2 | 3 | /* Define colors, fonts and other style attributes here to override the defaults */ 4 | 5 | /* Page background color */ 6 | body { background-color: #FFFFFF; color:#000000 } 7 | 8 | /* Headings */ 9 | h1 { font-size: 145% } 10 | 11 | /* Table colors */ 12 | .TableHeadingColor { background: #CCCCFF; color:#000000 } /* Dark mauve */ 13 | .TableSubHeadingColor { background: #EEEEFF; color:#000000 } /* Light mauve */ 14 | .TableRowColor { background: #FFFFFF; color:#000000 } /* White */ 15 | 16 | /* Font used in left-hand frame lists */ 17 | .FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 } 18 | .FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } 19 | .FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } 20 | 21 | /* Navigation bar fonts and colors */ 22 | .NavBarCell1 { background-color:#EEEEFF; color:#000000} /* Light mauve */ 23 | .NavBarCell1Rev { background-color:#00008B; color:#FFFFFF} /* Dark Blue */ 24 | .NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;color:#000000;} 25 | .NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;color:#FFFFFF;} 26 | 27 | .NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} 28 | .NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} 29 | 30 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-7 12 | -------------------------------------------------------------------------------- /res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phishman3579/android-motion-detection/07b246ac742f01a649163c27b79099bd7118d20b/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /res/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phishman3579/android-motion-detection/07b246ac742f01a649163c27b79099bd7118d20b/res/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phishman3579/android-motion-detection/07b246ac742f01a649163c27b79099bd7118d20b/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | MotionDetection 4 | 5 | -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/MotionDetectionActivity.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.util.concurrent.atomic.AtomicBoolean; 6 | 7 | import com.jwetherell.motion_detection.data.GlobalData; 8 | import com.jwetherell.motion_detection.data.Preferences; 9 | import com.jwetherell.motion_detection.detection.AggregateLumaMotionDetection; 10 | import com.jwetherell.motion_detection.detection.IMotionDetection; 11 | import com.jwetherell.motion_detection.detection.LumaMotionDetection; 12 | import com.jwetherell.motion_detection.detection.RgbMotionDetection; 13 | import com.jwetherell.motion_detection.image.ImageProcessing; 14 | 15 | import android.content.res.Configuration; 16 | import android.graphics.Bitmap; 17 | import android.hardware.Camera; 18 | import android.hardware.Camera.PreviewCallback; 19 | import android.os.AsyncTask; 20 | import android.os.Bundle; 21 | import android.os.Environment; 22 | import android.os.Looper; 23 | import android.util.Log; 24 | import android.view.SurfaceHolder; 25 | import android.view.SurfaceView; 26 | 27 | 28 | /** 29 | * This class extends Activity to handle a picture preview, process the frame 30 | * for motion, and then save the file to the SD card. 31 | * 32 | * @author Justin Wetherell 33 | */ 34 | public class MotionDetectionActivity extends SensorsActivity { 35 | 36 | private static final String TAG = "MotionDetectionActivity"; 37 | 38 | private static SurfaceView preview = null; 39 | private static SurfaceHolder previewHolder = null; 40 | private static Camera camera = null; 41 | private static boolean inPreview = false; 42 | private static long mReferenceTime = 0; 43 | private static IMotionDetection detector = null; 44 | 45 | private static volatile AtomicBoolean processing = new AtomicBoolean(false); 46 | 47 | /** 48 | * {@inheritDoc} 49 | */ 50 | @Override 51 | public void onCreate(Bundle savedInstanceState) { 52 | super.onCreate(savedInstanceState); 53 | setContentView(R.layout.main); 54 | 55 | preview = (SurfaceView) findViewById(R.id.preview); 56 | previewHolder = preview.getHolder(); 57 | previewHolder.addCallback(surfaceCallback); 58 | previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 59 | 60 | if (Preferences.USE_RGB) { 61 | detector = new RgbMotionDetection(); 62 | } else if (Preferences.USE_LUMA) { 63 | detector = new LumaMotionDetection(); 64 | } else { 65 | // Using State based (aggregate map) 66 | detector = new AggregateLumaMotionDetection(); 67 | } 68 | } 69 | 70 | /** 71 | * {@inheritDoc} 72 | */ 73 | @Override 74 | public void onConfigurationChanged(Configuration newConfig) { 75 | super.onConfigurationChanged(newConfig); 76 | } 77 | 78 | /** 79 | * {@inheritDoc} 80 | */ 81 | @Override 82 | public void onPause() { 83 | super.onPause(); 84 | 85 | camera.setPreviewCallback(null); 86 | if (inPreview) camera.stopPreview(); 87 | inPreview = false; 88 | camera.release(); 89 | camera = null; 90 | } 91 | 92 | /** 93 | * {@inheritDoc} 94 | */ 95 | @Override 96 | public void onResume() { 97 | super.onResume(); 98 | 99 | camera = Camera.open(); 100 | } 101 | 102 | private PreviewCallback previewCallback = new PreviewCallback() { 103 | 104 | /** 105 | * {@inheritDoc} 106 | */ 107 | @Override 108 | public void onPreviewFrame(byte[] data, Camera cam) { 109 | if (data == null) return; 110 | Camera.Size size = cam.getParameters().getPreviewSize(); 111 | if (size == null) return; 112 | 113 | if (!GlobalData.isPhoneInMotion()) { 114 | DetectionThread thread = new DetectionThread(data, size.width, size.height); 115 | thread.start(); 116 | } 117 | } 118 | }; 119 | 120 | private SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() { 121 | 122 | /** 123 | * {@inheritDoc} 124 | */ 125 | @Override 126 | public void surfaceCreated(SurfaceHolder holder) { 127 | try { 128 | camera.setPreviewDisplay(previewHolder); 129 | camera.setPreviewCallback(previewCallback); 130 | } catch (Throwable t) { 131 | Log.e("PreviewDemo-surfaceCallback", "Exception in setPreviewDisplay()", t); 132 | } 133 | } 134 | 135 | /** 136 | * {@inheritDoc} 137 | */ 138 | @Override 139 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 140 | Camera.Parameters parameters = camera.getParameters(); 141 | Camera.Size size = getBestPreviewSize(width, height, parameters); 142 | if (size != null) { 143 | parameters.setPreviewSize(size.width, size.height); 144 | Log.d(TAG, "Using width=" + size.width + " height=" + size.height); 145 | } 146 | camera.setParameters(parameters); 147 | camera.startPreview(); 148 | inPreview = true; 149 | } 150 | 151 | /** 152 | * {@inheritDoc} 153 | */ 154 | @Override 155 | public void surfaceDestroyed(SurfaceHolder holder) { 156 | // Ignore 157 | } 158 | }; 159 | 160 | private static Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) { 161 | Camera.Size result = null; 162 | 163 | for (Camera.Size size : parameters.getSupportedPreviewSizes()) { 164 | if (size.width <= width && size.height <= height) { 165 | if (result == null) { 166 | result = size; 167 | } else { 168 | int resultArea = result.width * result.height; 169 | int newArea = size.width * size.height; 170 | 171 | if (newArea > resultArea) result = size; 172 | } 173 | } 174 | } 175 | 176 | return result; 177 | } 178 | 179 | private static final class DetectionThread extends Thread { 180 | 181 | private byte[] data; 182 | private int width; 183 | private int height; 184 | 185 | public DetectionThread(byte[] data, int width, int height) { 186 | this.data = data; 187 | this.width = width; 188 | this.height = height; 189 | } 190 | 191 | /** 192 | * {@inheritDoc} 193 | */ 194 | @Override 195 | public void run() { 196 | if (!processing.compareAndSet(false, true)) return; 197 | 198 | // Log.d(TAG, "BEGIN PROCESSING..."); 199 | try { 200 | // Previous frame 201 | int[] pre = null; 202 | if (Preferences.SAVE_PREVIOUS) pre = detector.getPrevious(); 203 | 204 | // Current frame (with changes) 205 | // long bConversion = System.currentTimeMillis(); 206 | int[] img = null; 207 | if (Preferences.USE_RGB) { 208 | img = ImageProcessing.decodeYUV420SPtoRGB(data, width, height); 209 | } else { 210 | img = ImageProcessing.decodeYUV420SPtoLuma(data, width, height); 211 | } 212 | // long aConversion = System.currentTimeMillis(); 213 | // Log.d(TAG, "Converstion="+(aConversion-bConversion)); 214 | 215 | // Current frame (without changes) 216 | int[] org = null; 217 | if (Preferences.SAVE_ORIGINAL && img != null) org = img.clone(); 218 | 219 | if (img != null && detector.detect(img, width, height)) { 220 | // The delay is necessary to avoid taking a picture while in 221 | // the 222 | // middle of taking another. This problem can causes some 223 | // phones 224 | // to reboot. 225 | long now = System.currentTimeMillis(); 226 | if (now > (mReferenceTime + Preferences.PICTURE_DELAY)) { 227 | mReferenceTime = now; 228 | 229 | Bitmap previous = null; 230 | if (Preferences.SAVE_PREVIOUS && pre != null) { 231 | if (Preferences.USE_RGB) previous = ImageProcessing.rgbToBitmap(pre, width, height); 232 | else previous = ImageProcessing.lumaToGreyscale(pre, width, height); 233 | } 234 | 235 | Bitmap original = null; 236 | if (Preferences.SAVE_ORIGINAL && org != null) { 237 | if (Preferences.USE_RGB) original = ImageProcessing.rgbToBitmap(org, width, height); 238 | else original = ImageProcessing.lumaToGreyscale(org, width, height); 239 | } 240 | 241 | Bitmap bitmap = null; 242 | if (Preferences.SAVE_CHANGES) { 243 | if (Preferences.USE_RGB) bitmap = ImageProcessing.rgbToBitmap(img, width, height); 244 | else bitmap = ImageProcessing.lumaToGreyscale(img, width, height); 245 | } 246 | 247 | Log.i(TAG, "Saving.. previous=" + previous + " original=" + original + " bitmap=" + bitmap); 248 | Looper.prepare(); 249 | new SavePhotoTask().execute(previous, original, bitmap); 250 | } else { 251 | Log.i(TAG, "Not taking picture because not enough time has passed since the creation of the Surface"); 252 | } 253 | } 254 | } catch (Exception e) { 255 | e.printStackTrace(); 256 | } finally { 257 | processing.set(false); 258 | } 259 | // Log.d(TAG, "END PROCESSING..."); 260 | 261 | processing.set(false); 262 | } 263 | }; 264 | 265 | private static final class SavePhotoTask extends AsyncTask { 266 | 267 | /** 268 | * {@inheritDoc} 269 | */ 270 | @Override 271 | protected Integer doInBackground(Bitmap... data) { 272 | for (int i = 0; i < data.length; i++) { 273 | Bitmap bitmap = data[i]; 274 | String name = String.valueOf(System.currentTimeMillis()); 275 | if (bitmap != null) save(name, bitmap); 276 | } 277 | return 1; 278 | } 279 | 280 | private void save(String name, Bitmap bitmap) { 281 | File photo = new File(Environment.getExternalStorageDirectory(), name + ".jpg"); 282 | if (photo.exists()) photo.delete(); 283 | 284 | try { 285 | FileOutputStream fos = new FileOutputStream(photo.getPath()); 286 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); 287 | fos.close(); 288 | } catch (java.io.IOException e) { 289 | Log.e("PictureDemo", "Exception in photoCallback", e); 290 | } 291 | } 292 | } 293 | } -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/SensorsActivity.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.atomic.AtomicBoolean; 5 | 6 | import com.jwetherell.motion_detection.data.GlobalData; 7 | 8 | import android.app.Activity; 9 | import android.hardware.Sensor; 10 | import android.hardware.SensorEvent; 11 | import android.hardware.SensorEventListener; 12 | import android.hardware.SensorManager; 13 | import android.os.Bundle; 14 | import android.util.Log; 15 | 16 | 17 | /** 18 | * This class extends Activity and processes sensor data and location data. It 19 | * is used to detect when the phone is in motion, so we do not try to detect 20 | * motion. 21 | * 22 | * @author Justin Wetherell 23 | */ 24 | public class SensorsActivity extends Activity implements SensorEventListener { 25 | 26 | private static final String TAG = "SensorsActivity"; 27 | private static final AtomicBoolean computing = new AtomicBoolean(false); 28 | 29 | private static final float grav[] = new float[3]; // Gravity (a.k.a 30 | // accelerometer data) 31 | private static final float mag[] = new float[3]; // Magnetic 32 | 33 | private static final float gravThreshold = 0.5f; 34 | private static final float magThreshold = 1.0f; 35 | 36 | private static SensorManager sensorMgr = null; 37 | private static List sensors = null; 38 | private static Sensor sensorGrav = null; 39 | private static Sensor sensorMag = null; 40 | 41 | private static float prevGrav = 0.0f; 42 | private static float prevMag = 0.0f; 43 | 44 | /** 45 | * {@inheritDoc} 46 | */ 47 | @Override 48 | public void onCreate(Bundle savedInstanceState) { 49 | super.onCreate(savedInstanceState); 50 | } 51 | 52 | /** 53 | * {@inheritDoc} 54 | */ 55 | @Override 56 | public void onDestroy() { 57 | super.onDestroy(); 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | */ 63 | @Override 64 | public void onStart() { 65 | super.onStart(); 66 | 67 | try { 68 | sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE); 69 | 70 | sensors = sensorMgr.getSensorList(Sensor.TYPE_ACCELEROMETER); 71 | if (sensors.size() > 0) sensorGrav = sensors.get(0); 72 | 73 | sensors = sensorMgr.getSensorList(Sensor.TYPE_MAGNETIC_FIELD); 74 | if (sensors.size() > 0) sensorMag = sensors.get(0); 75 | 76 | sensorMgr.registerListener(this, sensorGrav, SensorManager.SENSOR_DELAY_NORMAL); 77 | sensorMgr.registerListener(this, sensorMag, SensorManager.SENSOR_DELAY_NORMAL); 78 | } catch (Exception ex1) { 79 | try { 80 | if (sensorMgr != null) { 81 | sensorMgr.unregisterListener(this, sensorGrav); 82 | sensorMgr.unregisterListener(this, sensorMag); 83 | sensorMgr = null; 84 | } 85 | } catch (Exception ex2) { 86 | ex2.printStackTrace(); 87 | } 88 | } 89 | } 90 | 91 | /** 92 | * {@inheritDoc} 93 | */ 94 | @Override 95 | public void onStop() { 96 | super.onStop(); 97 | 98 | try { 99 | try { 100 | sensorMgr.unregisterListener(this, sensorGrav); 101 | } catch (Exception ex) { 102 | ex.printStackTrace(); 103 | } 104 | try { 105 | sensorMgr.unregisterListener(this, sensorMag); 106 | } catch (Exception ex) { 107 | ex.printStackTrace(); 108 | } 109 | sensorMgr = null; 110 | } catch (Exception ex) { 111 | ex.printStackTrace(); 112 | } 113 | } 114 | 115 | /** 116 | * {@inheritDoc} 117 | */ 118 | @Override 119 | public void onSensorChanged(SensorEvent evt) { 120 | if (!computing.compareAndSet(false, true)) return; 121 | 122 | if (evt.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 123 | grav[0] = evt.values[0]; 124 | grav[1] = evt.values[1]; 125 | grav[2] = evt.values[2]; 126 | } else if (evt.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { 127 | mag[0] = evt.values[0]; 128 | mag[1] = evt.values[1]; 129 | mag[2] = evt.values[2]; 130 | } 131 | 132 | float gravity = grav[0] + grav[1] + grav[2]; 133 | float magnetic = mag[0] + mag[1] + mag[2]; 134 | 135 | float gravDiff = Math.abs(gravity - prevGrav); 136 | float magDiff = Math.abs(magnetic - prevMag); 137 | // Log.i(TAG, "gravDiff="+gravDiff+" magDiff="+magDiff); 138 | 139 | if ((Float.compare(prevGrav, 0.0f) != 0 && Float.compare(prevMag, 0.0f) != 0) && (gravDiff > gravThreshold || magDiff > magThreshold)) { 140 | GlobalData.setPhoneInMotion(true); 141 | } else { 142 | GlobalData.setPhoneInMotion(false); 143 | } 144 | 145 | prevGrav = gravity; 146 | prevMag = magnetic; 147 | 148 | computing.set(false); 149 | } 150 | 151 | /** 152 | * {@inheritDoc} 153 | */ 154 | @Override 155 | public void onAccuracyChanged(Sensor sensor, int accuracy) { 156 | if (sensor == null) throw new NullPointerException(); 157 | 158 | if (sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD && accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) { 159 | Log.e(TAG, "Compass data unreliable"); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/data/GlobalData.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection.data; 2 | 3 | import java.util.concurrent.atomic.AtomicBoolean; 4 | 5 | 6 | /** 7 | * This class is used to store global data. 8 | * 9 | * @author Justin Wetherell 10 | */ 11 | public abstract class GlobalData { 12 | 13 | private GlobalData() { 14 | }; 15 | 16 | private static final AtomicBoolean phoneInMotion = new AtomicBoolean(false); 17 | 18 | public static boolean isPhoneInMotion() { 19 | return phoneInMotion.get(); 20 | } 21 | 22 | public static void setPhoneInMotion(boolean bool) { 23 | phoneInMotion.set(bool); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/data/Preferences.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection.data; 2 | 3 | /** 4 | * This class is used to store preferences on how to decode images and what to 5 | * save. 6 | * 7 | * @author Justin Wetherell 8 | */ 9 | public abstract class Preferences { 10 | 11 | private Preferences() { 12 | } 13 | 14 | // Which motion detection to use 15 | public static boolean USE_RGB = true; 16 | public static boolean USE_LUMA = false; 17 | public static boolean USE_STATE = false; 18 | 19 | // Which photos to save 20 | public static boolean SAVE_PREVIOUS = false; 21 | public static boolean SAVE_ORIGINAL = true; 22 | public static boolean SAVE_CHANGES = true; 23 | 24 | // Time between saving photos 25 | public static int PICTURE_DELAY = 10000; 26 | } 27 | -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/detection/AggregateLumaMotionDetection.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection.detection; 2 | 3 | //import android.util.Log; 4 | 5 | /** 6 | * This class is used to process integer arrays containing luma data and detects 7 | * motion using an aggregate map. 8 | * 9 | * @author Justin Wetherell 10 | */ 11 | public class AggregateLumaMotionDetection implements IMotionDetection { 12 | 13 | // private static final String TAG = "AggregateLumaMotionDetection"; 14 | 15 | // Specific settings 16 | private static final int mLeniency = 10; // Difference of aggregate map of 17 | // luma values 18 | private static final int mDebugMode = 2; // State based debug 19 | private static final int mXBoxes = 10; // State based debug 20 | private static final int mYBoxes = 10; // State based debug 21 | 22 | private static int[] mPrevious = null; 23 | private static int mPreviousWidth; 24 | private static int mPreviousHeight; 25 | private static State mPreviousState = null; 26 | 27 | /** 28 | * {@inheritDoc} 29 | */ 30 | @Override 31 | public int[] getPrevious() { 32 | return ((mPrevious != null) ? mPrevious.clone() : null); 33 | } 34 | 35 | protected static boolean isDifferent(int[] first, int width, int height) { 36 | if (first == null) throw new NullPointerException(); 37 | 38 | if (mPrevious == null) return false; 39 | if (first.length != mPrevious.length) return true; 40 | if (mPreviousWidth != width || mPreviousHeight != height) return true; 41 | 42 | if (mPreviousState == null) { 43 | mPreviousState = new State(mPrevious, mPreviousWidth, mPreviousHeight); 44 | return false; 45 | } 46 | 47 | State state = new State(first, width, height); 48 | Comparer comparer = new Comparer(state, mPreviousState, mXBoxes, mYBoxes, mLeniency, mDebugMode); 49 | 50 | boolean different = comparer.isDifferent(); 51 | // String output = "isDifferent="+different; 52 | if (different) { 53 | // Log.e(TAG, output); 54 | comparer.paintDifferences(first); 55 | // } else { 56 | // Log.d(TAG, output); 57 | } 58 | 59 | mPreviousState = state; 60 | 61 | return different; 62 | } 63 | 64 | /** 65 | * Detect motion using aggregate luma values. {@inheritDoc} 66 | */ 67 | @Override 68 | public boolean detect(int[] luma, int width, int height) { 69 | if (luma == null) throw new NullPointerException(); 70 | 71 | int[] original = luma.clone(); 72 | 73 | // Create the "mPrevious" picture, the one that will be used to check 74 | // the next frame against. 75 | if (mPrevious == null) { 76 | mPrevious = original; 77 | mPreviousWidth = width; 78 | mPreviousHeight = height; 79 | // Log.i(TAG, "Creating background image"); 80 | } 81 | 82 | // long bDetection = System.currentTimeMillis(); 83 | boolean motionDetected = isDifferent(luma, width, height); 84 | // long aDetection = System.currentTimeMillis(); 85 | // Log.d(TAG, "Detection "+(aDetection-bDetection)); 86 | 87 | // Replace the current image with the previous. 88 | mPrevious = original; 89 | mPreviousWidth = width; 90 | mPreviousHeight = height; 91 | 92 | return motionDetected; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/detection/Comparer.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection.detection; 2 | 3 | import android.graphics.Color; 4 | 5 | 6 | /** 7 | * This class is adapted from the web site below. It is used to compare two 8 | * State objects. 9 | * http://mindmeat.blogspot.com/2008/11/java-image-comparison.html 10 | * 11 | * @author Pat Cullen 12 | * @author Justin Wetherell 13 | */ 14 | public class Comparer { 15 | 16 | private State state1 = null; 17 | private State state2 = null; 18 | private int xBoxes; 19 | private int yBoxes; 20 | private int xPixelsPerBox; 21 | private int yPixelsPerBox; 22 | private int xLeftOver; 23 | private int yLeftOver; 24 | private int rowWidthInPix; 25 | private int colWidthInPix; 26 | private int leniency; 27 | private int debugMode; // 1: textual indication of change, 2: difference of 28 | // factors 29 | 30 | private int[][] variance = null; 31 | private boolean different = false; 32 | 33 | public Comparer(State s1, State s2, int xBoxes, int yBoxes, int leniency, int debug) { 34 | this.state1 = s1; 35 | this.state2 = s2; 36 | 37 | this.xBoxes = xBoxes; 38 | if (this.xBoxes > s1.getWidth()) this.xBoxes = s1.getWidth(); 39 | 40 | this.yBoxes = yBoxes; 41 | if (this.yBoxes > s1.getHeight()) this.yBoxes = s1.getHeight(); 42 | 43 | this.leniency = leniency; 44 | this.debugMode = 0; 45 | 46 | // how many points per box 47 | this.xPixelsPerBox = (int) (Math.floor(s1.getWidth() / this.xBoxes)); 48 | if (xPixelsPerBox <= 0) xPixelsPerBox = 1; 49 | this.yPixelsPerBox = (int) (Math.floor(s1.getHeight() / this.yBoxes)); 50 | if (yPixelsPerBox <= 0) yPixelsPerBox = 1; 51 | 52 | this.xLeftOver = s1.getWidth() - (this.xBoxes * this.xPixelsPerBox); 53 | if (xLeftOver > 0) this.xBoxes++; 54 | yLeftOver = s1.getHeight() - (this.yBoxes * this.yPixelsPerBox); 55 | if (yLeftOver > 0) this.yBoxes++; 56 | 57 | this.rowWidthInPix = (this.xBoxes * xPixelsPerBox) - (xPixelsPerBox - xLeftOver); 58 | this.colWidthInPix = this.xPixelsPerBox; 59 | 60 | this.debugMode = debug; 61 | 62 | this.different = isDifferent(this.state1, this.state2); 63 | } 64 | 65 | /** 66 | * Compare two images and populate the variance variable 67 | * 68 | * @param s1 69 | * State for image one. 70 | * @param s2 71 | * State for image two. 72 | * @return True is the two images are different. 73 | * @throws NullPointerException 74 | * if s1 or s2 is NULL. 75 | */ 76 | public boolean isDifferent(State s1, State s2) { 77 | if (s1 == null || s2 == null) throw new NullPointerException(); 78 | if (s1.getWidth() != s2.getWidth() || s1.getHeight() != s2.getHeight()) return true; 79 | 80 | // Boxes 81 | this.variance = new int[yBoxes][xBoxes]; 82 | 83 | // set to a different by default, if a change is found then flag 84 | // non-match 85 | boolean different = false; 86 | // loop through whole image and compare individual blocks of images 87 | int b1 = 0; 88 | int b2 = 0; 89 | int diff = 0; 90 | for (int y = 0; y < yBoxes; y++) { 91 | for (int x = 0; x < xBoxes; x++) { 92 | b1 = aggregateMapArea(state1.getMap(), x, y); 93 | b2 = aggregateMapArea(state2.getMap(), x, y); 94 | diff = Math.abs(b1 - b2); 95 | variance[y][x] = diff; 96 | // the difference in a certain region has passed the threshold 97 | // value 98 | if (diff > leniency) different = true; 99 | } 100 | } 101 | return different; 102 | } 103 | 104 | private int aggregateMapArea(int[] map, int xBox, int yBox) { 105 | if (map == null) throw new NullPointerException(); 106 | 107 | int yPix = yPixelsPerBox; 108 | int xPix = xPixelsPerBox; 109 | if (yBox == (yBoxes - 1) && yLeftOver > 0) yPix = yLeftOver; 110 | if (xBox == (xBoxes - 1) && xLeftOver > 0) xPix = xLeftOver; 111 | 112 | int rowOffset = (yBox * yPixelsPerBox * rowWidthInPix); 113 | int columnOffset = (xBox * colWidthInPix); 114 | 115 | int i = 0; 116 | int iy = 0; 117 | for (int y = 0; y < yPix; y++) { 118 | iy = (y * (xBoxes * xPixelsPerBox)) - (y * (xPixelsPerBox - xLeftOver)); 119 | for (int x = 0; x < xPix; x++) { 120 | i += map[rowOffset + columnOffset + iy + x]; 121 | } 122 | } 123 | 124 | return (i / (xPix * yPix)); 125 | } 126 | 127 | /** 128 | * Given the int array of an image, paint the pixels that are different. 129 | * 130 | * @param data 131 | * int array of an image. 132 | * @throws NullPointerException 133 | * if data int array is NULL. 134 | */ 135 | public void paintDifferences(int[] data) { 136 | if (data == null) throw new NullPointerException(); 137 | 138 | for (int y = 0; y < yBoxes; y++) { 139 | for (int x = 0; x < xBoxes; x++) { 140 | if (variance[y][x] > leniency) paint(data, x, y, Color.RED); 141 | } 142 | } 143 | } 144 | 145 | private void paint(int[] data, int xBox, int yBox, int color) { 146 | if (data == null) throw new NullPointerException(); 147 | 148 | int yPix = yPixelsPerBox; 149 | int xPix = xPixelsPerBox; 150 | if (yBox == (yBoxes - 1) && yLeftOver > 0) yPix = yLeftOver; 151 | if (xBox == (xBoxes - 1) && xLeftOver > 0) xPix = xLeftOver; 152 | 153 | int rowOffset = (yBox * yPixelsPerBox * rowWidthInPix); 154 | int columnOffset = (xBox * colWidthInPix); 155 | 156 | int iy = 0; 157 | for (int y = 0; y < yPix; y++) { 158 | iy = y * (xBoxes * xPixelsPerBox) - (y * (xPixelsPerBox - xLeftOver)); 159 | for (int x = 0; x < xPix; x++) { 160 | if (y == 0 || y == (yPix - 1) || x == 0 || x == (xPix - 1)) data[rowOffset + columnOffset + iy + x] = color; 161 | } 162 | } 163 | } 164 | 165 | /** 166 | * Number of X Boxes. 167 | * 168 | * @return int representing the number of X boxes. 169 | */ 170 | public int getCompareX() { 171 | return xBoxes; 172 | } 173 | 174 | /** 175 | * Number of Y Boxes. 176 | * 177 | * @return int representing the number of Y boxes. 178 | */ 179 | public int getCompareY() { 180 | return yBoxes; 181 | } 182 | 183 | /** 184 | * Leniency of the pixel comparison. 185 | * 186 | * @return int representing the leniency. 187 | */ 188 | public int getLeniency() { 189 | return leniency; 190 | } 191 | 192 | /** 193 | * Debug mode of the comparer. 194 | * 195 | * @return int representing the debug mode. 196 | */ 197 | public int getDebugMode() { 198 | return debugMode; 199 | } 200 | 201 | /** 202 | * Are the two States different. 203 | * 204 | * @return True is the States are different. 205 | */ 206 | public boolean isDifferent() { 207 | return different; 208 | } 209 | 210 | /** 211 | * {@inheritDoc} 212 | */ 213 | @Override 214 | public String toString() { 215 | int diff = 0; 216 | StringBuilder output = new StringBuilder(); 217 | for (int y = 0; y < yBoxes; y++) { 218 | output.append('|'); 219 | for (int x = 0; x < xBoxes; x++) { 220 | diff = variance[y][x]; 221 | if (debugMode == 1) output.append((diff > leniency) ? 'X' : ' '); 222 | if (debugMode == 2) output.append(diff + ((x < (xBoxes - 1)) ? "," : "")); 223 | } 224 | output.append("|\n"); 225 | } 226 | return output.toString(); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/detection/IMotionDetection.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection.detection; 2 | 3 | /** 4 | * This interface is used to represent a class that can detect motion 5 | * 6 | * @author Justin Wetherell 7 | */ 8 | public interface IMotionDetection { 9 | 10 | /** 11 | * Get the previous image in integer array format 12 | * 13 | * @return int array of previous image. 14 | */ 15 | public int[] getPrevious(); 16 | 17 | /** 18 | * Detect motion. 19 | * 20 | * @param data 21 | * integer array representing an image. 22 | * @param width 23 | * Width of the image. 24 | * @param height 25 | * Height of the image. 26 | * @return boolean True is there is motion. 27 | * @throws NullPointerException 28 | * if data integer array is NULL. 29 | */ 30 | public boolean detect(int[] data, int width, int height); 31 | } 32 | -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/detection/LumaMotionDetection.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection.detection; 2 | 3 | import android.graphics.Color; 4 | 5 | 6 | //import android.util.Log; 7 | 8 | /** 9 | * This class is used to process integer arrays containing Luma data and detects 10 | * motion. 11 | * 12 | * @author Justin Wetherell 13 | */ 14 | public class LumaMotionDetection implements IMotionDetection { 15 | 16 | // private static final String TAG = "LumaMotionDetection"; 17 | 18 | // Specific settings 19 | private static final int mPixelThreshold = 50; // Difference in luma value 20 | private static final int mThreshold = 10000; // Number of different pixels 21 | 22 | private static int[] mPrevious = null; 23 | private static int mPreviousWidth = 0; 24 | private static int mPreviousHeight = 0; 25 | 26 | /** 27 | * {@inheritDoc} 28 | */ 29 | @Override 30 | public int[] getPrevious() { 31 | return ((mPrevious != null) ? mPrevious.clone() : null); 32 | } 33 | 34 | protected static boolean isDifferent(int[] first, int width, int height) { 35 | if (first == null) throw new NullPointerException(); 36 | 37 | if (mPrevious == null) return false; 38 | if (first.length != mPrevious.length) return true; 39 | if (mPreviousWidth != width || mPreviousHeight != height) return true; 40 | 41 | int totDifferentPixels = 0; 42 | for (int i = 0, ij = 0; i < height; i++) { 43 | for (int j = 0; j < width; j++, ij++) { 44 | int pix = (0xff & (first[ij])); 45 | int otherPix = (0xff & (mPrevious[ij])); 46 | 47 | // Catch any pixels that are out of range 48 | if (pix < 0) pix = 0; 49 | if (pix > 255) pix = 255; 50 | if (otherPix < 0) otherPix = 0; 51 | if (otherPix > 255) otherPix = 255; 52 | 53 | if (Math.abs(pix - otherPix) >= mPixelThreshold) { 54 | totDifferentPixels++; 55 | // Paint different pixel red 56 | first[ij] = Color.RED; 57 | } 58 | } 59 | } 60 | if (totDifferentPixels <= 0) totDifferentPixels = 1; 61 | boolean different = totDifferentPixels > mThreshold; 62 | /* 63 | * int size = height * width; int percent = 64 | * 100/(size/totDifferentPixels); String output = 65 | * "Number of different pixels: " + totDifferentPixels + "> " + percent 66 | * + "%"; if (different) { Log.e(TAG, output); } else { Log.d(TAG, 67 | * output); } 68 | */ 69 | return different; 70 | } 71 | 72 | /** 73 | * Detect motion using comparing luma values. {@inheritDoc} 74 | */ 75 | @Override 76 | public boolean detect(int[] luma, int width, int height) { 77 | if (luma == null) throw new NullPointerException(); 78 | 79 | int[] original = luma.clone(); 80 | 81 | // Create the "mPrevious" picture, the one that will be used to check 82 | // the next frame against. 83 | if (mPrevious == null) { 84 | mPrevious = original; 85 | mPreviousWidth = width; 86 | mPreviousHeight = height; 87 | // Log.i(TAG, "Creating background image"); 88 | return false; 89 | } 90 | 91 | // long bDetection = System.currentTimeMillis(); 92 | boolean motionDetected = isDifferent(luma, width, height); 93 | // long aDetection = System.currentTimeMillis(); 94 | // Log.d(TAG, "Detection "+(aDetection-bDetection)); 95 | 96 | // Replace the current image with the previous. 97 | mPrevious = original; 98 | mPreviousWidth = width; 99 | mPreviousHeight = height; 100 | 101 | return motionDetected; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/detection/RgbMotionDetection.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection.detection; 2 | 3 | import android.graphics.Color; 4 | 5 | 6 | //import android.util.Log; 7 | 8 | /** 9 | * This class is used to process integer arrays containing RGB data and detects 10 | * motion. 11 | * 12 | * @author Justin Wetherell 13 | */ 14 | public class RgbMotionDetection implements IMotionDetection { 15 | 16 | // private static final String TAG = "RgbMotionDetection"; 17 | 18 | // Specific settings 19 | private static final int mPixelThreshold = 50; // Difference in pixel (RGB) 20 | private static final int mThreshold = 10000; // Number of different pixels 21 | // (RGB) 22 | 23 | private static int[] mPrevious = null; 24 | private static int mPreviousWidth = 0; 25 | private static int mPreviousHeight = 0; 26 | 27 | /** 28 | * {@inheritDoc} 29 | */ 30 | @Override 31 | public int[] getPrevious() { 32 | return ((mPrevious != null) ? mPrevious.clone() : null); 33 | } 34 | 35 | protected static boolean isDifferent(int[] first, int width, int height) { 36 | if (first == null) throw new NullPointerException(); 37 | 38 | if (mPrevious == null) return false; 39 | if (first.length != mPrevious.length) return true; 40 | if (mPreviousWidth != width || mPreviousHeight != height) return true; 41 | 42 | int totDifferentPixels = 0; 43 | for (int i = 0, ij = 0; i < height; i++) { 44 | for (int j = 0; j < width; j++, ij++) { 45 | int pix = (0xff & (first[ij])); 46 | int otherPix = (0xff & (mPrevious[ij])); 47 | 48 | // Catch any pixels that are out of range 49 | if (pix < 0) pix = 0; 50 | if (pix > 255) pix = 255; 51 | if (otherPix < 0) otherPix = 0; 52 | if (otherPix > 255) otherPix = 255; 53 | 54 | if (Math.abs(pix - otherPix) >= mPixelThreshold) { 55 | totDifferentPixels++; 56 | // Paint different pixel red 57 | first[ij] = Color.RED; 58 | } 59 | } 60 | } 61 | if (totDifferentPixels <= 0) totDifferentPixels = 1; 62 | boolean different = totDifferentPixels > mThreshold; 63 | /* 64 | * int size = height * width; int percent = 65 | * 100/(size/totDifferentPixels); String output = 66 | * "Number of different pixels: " + totDifferentPixels + "> " + percent 67 | * + "%"; if (different) { Log.e(TAG, output); } else { Log.d(TAG, 68 | * output); } 69 | */ 70 | return different; 71 | } 72 | 73 | /** 74 | * Detect motion comparing RGB pixel values. {@inheritDoc} 75 | */ 76 | @Override 77 | public boolean detect(int[] rgb, int width, int height) { 78 | if (rgb == null) throw new NullPointerException(); 79 | 80 | int[] original = rgb.clone(); 81 | 82 | // Create the "mPrevious" picture, the one that will be used to check 83 | // the next frame against. 84 | if (mPrevious == null) { 85 | mPrevious = original; 86 | mPreviousWidth = width; 87 | mPreviousHeight = height; 88 | // Log.i(TAG, "Creating background image"); 89 | return false; 90 | } 91 | 92 | // long bDetection = System.currentTimeMillis(); 93 | boolean motionDetected = isDifferent(rgb, width, height); 94 | // long aDetection = System.currentTimeMillis(); 95 | // Log.d(TAG, "Detection "+(aDetection-bDetection)); 96 | 97 | // Replace the current image with the previous. 98 | mPrevious = original; 99 | mPreviousWidth = width; 100 | mPreviousHeight = height; 101 | 102 | return motionDetected; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/detection/State.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection.detection; 2 | 3 | /** 4 | * This class is adapted from the web site below. It creates a state object 5 | * based on the brightness of a RGB image represented by an integer array. 6 | * http://mindmeat.blogspot.com/2008/11/java-image-comparison.html 7 | * 8 | * @author Pat Cullen 9 | * @author Justin Wetherell 10 | */ 11 | public class State { 12 | 13 | private int[] map = null; 14 | private int width; 15 | private int height; 16 | private int average; 17 | 18 | public State(int[] data, int width, int height) { 19 | if (data == null) throw new NullPointerException(); 20 | 21 | this.map = data.clone(); 22 | this.width = width; 23 | this.height = height; 24 | 25 | // build map and stats 26 | this.average = 0; 27 | for (int y = 0, xy = 0; y < this.height; y++) { 28 | for (int x = 0; x < this.width; x++, xy++) { 29 | this.average += data[xy]; 30 | } 31 | } 32 | this.average = (this.average / (this.width * this.height)); 33 | } 34 | 35 | /** 36 | * Get Map of the State. 37 | * 38 | * @return integer array of the State. 39 | */ 40 | public int[] getMap() { 41 | return map; 42 | } 43 | 44 | /** 45 | * Get the width of the State. 46 | * 47 | * @return integer representing the width of the state. 48 | */ 49 | public int getWidth() { 50 | return width; 51 | } 52 | 53 | /** 54 | * Get the height of the State. 55 | * 56 | * @return integer representing the height of the state. 57 | */ 58 | public int getHeight() { 59 | return height; 60 | } 61 | 62 | /** 63 | * {@inheritDoc} 64 | */ 65 | @Override 66 | public String toString() { 67 | StringBuilder output = new StringBuilder(); 68 | output.append("h=" + height + " w=" + width + "\n"); 69 | for (int y = 0, xy = 0; y < height; y++) { 70 | output.append('|'); 71 | for (int x = 0; x < width; x++, xy++) { 72 | output.append(map[xy]); 73 | output.append('|'); 74 | } 75 | output.append("\n"); 76 | } 77 | return output.toString(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/com/jwetherell/motion_detection/image/ImageProcessing.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.motion_detection.image; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Color; 7 | import android.graphics.Matrix; 8 | 9 | 10 | /** 11 | * This abstract class is used to process images. 12 | * 13 | * @author Justin Wetherell 14 | */ 15 | public abstract class ImageProcessing { 16 | 17 | public static final int A = 0; 18 | public static final int R = 1; 19 | public static final int G = 2; 20 | public static final int B = 3; 21 | 22 | public static final int H = 0; 23 | public static final int S = 1; 24 | public static final int L = 2; 25 | 26 | private ImageProcessing() { 27 | } 28 | 29 | /** 30 | * Get RGB values from pixel. 31 | * 32 | * @param pixel 33 | * Integer representation of a pixel. 34 | * @return float array of a,r,g,b values. 35 | */ 36 | public static float[] getARGB(int pixel) { 37 | int a = (pixel >> 24) & 0xff; 38 | int r = (pixel >> 16) & 0xff; 39 | int g = (pixel >> 8) & 0xff; 40 | int b = (pixel) & 0xff; 41 | return (new float[] { a, r, g, b }); 42 | } 43 | 44 | /** 45 | * Get HSL (Hue, Saturation, Luma) from RGB. Note1: H is 0-360 (degrees) 46 | * Note2: S and L are 0-100 (percent) 47 | * 48 | * @param r 49 | * Red value. 50 | * @param g 51 | * Green value. 52 | * @param b 53 | * Blue value. 54 | * @return Integer array representing an HSL pixel. 55 | */ 56 | public static int[] convertToHSL(int r, int g, int b) { 57 | float red = r / 255; 58 | float green = g / 255; 59 | float blue = b / 255; 60 | 61 | float minComponent = Math.min(red, Math.min(green, blue)); 62 | float maxComponent = Math.max(red, Math.max(green, blue)); 63 | float range = maxComponent - minComponent; 64 | float h = 0, s = 0, l = 0; 65 | 66 | l = (maxComponent + minComponent) / 2; 67 | 68 | if (range == 0) { // Monochrome image 69 | h = s = 0; 70 | } else { 71 | s = (l > 0.5) ? range / (2 - range) : range / (maxComponent + minComponent); 72 | 73 | if (red == maxComponent) { 74 | h = (blue - green) / range; 75 | } else if (green == maxComponent) { 76 | h = 2 + (blue - red) / range; 77 | } else if (blue == maxComponent) { 78 | h = 4 + (red - green) / range; 79 | } 80 | } 81 | 82 | // convert to 0-360 (degrees) 83 | h *= 60; 84 | if (h < 0) h += 360; 85 | 86 | // convert to 0-100 (percent) 87 | s *= 100; 88 | l *= 100; 89 | 90 | // Since they were converted from float to int 91 | return (new int[] { (int) h, (int) s, (int) l }); 92 | } 93 | 94 | /** 95 | * Decode a YUV420SP image to Luma. 96 | * 97 | * @param yuv420sp 98 | * Byte array representing a YUV420SP image. 99 | * @param width 100 | * Width of the image. 101 | * @param height 102 | * Height of the image. 103 | * @return Integer array representing the Luma image. 104 | * @throws NullPointerException 105 | * if yuv420sp byte array is NULL. 106 | */ 107 | public static int[] decodeYUV420SPtoLuma(byte[] yuv420sp, int width, int height) { 108 | if (yuv420sp == null) throw new NullPointerException(); 109 | 110 | final int frameSize = width * height; 111 | int[] hsl = new int[frameSize]; 112 | 113 | for (int j = 0, yp = 0; j < height; j++) { 114 | for (int i = 0; i < width; i++, yp++) { 115 | int y = (0xff & (yuv420sp[yp])) - 16; 116 | if (y < 0) y = 0; 117 | hsl[yp] = y; 118 | } 119 | } 120 | return hsl; 121 | } 122 | 123 | /** 124 | * Decode a YUV420SP image to RGB. 125 | * 126 | * @param yuv420sp 127 | * Byte array representing a YUV420SP image. 128 | * @param width 129 | * Width of the image. 130 | * @param height 131 | * Height of the image. 132 | * @return Integer array representing the RGB image. 133 | * @throws NullPointerException 134 | * if yuv420sp byte array is NULL. 135 | */ 136 | public static int[] decodeYUV420SPtoRGB(byte[] yuv420sp, int width, int height) { 137 | if (yuv420sp == null) throw new NullPointerException(); 138 | 139 | final int frameSize = width * height; 140 | int[] rgb = new int[frameSize]; 141 | 142 | for (int j = 0, yp = 0; j < height; j++) { 143 | int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; 144 | for (int i = 0; i < width; i++, yp++) { 145 | int y = (0xff & (yuv420sp[yp])) - 16; 146 | if (y < 0) y = 0; 147 | if ((i & 1) == 0) { 148 | v = (0xff & yuv420sp[uvp++]) - 128; 149 | u = (0xff & yuv420sp[uvp++]) - 128; 150 | } 151 | int y1192 = 1192 * y; 152 | int r = (y1192 + 1634 * v); 153 | int g = (y1192 - 833 * v - 400 * u); 154 | int b = (y1192 + 2066 * u); 155 | 156 | if (r < 0) r = 0; 157 | else if (r > 262143) r = 262143; 158 | if (g < 0) g = 0; 159 | else if (g > 262143) g = 262143; 160 | if (b < 0) b = 0; 161 | else if (b > 262143) b = 262143; 162 | 163 | rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); 164 | } 165 | } 166 | return rgb; 167 | } 168 | 169 | /** 170 | * Convert an RGB image into a Bitmap. 171 | * 172 | * @param rgb 173 | * Integer array representing an RGB image. 174 | * @param width 175 | * Width of the image. 176 | * @param height 177 | * Height of the image. 178 | * @return Bitmap of the RGB image. 179 | * @throws NullPointerException 180 | * if RGB integer array is NULL. 181 | */ 182 | public static Bitmap rgbToBitmap(int[] rgb, int width, int height) { 183 | if (rgb == null) throw new NullPointerException(); 184 | 185 | Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); 186 | bitmap.setPixels(rgb, 0, width, 0, 0, width, height); 187 | return bitmap; 188 | } 189 | 190 | /** 191 | * Convert an Luma image into Greyscale. 192 | * 193 | * @param lum 194 | * Integer array representing an Luma image. 195 | * @param width 196 | * Width of the image. 197 | * @param height 198 | * Height of the image. 199 | * @return Bitmap of the Luma image. 200 | * @throws NullPointerException 201 | * if RGB integer array is NULL. 202 | */ 203 | public static Bitmap lumaToGreyscale(int[] lum, int width, int height) { 204 | if (lum == null) throw new NullPointerException(); 205 | 206 | Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); 207 | for (int y = 0, xy = 0; y < bitmap.getHeight(); y++) { 208 | for (int x = 0; x < bitmap.getWidth(); x++, xy++) { 209 | int luma = lum[xy]; 210 | bitmap.setPixel(x, y, Color.argb(1, luma, luma, luma)); 211 | } 212 | } 213 | return bitmap; 214 | } 215 | 216 | /** 217 | * Rotate the given Bitmap by the given degrees. 218 | * 219 | * @param bmp 220 | * Bitmap to rotate. 221 | * @param degrees 222 | * Degrees to rotate. 223 | * @return Bitmap which was rotated. 224 | */ 225 | public static Bitmap rotate(Bitmap bmp, int degrees) { 226 | if (bmp == null) throw new NullPointerException(); 227 | 228 | // getting scales of the image 229 | int width = bmp.getWidth(); 230 | int height = bmp.getHeight(); 231 | 232 | // Creating a Matrix and rotating it to 90 degrees 233 | Matrix matrix = new Matrix(); 234 | matrix.postRotate(degrees); 235 | 236 | // Getting the rotated Bitmap 237 | Bitmap rotatedBmp = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix, true); 238 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); 239 | rotatedBmp.compress(Bitmap.CompressFormat.JPEG, 100, stream); 240 | return rotatedBmp; 241 | } 242 | 243 | /** 244 | * Rotate the given image in byte array format by the given degrees. 245 | * 246 | * @param data 247 | * Bitmap to rotate in byte array form. 248 | * @param degrees 249 | * Degrees to rotate. 250 | * @return Byte array format of an image which was rotated. 251 | */ 252 | public static byte[] rotate(byte[] data, int degrees) { 253 | if (data == null) throw new NullPointerException(); 254 | 255 | // Convert the byte data into a Bitmap 256 | Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length); 257 | 258 | // Getting the rotated Bitmap 259 | Bitmap rotatedBmp = rotate(bmp, degrees); 260 | 261 | // Get the byte array from the Bitmap 262 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); 263 | rotatedBmp.compress(Bitmap.CompressFormat.JPEG, 100, stream); 264 | return stream.toByteArray(); 265 | } 266 | } 267 | --------------------------------------------------------------------------------