分享

【UVCcamera/新手向】AS中初次使用OpenCV

 QomoIT 2019-08-09

  • 简单的灰度图

     o0olele/UVCcamera-OpenCV

    1.  新建一个camera的工程

    2.  将第三方库文件(源码里有)复制到对应位置

    3.  更改项目下的build.gradle

    4.  更改app下的build.gradle

    5.  更改界面,添加camera_view(这是UVC要求的,貌似)、imageView(用于显示opencv处理后的图像)、一个button(普通、imagebutton都行)

    6.  源代码

    (部分注释,刚入门,自己的一些理解)

    说在前面
    • 过程 

    • 源码地址

    • 运行截图

    • 说在前面

    1. package com.example.o0orick.camera;
    2. import android.animation.Animator;
    3. import android.graphics.Bitmap;
    4. import android.graphics.Matrix;
    5. import android.graphics.SurfaceTexture;
    6. import android.hardware.usb.UsbDevice;
    7. import android.os.Bundle;
    8. import android.support.annotation.NonNull;
    9. import android.util.Log;
    10. import android.view.Surface;
    11. import android.view.View;
    12. import android.view.View.OnClickListener;
    13. import android.view.Window;
    14. import android.view.WindowManager;
    15. import android.widget.AdapterView;
    16. import android.widget.CompoundButton;
    17. import android.widget.ImageButton;
    18. import android.widget.ImageView;
    19. import android.widget.SeekBar;
    20. import android.widget.Spinner;
    21. import android.widget.TextView;
    22. import android.widget.Toast;
    23. import android.widget.ToggleButton;
    24. import com.serenegiant.common.BaseActivity;
    25. import com.serenegiant.usb.CameraDialog;
    26. import com.serenegiant.usb.IFrameCallback;
    27. import com.serenegiant.usb.USBMonitor;
    28. import com.serenegiant.usb.USBMonitor.OnDeviceConnectListener;
    29. import com.serenegiant.usb.USBMonitor.UsbControlBlock;
    30. import com.serenegiant.usb.UVCCamera;
    31. import com.serenegiant.usbcameracommon.UVCCameraHandler;
    32. import com.serenegiant.utils.ViewAnimationHelper;
    33. import com.serenegiant.widget.CameraViewInterface;
    34. import org.opencv.android.BaseLoaderCallback;
    35. import org.opencv.android.LoaderCallbackInterface;
    36. import org.opencv.android.OpenCVLoader;
    37. import org.opencv.android.Utils;
    38. import org.opencv.core.Mat;
    39. import org.opencv.core.MatOfPoint;
    40. import org.opencv.core.MatOfRect;
    41. import org.opencv.core.Rect;
    42. import org.opencv.imgproc.Imgproc;
    43. import java.math.BigDecimal;
    44. import java.nio.ByteBuffer;
    45. import java.util.ArrayList;
    46. import java.util.List;
    47. public final class MainActivity extends BaseActivity implements CameraDialog.CameraDialogParent {
    48. private static final boolean DEBUG = true; // TODO set false on release
    49. private static final String TAG = "MainActivity";
    50. /**
    51. * 操作锁
    52. */
    53. private final Object mSync = new Object();
    54. /**
    55. * set true if you want to record movie using MediaSurfaceEncoder
    56. * (writing frame data into Surface camera from MediaCodec
    57. * by almost same way as USBCameratest2)
    58. * set false if you want to record movie using MediaVideoEncoder
    59. */
    60. private static final boolean USE_SURFACE_ENCODER = false;
    61. /**
    62. * preview resolution(width)
    63. * if your camera does not support specific resolution and mode,
    64. * {@link UVCCamera#setPreviewSize(int, int, int)} throw exception
    65. */
    66. private static final int PREVIEW_WIDTH = 640; // 640
    67. /**
    68. * preview resolution(height)
    69. * if your camera does not support specific resolution and mode,
    70. * {@link UVCCamera#setPreviewSize(int, int, int)} throw exception
    71. */
    72. private static final int PREVIEW_HEIGHT = 480; //480
    73. /**
    74. * preview mode
    75. * if your camera does not support specific resolution and mode,
    76. * {@link UVCCamera#setPreviewSize(int, int, int)} throw exception
    77. * 0:YUYV, other:MJPEG
    78. */
    79. private static final int PREVIEW_MODE = 0; // YUV
    80. protected static final int SETTINGS_HIDE_DELAY_MS = 2500;
    81. /**
    82. * for accessing USB
    83. */
    84. private USBMonitor mUSBMonitor;
    85. /**
    86. * Handler to execute camera related methods sequentially on private thread
    87. */
    88. private UVCCameraHandler mCameraHandler;
    89. /**
    90. * for camera preview display
    91. */
    92. private CameraViewInterface mUVCCameraView;
    93. /**
    94. * for open&start / stop&close camera preview
    95. */
    96. private ImageButton mCameraButton;
    97. private ImageView mImageView;
    98. private boolean isScaling = false;
    99. private boolean isInCapturing = false;
    100. private int[][] capture_solution = {{640,480}, {800,600},{1024,768}, {1280,1024}};
    101. private int mCaptureWidth = capture_solution[0][0];
    102. private int mCaptureHeight = capture_solution[0][1];
    103. /**
    104. * opencv的一个抽象类,为了支持opencv与app之间的相互作用,
    105. * 该类声明了一个callback,在opencv manager之后执行,这个回调是为了使opencv在合适的地方进行初始化
    106. */
    107. private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
    108. @Override
    109. public void onManagerConnected(int status) {
    110. switch (status) {
    111. case LoaderCallbackInterface.SUCCESS:
    112. {
    113. Log.i(TAG, "OpenCV loaded successfully");
    114. } break;
    115. default:
    116. {
    117. super.onManagerConnected(status);
    118. } break;
    119. }
    120. }
    121. };
    122. @Override
    123. protected void onCreate(final Bundle savedInstanceState) {
    124. super.onCreate(savedInstanceState);
    125. Log.v(TAG, "onCreate:");
    126. getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    127. requestWindowFeature(Window.FEATURE_NO_TITLE);
    128. getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
    129. WindowManager.LayoutParams.FLAG_FULLSCREEN);
    130. setContentView(R.layout.activity_main);
    131. mCameraButton = findViewById(R.id.imageButton);
    132. mCameraButton.setOnClickListener(mOnClickListener);
    133. mImageView = (ImageView)findViewById(R.id.imageView);
    134. mCaptureWidth = capture_solution[0][0];
    135. mCaptureHeight = capture_solution[0][1];
    136. bitmap = Bitmap.createBitmap(mCaptureWidth, mCaptureHeight, Bitmap.Config.RGB_565);
    137. final View view = findViewById(R.id.camera_view);
    138. mUVCCameraView = (CameraViewInterface)view;
    139. mUVCCameraView.setAspectRatio(PREVIEW_WIDTH / (float)PREVIEW_HEIGHT);
    140. synchronized (mSync) {
    141. mUSBMonitor = new USBMonitor(this, mOnDeviceConnectListener);
    142. mCameraHandler = UVCCameraHandler.createHandler(this, mUVCCameraView,
    143. USE_SURFACE_ENCODER ? 0 : 1, PREVIEW_WIDTH, PREVIEW_HEIGHT, PREVIEW_MODE);
    144. }
    145. }
    146. @Override
    147. protected void onStart() {
    148. super.onStart();
    149. Log.v(TAG, "onStart:");
    150. if (!OpenCVLoader.initDebug()) {
    151. Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
    152. OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
    153. } else {
    154. Log.d(TAG, "OpenCV library found inside package. Using it!");
    155. mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
    156. }
    157. synchronized (mSync) {
    158. mUSBMonitor.register();
    159. }
    160. if (mUVCCameraView != null) {
    161. mUVCCameraView.onResume();
    162. }
    163. }
    164. @Override
    165. protected void onStop() {
    166. Log.v(TAG, "onStop:");
    167. synchronized (mSync) {
    168. mCameraHandler.close(); // #close include #stopRecording and #stopPreview
    169. mUSBMonitor.unregister();
    170. }
    171. if (mUVCCameraView != null)
    172. mUVCCameraView.onPause();
    173. super.onStop();
    174. }
    175. @Override
    176. public void onDestroy() {
    177. Log.v(TAG, "onDestroy:");
    178. synchronized (mSync) {
    179. if (mCameraHandler != null) {
    180. mCameraHandler.setPreviewCallback(null); //zhf
    181. mCameraHandler.release();
    182. mCameraHandler = null;
    183. }
    184. if (mUSBMonitor != null) {
    185. mUSBMonitor.destroy();
    186. mUSBMonitor = null;
    187. }
    188. }
    189. super.onDestroy();
    190. }
    191. /**
    192. * event handler when click camera / capture button
    193. */
    194. private final OnClickListener mOnClickListener = new OnClickListener() {
    195. @Override
    196. public void onClick(final View view) {
    197. synchronized (mSync) {
    198. if ((mCameraHandler != null) && !mCameraHandler.isOpened()) {
    199. CameraDialog.showDialog(MainActivity.this);
    200. } else {
    201. mCameraHandler.close();
    202. }
    203. }
    204. }
    205. };
    206. private void startPreview() {
    207. synchronized (mSync) {
    208. if (mCameraHandler != null) {
    209. final SurfaceTexture st = mUVCCameraView.getSurfaceTexture();
    210. /**
    211. * 由于surfaceview由另一个线程处理,这里使用消息处理机制
    212. * 对Frame进行回调处理
    213. */
    214. mCameraHandler.setPreviewCallback(mIFrameCallback);
    215. mCameraHandler.startPreview(new Surface(st));
    216. }
    217. }
    218. updateItems();
    219. }
    220. private final OnDeviceConnectListener mOnDeviceConnectListener = new OnDeviceConnectListener() {
    221. @Override
    222. public void onAttach(final UsbDevice device) {
    223. Toast.makeText(MainActivity.this, "USB_DEVICE_ATTACHED", Toast.LENGTH_SHORT).show();
    224. }
    225. @Override
    226. public void onConnect(final UsbDevice device, final UsbControlBlock ctrlBlock, final boolean createNew) {
    227. if (DEBUG) Log.v(TAG, "onConnect:");
    228. synchronized (mSync) {
    229. if (mCameraHandler != null) {
    230. mCameraHandler.open(ctrlBlock);
    231. startPreview();
    232. updateItems();
    233. }
    234. }
    235. }
    236. @Override
    237. public void onDisconnect(final UsbDevice device, final UsbControlBlock ctrlBlock) {
    238. if (DEBUG) Log.v(TAG, "onDisconnect:");
    239. synchronized (mSync) {
    240. if (mCameraHandler != null) {
    241. queueEvent(new Runnable() {
    242. @Override
    243. public void run() {
    244. try{
    245. // maybe throw java.lang.IllegalStateException: already released
    246. mCameraHandler.setPreviewCallback(null); //zhf
    247. }
    248. catch(Exception e){
    249. e.printStackTrace();
    250. }
    251. mCameraHandler.close();
    252. }
    253. }, 0);
    254. }
    255. }
    256. }
    257. @Override
    258. public void onDettach(final UsbDevice device) {
    259. Toast.makeText(MainActivity.this, "USB_DEVICE_DETACHED", Toast.LENGTH_SHORT).show();
    260. }
    261. @Override
    262. public void onCancel(final UsbDevice device) {
    263. }
    264. };
    265. /**
    266. * to access from CameraDialog
    267. * @return
    268. */
    269. @Override
    270. public USBMonitor getUSBMonitor() {
    271. synchronized (mSync) {
    272. return mUSBMonitor;
    273. }
    274. }
    275. @Override
    276. public void onDialogResult(boolean canceled) {
    277. if (DEBUG) Log.v(TAG, "onDialogResult:canceled=" + canceled);
    278. }
    279. //================================================================================
    280. private boolean isActive() {
    281. return mCameraHandler != null && mCameraHandler.isOpened();
    282. }
    283. private boolean checkSupportFlag(final int flag) {
    284. return mCameraHandler != null && mCameraHandler.checkSupportFlag(flag);
    285. }
    286. private int getValue(final int flag) {
    287. return mCameraHandler != null ? mCameraHandler.getValue(flag) : 0;
    288. }
    289. private int setValue(final int flag, final int value) {
    290. return mCameraHandler != null ? mCameraHandler.setValue(flag, value) : 0;
    291. }
    292. private int resetValue(final int flag) {
    293. return mCameraHandler != null ? mCameraHandler.resetValue(flag) : 0;
    294. }
    295. /**
    296. * 利用Activity.runOnUiThread(Runnable)把更新ui的代码创建在Runnable中,
    297. * 然后在需要更新ui时,把这个Runnable对象传给Activity.runOnUiThread(Runnable)
    298. */
    299. private void updateItems() {
    300. runOnUiThread(mUpdateItemsOnUITask, 100);
    301. }
    302. private final Runnable mUpdateItemsOnUITask = new Runnable() {
    303. @Override
    304. public void run() {
    305. if (isFinishing()) return;
    306. final int visible_active = isActive() ? View.VISIBLE : View.INVISIBLE;
    307. mImageView.setVisibility(visible_active);
    308. }
    309. };
    310. // if you need frame data as byte array on Java side, you can use this callback method with UVCCamera#setFrameCallback
    311. // if you need to create Bitmap in IFrameCallback, please refer following snippet.
    312. private Bitmap bitmap = null;//Bitmap.createBitmap(640, 480, Bitmap.Config.RGB_565);
    313. private final Bitmap srcBitmap = Bitmap.createBitmap(PREVIEW_WIDTH, PREVIEW_HEIGHT, Bitmap.Config.RGB_565);
    314. private String WarnText;
    315. private final IFrameCallback mIFrameCallback = new IFrameCallback() {
    316. @Override
    317. public void onFrame(final ByteBuffer frame) {
    318. frame.clear();
    319. if(!isActive() || isInCapturing){
    320. return;
    321. }
    322. if(bitmap == null){
    323. Toast.makeText(MainActivity.this, "错误:Bitmap为空", Toast.LENGTH_SHORT).show();
    324. return;
    325. }
    326. /**
    327. * 这里进行opencv操作
    328. * srcBitmap:源
    329. * bitmap:处理后
    330. */
    331. synchronized (bitmap) {
    332. srcBitmap.copyPixelsFromBuffer(frame);
    333. WarnText = "";
    334. if(bitmap.getWidth() != mCaptureWidth || bitmap.getHeight() != mCaptureHeight){
    335. bitmap = Bitmap.createBitmap(mCaptureWidth, mCaptureHeight, Bitmap.Config.RGB_565);
    336. }
    337. Mat rgbMat = new Mat();
    338. Mat grayMat = new Mat();
    339. bitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.RGB_565);
    340. Utils.bitmapToMat(srcBitmap, rgbMat);//convert original bitmap to Mat, R G B.
    341. Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY);//rgbMat to gray grayMat
    342. Utils.matToBitmap(grayMat, bitmap); //convert mat to bitmap
    343. Log.i(TAG, "procSrc2Gray sucess...");
    344. }
    345. mImageView.post(mUpdateImageTask);
    346. }
    347. };
    348. private final Runnable mUpdateImageTask = new Runnable() {
    349. @Override
    350. public void run() {
    351. synchronized (bitmap) {
    352. mImageView.setImageBitmap(bitmap);
    353. }
    354. }
    355. };
    356. }
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas./apk/res/android"
    3. xmlns:app="http://schemas./apk/res-auto"
    4. xmlns:tools="http://schemas./tools"
    5. android:layout_width="match_parent"
    6. android:layout_height="match_parent"
    7. tools:context=".MainActivity">
    8. <com.serenegiant.widget.UVCCameraTextureView
    9. android:id="@+id/camera_view"
    10. android:layout_width="20dp"
    11. android:layout_height="16dp"
    12. android:layout_centerInParent="true" />
    13. <ImageView
    14. android:id="@+id/imageView"
    15. android:layout_width="match_parent"
    16. android:layout_height="match_parent"
    17. android:scaleType="fitCenter"
    18. android:src="?attr/colorBackgroundFloating"
    19. app:srcCompat="@color/BLACK" />
    20. <ImageButton
    21. android:id="@+id/imageButton"
    22. android:layout_width="50dp"
    23. android:layout_height="50dp"
    24. android:layout_marginBottom="16dp"
    25. android:background="@mipmap/ic_transparent"
    26. android:scaleType="fitCenter"
    27. android:src="@drawable/btn_new_shutter"
    28. app:layout_constraintBottom_toBottomOf="parent"
    29. app:layout_constraintEnd_toEndOf="parent"
    30. app:layout_constraintStart_toStartOf="parent" />
    31. </android.support.constraint.ConstraintLayout>
    1. apply plugin: 'com.android.application'
    2. android {
    3. compileSdkVersion 27
    4. defaultConfig {
    5. applicationId "com.example.o0orick.camera"
    6. minSdkVersion 21
    7. targetSdkVersion 27
    8. versionCode 1
    9. versionName "1.0"
    10. testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    11. }
    12. buildTypes {
    13. release {
    14. minifyEnabled false
    15. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    16. }
    17. }
    18. //添加内容
    19. repositories {
    20. flatDir {
    21. dirs 'libs'
    22. }
    23. }
    24. }
    25. dependencies {
    26. implementation fileTree(dir: 'libs', include: ['*.jar'])
    27. implementation 'com.android.support:appcompat-v7:27.1.1'
    28. implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    29. testImplementation 'junit:junit:4.12'
    30. androidTestImplementation 'com.android.support.test:runner:1.0.2'
    31. androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    32. //添加内容,使用第三方库
    33. implementation(name: 'openCVLibrary', ext: 'aar')
    34. implementation(name: 'libuvccamera', ext: 'aar')
    35. implementation(name: 'usbCameraCommon', ext: 'aar')
    36. implementation("com.serenegiant:common:1.5.20") {
    37. exclude module: 'support-v4'
    38. }
    39. }
    1. buildscript {
    2. repositories {
    3. google()
    4. jcenter()
    5. }
    6. dependencies {
    7. classpath 'com.android.tools.build:gradle:3.2.0'
    8. //改成自己使用的版本
    9. }
    10. }
    11. allprojects {
    12. repositories {
    13. maven { url 'http://raw.github.com/saki4510t/libcommon/master/repository/' }
    14. google()
    15. jcenter()
    16. }
    17. configurations.all {
    18. resolutionStrategy.eachDependency { DependencyResolveDetails details ->
    19. def requested = details.requested
    20. if (requested.group == 'com.android.support') {
    21. if (!requested.name.startsWith("multidex")) {
    22. details.useVersion '27.1.1'
    23. //改成自己使用的版本
    24. //将所有的三方库使用的lib版本统一
    25. }
    26. }
    27. }
    28. }
    29. }
    30. task clean(type: Delete) {
    31. delete rootProject.buildDir
    32. }

Android Studio版本:3.2

操作系统(AS):Windows10

Android版本:5.0.2

摄像头:USB摄像头(640*480 贼辣鸡

开源项目:saki4510t/UVCCamerasaki4510t/OpenCVwithUVC

接上篇【UVCcamera/新手向】Android Studio编译&踩的坑

下一篇:【UVCcamera/新手向】AS中使用OpenCV进行简单人脸识别

  • 运行截图

简单的灰度图

  • 源码地址

 o0olele/UVCcamera-OpenCV

  • 过程 

1.  新建一个camera的工程

2.  将第三方库文件(源码里有)复制到对应位置

3.  更改项目下的build.gradle

  1. buildscript {
  2. repositories {
  3. google()
  4. jcenter()
  5. }
  6. dependencies {
  7. classpath 'com.android.tools.build:gradle:3.2.0'
  8. //改成自己使用的版本
  9. }
  10. }
  11. allprojects {
  12. repositories {
  13. maven { url 'http://raw.github.com/saki4510t/libcommon/master/repository/' }
  14. google()
  15. jcenter()
  16. }
  17. configurations.all {
  18. resolutionStrategy.eachDependency { DependencyResolveDetails details ->
  19. def requested = details.requested
  20. if (requested.group == 'com.android.support') {
  21. if (!requested.name.startsWith("multidex")) {
  22. details.useVersion '27.1.1'
  23. //改成自己使用的版本
  24. //将所有的三方库使用的lib版本统一
  25. }
  26. }
  27. }
  28. }
  29. }
  30. task clean(type: Delete) {
  31. delete rootProject.buildDir
  32. }

4.  更改app下的build.gradle

  1. apply plugin: 'com.android.application'
  2. android {
  3. compileSdkVersion 27
  4. defaultConfig {
  5. applicationId "com.example.o0orick.camera"
  6. minSdkVersion 21
  7. targetSdkVersion 27
  8. versionCode 1
  9. versionName "1.0"
  10. testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  11. }
  12. buildTypes {
  13. release {
  14. minifyEnabled false
  15. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  16. }
  17. }
  18. //添加内容
  19. repositories {
  20. flatDir {
  21. dirs 'libs'
  22. }
  23. }
  24. }
  25. dependencies {
  26. implementation fileTree(dir: 'libs', include: ['*.jar'])
  27. implementation 'com.android.support:appcompat-v7:27.1.1'
  28. implementation 'com.android.support.constraint:constraint-layout:1.1.3'
  29. testImplementation 'junit:junit:4.12'
  30. androidTestImplementation 'com.android.support.test:runner:1.0.2'
  31. androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
  32. //添加内容,使用第三方库
  33. implementation(name: 'openCVLibrary', ext: 'aar')
  34. implementation(name: 'libuvccamera', ext: 'aar')
  35. implementation(name: 'usbCameraCommon', ext: 'aar')
  36. implementation("com.serenegiant:common:1.5.20") {
  37. exclude module: 'support-v4'
  38. }
  39. }

5.  更改界面,添加camera_view(这是UVC要求的,貌似)、imageView(用于显示opencv处理后的图像)、一个button(普通、imagebutton都行)

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas./apk/res/android"
  3. xmlns:app="http://schemas./apk/res-auto"
  4. xmlns:tools="http://schemas./tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. tools:context=".MainActivity">
  8. <com.serenegiant.widget.UVCCameraTextureView
  9. android:id="@+id/camera_view"
  10. android:layout_width="20dp"
  11. android:layout_height="16dp"
  12. android:layout_centerInParent="true" />
  13. <ImageView
  14. android:id="@+id/imageView"
  15. android:layout_width="match_parent"
  16. android:layout_height="match_parent"
  17. android:scaleType="fitCenter"
  18. android:src="?attr/colorBackgroundFloating"
  19. app:srcCompat="@color/BLACK" />
  20. <ImageButton
  21. android:id="@+id/imageButton"
  22. android:layout_width="50dp"
  23. android:layout_height="50dp"
  24. android:layout_marginBottom="16dp"
  25. android:background="@mipmap/ic_transparent"
  26. android:scaleType="fitCenter"
  27. android:src="@drawable/btn_new_shutter"
  28. app:layout_constraintBottom_toBottomOf="parent"
  29. app:layout_constraintEnd_toEndOf="parent"
  30. app:layout_constraintStart_toStartOf="parent" />
  31. </android.support.constraint.ConstraintLayout>

6.  源代码

(部分注释,刚入门,自己的一些理解)

  1. package com.example.o0orick.camera;
  2. import android.animation.Animator;
  3. import android.graphics.Bitmap;
  4. import android.graphics.Matrix;
  5. import android.graphics.SurfaceTexture;
  6. import android.hardware.usb.UsbDevice;
  7. import android.os.Bundle;
  8. import android.support.annotation.NonNull;
  9. import android.util.Log;
  10. import android.view.Surface;
  11. import android.view.View;
  12. import android.view.View.OnClickListener;
  13. import android.view.Window;
  14. import android.view.WindowManager;
  15. import android.widget.AdapterView;
  16. import android.widget.CompoundButton;
  17. import android.widget.ImageButton;
  18. import android.widget.ImageView;
  19. import android.widget.SeekBar;
  20. import android.widget.Spinner;
  21. import android.widget.TextView;
  22. import android.widget.Toast;
  23. import android.widget.ToggleButton;
  24. import com.serenegiant.common.BaseActivity;
  25. import com.serenegiant.usb.CameraDialog;
  26. import com.serenegiant.usb.IFrameCallback;
  27. import com.serenegiant.usb.USBMonitor;
  28. import com.serenegiant.usb.USBMonitor.OnDeviceConnectListener;
  29. import com.serenegiant.usb.USBMonitor.UsbControlBlock;
  30. import com.serenegiant.usb.UVCCamera;
  31. import com.serenegiant.usbcameracommon.UVCCameraHandler;
  32. import com.serenegiant.utils.ViewAnimationHelper;
  33. import com.serenegiant.widget.CameraViewInterface;
  34. import org.opencv.android.BaseLoaderCallback;
  35. import org.opencv.android.LoaderCallbackInterface;
  36. import org.opencv.android.OpenCVLoader;
  37. import org.opencv.android.Utils;
  38. import org.opencv.core.Mat;
  39. import org.opencv.core.MatOfPoint;
  40. import org.opencv.core.MatOfRect;
  41. import org.opencv.core.Rect;
  42. import org.opencv.imgproc.Imgproc;
  43. import java.math.BigDecimal;
  44. import java.nio.ByteBuffer;
  45. import java.util.ArrayList;
  46. import java.util.List;
  47. public final class MainActivity extends BaseActivity implements CameraDialog.CameraDialogParent {
  48. private static final boolean DEBUG = true; // TODO set false on release
  49. private static final String TAG = "MainActivity";
  50. /**
  51. * 操作锁
  52. */
  53. private final Object mSync = new Object();
  54. /**
  55. * set true if you want to record movie using MediaSurfaceEncoder
  56. * (writing frame data into Surface camera from MediaCodec
  57. * by almost same way as USBCameratest2)
  58. * set false if you want to record movie using MediaVideoEncoder
  59. */
  60. private static final boolean USE_SURFACE_ENCODER = false;
  61. /**
  62. * preview resolution(width)
  63. * if your camera does not support specific resolution and mode,
  64. * {@link UVCCamera#setPreviewSize(int, int, int)} throw exception
  65. */
  66. private static final int PREVIEW_WIDTH = 640; // 640
  67. /**
  68. * preview resolution(height)
  69. * if your camera does not support specific resolution and mode,
  70. * {@link UVCCamera#setPreviewSize(int, int, int)} throw exception
  71. */
  72. private static final int PREVIEW_HEIGHT = 480; //480
  73. /**
  74. * preview mode
  75. * if your camera does not support specific resolution and mode,
  76. * {@link UVCCamera#setPreviewSize(int, int, int)} throw exception
  77. * 0:YUYV, other:MJPEG
  78. */
  79. private static final int PREVIEW_MODE = 0; // YUV
  80. protected static final int SETTINGS_HIDE_DELAY_MS = 2500;
  81. /**
  82. * for accessing USB
  83. */
  84. private USBMonitor mUSBMonitor;
  85. /**
  86. * Handler to execute camera related methods sequentially on private thread
  87. */
  88. private UVCCameraHandler mCameraHandler;
  89. /**
  90. * for camera preview display
  91. */
  92. private CameraViewInterface mUVCCameraView;
  93. /**
  94. * for open&start / stop&close camera preview
  95. */
  96. private ImageButton mCameraButton;
  97. private ImageView mImageView;
  98. private boolean isScaling = false;
  99. private boolean isInCapturing = false;
  100. private int[][] capture_solution = {{640,480}, {800,600},{1024,768}, {1280,1024}};
  101. private int mCaptureWidth = capture_solution[0][0];
  102. private int mCaptureHeight = capture_solution[0][1];
  103. /**
  104. * opencv的一个抽象类,为了支持opencv与app之间的相互作用,
  105. * 该类声明了一个callback,在opencv manager之后执行,这个回调是为了使opencv在合适的地方进行初始化
  106. */
  107. private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
  108. @Override
  109. public void onManagerConnected(int status) {
  110. switch (status) {
  111. case LoaderCallbackInterface.SUCCESS:
  112. {
  113. Log.i(TAG, "OpenCV loaded successfully");
  114. } break;
  115. default:
  116. {
  117. super.onManagerConnected(status);
  118. } break;
  119. }
  120. }
  121. };
  122. @Override
  123. protected void onCreate(final Bundle savedInstanceState) {
  124. super.onCreate(savedInstanceState);
  125. Log.v(TAG, "onCreate:");
  126. getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  127. requestWindowFeature(Window.FEATURE_NO_TITLE);
  128. getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  129. WindowManager.LayoutParams.FLAG_FULLSCREEN);
  130. setContentView(R.layout.activity_main);
  131. mCameraButton = findViewById(R.id.imageButton);
  132. mCameraButton.setOnClickListener(mOnClickListener);
  133. mImageView = (ImageView)findViewById(R.id.imageView);
  134. mCaptureWidth = capture_solution[0][0];
  135. mCaptureHeight = capture_solution[0][1];
  136. bitmap = Bitmap.createBitmap(mCaptureWidth, mCaptureHeight, Bitmap.Config.RGB_565);
  137. final View view = findViewById(R.id.camera_view);
  138. mUVCCameraView = (CameraViewInterface)view;
  139. mUVCCameraView.setAspectRatio(PREVIEW_WIDTH / (float)PREVIEW_HEIGHT);
  140. synchronized (mSync) {
  141. mUSBMonitor = new USBMonitor(this, mOnDeviceConnectListener);
  142. mCameraHandler = UVCCameraHandler.createHandler(this, mUVCCameraView,
  143. USE_SURFACE_ENCODER ? 0 : 1, PREVIEW_WIDTH, PREVIEW_HEIGHT, PREVIEW_MODE);
  144. }
  145. }
  146. @Override
  147. protected void onStart() {
  148. super.onStart();
  149. Log.v(TAG, "onStart:");
  150. if (!OpenCVLoader.initDebug()) {
  151. Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
  152. OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
  153. } else {
  154. Log.d(TAG, "OpenCV library found inside package. Using it!");
  155. mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
  156. }
  157. synchronized (mSync) {
  158. mUSBMonitor.register();
  159. }
  160. if (mUVCCameraView != null) {
  161. mUVCCameraView.onResume();
  162. }
  163. }
  164. @Override
  165. protected void onStop() {
  166. Log.v(TAG, "onStop:");
  167. synchronized (mSync) {
  168. mCameraHandler.close(); // #close include #stopRecording and #stopPreview
  169. mUSBMonitor.unregister();
  170. }
  171. if (mUVCCameraView != null)
  172. mUVCCameraView.onPause();
  173. super.onStop();
  174. }
  175. @Override
  176. public void onDestroy() {
  177. Log.v(TAG, "onDestroy:");
  178. synchronized (mSync) {
  179. if (mCameraHandler != null) {
  180. mCameraHandler.setPreviewCallback(null); //zhf
  181. mCameraHandler.release();
  182. mCameraHandler = null;
  183. }
  184. if (mUSBMonitor != null) {
  185. mUSBMonitor.destroy();
  186. mUSBMonitor = null;
  187. }
  188. }
  189. super.onDestroy();
  190. }
  191. /**
  192. * event handler when click camera / capture button
  193. */
  194. private final OnClickListener mOnClickListener = new OnClickListener() {
  195. @Override
  196. public void onClick(final View view) {
  197. synchronized (mSync) {
  198. if ((mCameraHandler != null) && !mCameraHandler.isOpened()) {
  199. CameraDialog.showDialog(MainActivity.this);
  200. } else {
  201. mCameraHandler.close();
  202. }
  203. }
  204. }
  205. };
  206. private void startPreview() {
  207. synchronized (mSync) {
  208. if (mCameraHandler != null) {
  209. final SurfaceTexture st = mUVCCameraView.getSurfaceTexture();
  210. /**
  211. * 由于surfaceview由另一个线程处理,这里使用消息处理机制
  212. * 对Frame进行回调处理
  213. */
  214. mCameraHandler.setPreviewCallback(mIFrameCallback);
  215. mCameraHandler.startPreview(new Surface(st));
  216. }
  217. }
  218. updateItems();
  219. }
  220. private final OnDeviceConnectListener mOnDeviceConnectListener = new OnDeviceConnectListener() {
  221. @Override
  222. public void onAttach(final UsbDevice device) {
  223. Toast.makeText(MainActivity.this, "USB_DEVICE_ATTACHED", Toast.LENGTH_SHORT).show();
  224. }
  225. @Override
  226. public void onConnect(final UsbDevice device, final UsbControlBlock ctrlBlock, final boolean createNew) {
  227. if (DEBUG) Log.v(TAG, "onConnect:");
  228. synchronized (mSync) {
  229. if (mCameraHandler != null) {
  230. mCameraHandler.open(ctrlBlock);
  231. startPreview();
  232. updateItems();
  233. }
  234. }
  235. }
  236. @Override
  237. public void onDisconnect(final UsbDevice device, final UsbControlBlock ctrlBlock) {
  238. if (DEBUG) Log.v(TAG, "onDisconnect:");
  239. synchronized (mSync) {
  240. if (mCameraHandler != null) {
  241. queueEvent(new Runnable() {
  242. @Override
  243. public void run() {
  244. try{
  245. // maybe throw java.lang.IllegalStateException: already released
  246. mCameraHandler.setPreviewCallback(null); //zhf
  247. }
  248. catch(Exception e){
  249. e.printStackTrace();
  250. }
  251. mCameraHandler.close();
  252. }
  253. }, 0);
  254. }
  255. }
  256. }
  257. @Override
  258. public void onDettach(final UsbDevice device) {
  259. Toast.makeText(MainActivity.this, "USB_DEVICE_DETACHED", Toast.LENGTH_SHORT).show();
  260. }
  261. @Override
  262. public void onCancel(final UsbDevice device) {
  263. }
  264. };
  265. /**
  266. * to access from CameraDialog
  267. * @return
  268. */
  269. @Override
  270. public USBMonitor getUSBMonitor() {
  271. synchronized (mSync) {
  272. return mUSBMonitor;
  273. }
  274. }
  275. @Override
  276. public void onDialogResult(boolean canceled) {
  277. if (DEBUG) Log.v(TAG, "onDialogResult:canceled=" + canceled);
  278. }
  279. //================================================================================
  280. private boolean isActive() {
  281. return mCameraHandler != null && mCameraHandler.isOpened();
  282. }
  283. private boolean checkSupportFlag(final int flag) {
  284. return mCameraHandler != null && mCameraHandler.checkSupportFlag(flag);
  285. }
  286. private int getValue(final int flag) {
  287. return mCameraHandler != null ? mCameraHandler.getValue(flag) : 0;
  288. }
  289. private int setValue(final int flag, final int value) {
  290. return mCameraHandler != null ? mCameraHandler.setValue(flag, value) : 0;
  291. }
  292. private int resetValue(final int flag) {
  293. return mCameraHandler != null ? mCameraHandler.resetValue(flag) : 0;
  294. }
  295. /**
  296. * 利用Activity.runOnUiThread(Runnable)把更新ui的代码创建在Runnable中,
  297. * 然后在需要更新ui时,把这个Runnable对象传给Activity.runOnUiThread(Runnable)
  298. */
  299. private void updateItems() {
  300. runOnUiThread(mUpdateItemsOnUITask, 100);
  301. }
  302. private final Runnable mUpdateItemsOnUITask = new Runnable() {
  303. @Override
  304. public void run() {
  305. if (isFinishing()) return;
  306. final int visible_active = isActive() ? View.VISIBLE : View.INVISIBLE;
  307. mImageView.setVisibility(visible_active);
  308. }
  309. };
  310. // if you need frame data as byte array on Java side, you can use this callback method with UVCCamera#setFrameCallback
  311. // if you need to create Bitmap in IFrameCallback, please refer following snippet.
  312. private Bitmap bitmap = null;//Bitmap.createBitmap(640, 480, Bitmap.Config.RGB_565);
  313. private final Bitmap srcBitmap = Bitmap.createBitmap(PREVIEW_WIDTH, PREVIEW_HEIGHT, Bitmap.Config.RGB_565);
  314. private String WarnText;
  315. private final IFrameCallback mIFrameCallback = new IFrameCallback() {
  316. @Override
  317. public void onFrame(final ByteBuffer frame) {
  318. frame.clear();
  319. if(!isActive() || isInCapturing){
  320. return;
  321. }
  322. if(bitmap == null){
  323. Toast.makeText(MainActivity.this, "错误:Bitmap为空", Toast.LENGTH_SHORT).show();
  324. return;
  325. }
  326. /**
  327. * 这里进行opencv操作
  328. * srcBitmap:源
  329. * bitmap:处理后
  330. */
  331. synchronized (bitmap) {
  332. srcBitmap.copyPixelsFromBuffer(frame);
  333. WarnText = "";
  334. if(bitmap.getWidth() != mCaptureWidth || bitmap.getHeight() != mCaptureHeight){
  335. bitmap = Bitmap.createBitmap(mCaptureWidth, mCaptureHeight, Bitmap.Config.RGB_565);
  336. }
  337. Mat rgbMat = new Mat();
  338. Mat grayMat = new Mat();
  339. bitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.RGB_565);
  340. Utils.bitmapToMat(srcBitmap, rgbMat);//convert original bitmap to Mat, R G B.
  341. Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY);//rgbMat to gray grayMat
  342. Utils.matToBitmap(grayMat, bitmap); //convert mat to bitmap
  343. Log.i(TAG, "procSrc2Gray sucess...");
  344. }
  345. mImageView.post(mUpdateImageTask);
  346. }
  347. };
  348. private final Runnable mUpdateImageTask = new Runnable() {
  349. @Override
  350. public void run() {
  351. synchronized (bitmap) {
  352. mImageView.setImageBitmap(bitmap);
  353. }
  354. }
  355. };
  356. }

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多