》权限
<uses-permission android:name="android.permission.CAMERA" /> <!-- 摄像头 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 内部存储 -->
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
》》 在MainActivity中继承CvCameraViewListener2接口
CvCameraViewListener2是使用OpenCV相机的核心监听
public class MainActivity extends Activity implements CvCameraViewListener2 {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onCameraViewStarted(int width, int height) {
// TODO Auto-generated method stub
}
@Override
public void onCameraViewStopped() {
// TODO Auto-generated method stub
}
@Override
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
// TODO Auto-generated method stub
return null;
}
}
onCameraViewStarted:相机启动时调用
onCameraViewStopped:相机销毁时调用
onCameraFrame: 相机工作时调用,参数是相机每一帧的图像,实时对比就在这个方法中进行
》》》 OnCreate中初始化相机,并添加开启相机的回调
/**
* CV相机
*/
private CameraBridgeViewBase mCVCamera;
/**
* 加载OpenCV的回调
*/
private BaseLoaderCallback mLoaderCallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化CV相机
mCVCamera = (CameraBridgeViewBase) findViewById(R.id.cv);
mCVCamera.setVisibility(CameraBridgeViewBase.VISIBLE);
// 设置相机监听
mCVCamera.setCvCameraViewListener(this);
// 连接到OpenCV的回调
mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
mCVCamera.enableView();
break;
default:
break;
}
}
};
}
》》》》界面加载完成时说明OpenCV已经初始化完成
所以重写onResume()方法,开启相机
@Override
protected void onResume() {
// 界面加载完成的时候向OpenCV的连接回调发送连接成功的信号
if (OpenCVLoader.initDebug()) {
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
super.onResume();
}
重写onPause方法,及时销毁相机
@Override
protected void onPause() {
super.onPause();
// 销毁OpenCV相机
if (mCVCamera != null)
mCVCamera.disableView();
}
编辑onCameraFrame方法,让相机的每一帧展示在界面上
@Override
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
return inputFrame.rgba();
}
package com.e.opcv;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;
import java.io.File;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class MainActivity extends CameraActivity implements CvCameraViewListener2{
private static final String TAG = "OCVSample::Activity";
//opencv接口标志
/**
* CV相机
*/
private CameraBridgeViewBase mOpenCvCameraView;
//缓存相机每帧输入的数据
private Mat mRgba;
private Button button;
private boolean mIsJavaCamera = true;
private MenuItem mItemSwitchCamera = null;
/**
* 加载OpenCV的回调
* 通过OpenCV管理Android服务,初始化OpenCV
*/
private BaseLoaderCallback mLoaderCallback ;
public MainActivity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
if(msg.what == 1){
button.performClick();
}
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
// //初始化并设置预览部件 // 初始化CV相机
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
// 设置相机监听
mOpenCvCameraView.setCvCameraViewListener(this);
//拍照按键
button = (Button) findViewById(R.id.deal_btn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mRgba != null) {
if(!mRgba.empty()) {
Mat inter = new Mat(mRgba.width(), mRgba.height(), CvType.CV_8UC4);
Log.e("Mat","...............1...............");
//将四通道的RGBA转为三通道的BGR,重要!!
Imgproc.cvtColor(mRgba, inter, Imgproc.COLOR_RGBA2BGR);
Log.e("Mat","...............2...............");
File sdDir = null;
//判断是否存在机身内存
boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
if(sdCardExist) {
//获得机身储存根目录
sdDir = Environment.getExternalStorageDirectory();
Log.e("Mat","...............3...............");
}
//将拍摄准确时间作为文件名
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
String filename = sdf.format(new Date());
String savepath=sdDir + "/Pictures/OpenCV/";
File f=new File(savepath);
if(!f.exists()){
f.mkdirs();
}
String filePath = sdDir + "/Pictures/OpenCV/" + filename + ".png";
Log.e("Mat","..............."+filePath+"...............");
//将转化后的BGR矩阵内容写入到文件中
Imgcodecs.imwrite(filePath, inter);
Toast.makeText(MainActivity.this, "图片保存到: "+ filePath, Toast.LENGTH_SHORT).show();
}
}
}
});
// moveTaskToBack(true);
// new test().start();
// 连接到OpenCV的回调
mLoaderCallback = new BaseLoaderCallback(this){
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
}
private class test extends Thread{
@Override
public void run() {
super.run();
while (true){
try {
Thread.sleep(2000);
Log.e("begin","kaishi.........");
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}catch (Exception e){
Log.e("error",e.getMessage());
}
}
}
}
@Override
public void onPause()
{
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
public void onResume()
{
// 界面加载完成的时候向OpenCV的连接回调发送连接成功的信号
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
super.onResume();
}
@Override
public List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
//对象实例化及基本属性的设置,包括长度、宽度和图像类型标志
public void onCameraViewStarted(int width, int height) {
Log.e("Mat","...............4...............");
mRgba = new Mat(height, width, CvType.CV_8UC4);
}
/**图像处理都写在这里!!!**/
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba(); //一定要有!!!不然数据保存不进MAT中!!!
//直接返回输入视频预览图的RGB数据并存放在Mat数据中
Log.e("Mat","...............5...............");
return mRgba;
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
//结束时释放
public void onCameraViewStopped() {
Log.e("Mat","...............6...............");
mRgba.release();
// mTmp.release();
}
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:opencv="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<org.opencv.android.JavaCameraView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"
android:id="@+id/tutorial1_activity_java_surface_view"
opencv:show_fps="true"
opencv:camera_id="any" />
</FrameLayout>
package com.e.opcv;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.WindowManager;
import java.util.Collections;
import java.util.List;
public class MainActivity extends CameraActivity implements CvCameraViewListener2{
private static final String TAG = "OCVSample::Activity";
private CameraBridgeViewBase mOpenCvCameraView;
private boolean mIsJavaCamera = true;
private MenuItem mItemSwitchCamera = null;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
public MainActivity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
}
@Override
public void onPause()
{
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
public void onResume()
{
super.onResume();
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
@Override
public List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
public void onCameraViewStarted(int width, int height) {
}
public void onCameraViewStopped() {
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
return inputFrame.rgba();
}
}
修改 protected void deliverAndDrawFrame(CvCameraViewFrame frame)函数为:
//新方法
Matrix matrix = new Matrix(); // I rotate it with minimal process
//matrix.preTranslate((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,(canvas.getHeight() - mCacheBitmap.getHeight()) / 2);
//matrix.postRotate(90f,(canvas.getWidth()) / 2,(canvas.getHeight()) / 2);
//float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
//matrix.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
//canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
if (getDisplay().getRotation() == Surface.ROTATION_0) {
matrix.preTranslate((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,(canvas.getHeight() - mCacheBitmap.getHeight()) / 2);
matrix.postRotate(90f,(canvas.getWidth()) / 2,(canvas.getHeight()) / 2);
float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
matrix.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
} else if (getDisplay().getRotation() == Surface.ROTATION_90) {
float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
matrix.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
} else if (getDisplay().getRotation() == Surface.ROTATION_180) {
matrix.preTranslate((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,(canvas.getHeight() - mCacheBitmap.getHeight()) / 2);
matrix.postRotate(270f,(canvas.getWidth()) / 2,(canvas.getHeight()) / 2);
float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
matrix.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
} else if (getDisplay().getRotation() == Surface.ROTATION_270) {
matrix.postRotate(180f,(canvas.getWidth()) / 2,(canvas.getHeight()) / 2);
float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
matrix.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
}
拍照
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:opencv="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<org.opencv.android.JavaCameraView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"
android:id="@+id/tutorial1_activity_java_surface_view"
opencv:show_fps="true"
opencv:camera_id="any" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom|center_horizontal">
<Button
android:id="@+id/deal_btn"
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_marginBottom="20dp"
android:text="拍照处理"/>
</RelativeLayout>
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.e.opcv">
<uses-permission android:name="android.permission.CAMERA" />
<!--摄像头-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--内部存储-->
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
package com.e.opcv;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;
import java.io.File;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class MainActivity extends CameraActivity implements CvCameraViewListener2{
private static final String TAG = "OCVSample::Activity";
//opencv接口标志
private CameraBridgeViewBase mOpenCvCameraView;
//缓存相机每帧输入的数据
private Mat mRgba;
private Button button;
private boolean mIsJavaCamera = true;
private MenuItem mItemSwitchCamera = null;
/**通过OpenCV管理Android服务,初始化OpenCV**/
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
public MainActivity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
if(msg.what == 1){
button.performClick();
}
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
// //初始化并设置预览部件
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
//拍照按键
button = (Button) findViewById(R.id.deal_btn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mRgba != null) {
if(!mRgba.empty()) {
Mat inter = new Mat(mRgba.width(), mRgba.height(), CvType.CV_8UC4);
Log.e("Mat","...............1...............");
//将四通道的RGBA转为三通道的BGR,重要!!
Imgproc.cvtColor(mRgba, inter, Imgproc.COLOR_RGBA2BGR);
Log.e("Mat","...............2...............");
File sdDir = null;
//判断是否存在机身内存
boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
if(sdCardExist) {
//获得机身储存根目录
sdDir = Environment.getExternalStorageDirectory();
Log.e("Mat","...............3...............");
}
//将拍摄准确时间作为文件名
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
String filename = sdf.format(new Date());
String savepath=sdDir + "/Pictures/OpenCV/";
File f=new File(savepath);
if(!f.exists()){
f.mkdirs();
}
String filePath = sdDir + "/Pictures/OpenCV/" + filename + ".png";
Log.e("Mat","..............."+filePath+"...............");
//将转化后的BGR矩阵内容写入到文件中
Imgcodecs.imwrite(filePath, inter);
Toast.makeText(MainActivity.this, "图片保存到: "+ filePath, Toast.LENGTH_SHORT).show();
}
}
}
});
// moveTaskToBack(true);
// new test().start();
}
private class test extends Thread{
@Override
public void run() {
super.run();
while (true){
try {
Thread.sleep(2000);
Log.e("begin","kaishi.........");
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}catch (Exception e){
Log.e("error",e.getMessage());
}
}
}
}
@Override
public void onPause()
{
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
public void onResume()
{
/***强制横屏***/
if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
//横屏后才加载部件,否则会FC
if(!OpenCVLoader.initDebug()) {
Log.d(TAG, "OpenCV library not found!");
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
super.onResume();
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
@Override
public List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
//对象实例化及基本属性的设置,包括长度、宽度和图像类型标志
public void onCameraViewStarted(int width, int height) {
Log.e("Mat","...............4...............");
mRgba = new Mat(height, width, CvType.CV_8UC4);
}
/**图像处理都写在这里!!!**/
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba(); //一定要有!!!不然数据保存不进MAT中!!!
//直接返回输入视频预览图的RGB数据并存放在Mat数据中
Log.e("Mat","...............5...............");
return mRgba;
// return inputFrame.rgba();
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
//结束时释放
public void onCameraViewStopped() {
Log.e("Mat","...............6...............");
mRgba.release();
// mTmp.release();
}
}
/***强制横屏***/
if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
//横屏后才加载部件,否则会FC
if(!OpenCVLoader.initDebug()) {
Log.d(TAG, "OpenCV library not found!");
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
package com.e.opcv;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
public class Main2Activity extends Activity implements SurfaceHolder.Callback, Camera.ShutterCallback, Camera.PictureCallback {
public static final String FILE_PATH = "filePath";
private Camera mCamera;
private SurfaceView mPreview;
private Button ibSnapPhoto, ibCancelPhoto;
private String pictureFilePath;
/**
* 外部调用接口
* @param context
* @param filePath 拍摄照片的存储地址
*/
public static void callMe(Context context, String filePath){
Intent intent = new Intent(context,Main2Activity.class);
intent.putExtra(FILE_PATH, filePath);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
//mPrevie为摄像机预览图层
mPreview = (SurfaceView) findViewById(R.id.surface_view);
mPreview.getHolder().addCallback(this);
mPreview.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
ibSnapPhoto = (Button) findViewById(R.id.snap_photo);
ibCancelPhoto = (Button) findViewById(R.id.cancel_photo);
ibSnapPhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onSnapPhoto();
}
});
ibCancelPhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onCancelPhoto();
}
});
pictureFilePath = getIntent().getStringExtra(FILE_PATH);
//开启Camera
mCamera = Camera.open();
}
@Override
protected void onPause() {
super.onPause();
mCamera.stopPreview();
}
@Override
protected void onDestroy() {
super.onDestroy();
mCamera.release();
}
/**
* 点击按钮拍照
*/
private void onSnapPhoto(){
//拍照
mCamera.takePicture(this, null, null, this);
}
/**
* 点击按钮取消
*/
private void onCancelPhoto(){
mCamera.stopPreview();
finish();
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
savePictureToFile(data, pictureFilePath);
} catch (IOException e) {
Log.d("wcj", "originalImage保存失败!");
e.printStackTrace();
}
//重新启动预览
mCamera.startPreview();
}
@Override
public void onShutter() {
Toast.makeText(Main2Activity.this, "click!", Toast.LENGTH_SHORT).show();
}
//以下为Surface三种回调方法
@Override
public void surfaceCreated(SurfaceHolder holder) {
//当surfaceView建立时,在上面绑定预览显示界面
try{
mCamera.setPreviewDisplay(mPreview.getHolder());
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
Camera.Size selectedSize =getBestSupportPreviewSize(sizes, getScreenSize());
//设定摄像机预览界面尺寸
params.setPreviewSize(selectedSize.width, selectedSize.height);
mCamera.setParameters(params);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
/**
* 保存照片到存储器
*
* @param data
* @param _file
* @throws IOException
*/
public static void savePictureToFile(byte[] data, String _file) throws IOException {
BufferedOutputStream os = null;
try {
File file = new File(_file);
// String _filePath_file.replace(File.separatorChar +
// file.getName(), "");
int end = _file.lastIndexOf(File.separator);
String _filePath = _file.substring(0, end);
File filePath = new File(_filePath);
if (!filePath.exists()) {
filePath.mkdirs();
}
file.createNewFile();
os = new BufferedOutputStream(new FileOutputStream(file));
os.write(data);
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 寻找最大的预览图片尺寸(与屏幕分辨率适配)
*
* @param previewSizes 所有支持的预览图片大小
* @return
*/
public static Camera.Size getBestSupportPreviewSize(List<Camera.Size> previewSizes, Camera.Size screenSize) {
double screenRatio = screenSize.width * 1.0 / screenSize.height;
Camera.Size maxSize = previewSizes.get(0);
for (Camera.Size size : previewSizes) {
double sizeRatio = size.width * 1.0 / size.height;
if (size.width < 2000 && sizeRatio > screenRatio - 0.1 && sizeRatio < screenRatio + 0.1)
maxSize = (size.width > maxSize.width) ? size : maxSize;
}
return maxSize;
}
private Camera.Size getScreenSize() {
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int width = metric.widthPixels; // 宽度(PX)
int height = metric.heightPixels; // 高度(PX)
return mCamera.new Size(height, width);
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/surface_view"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/snap_photo"
android:text="SNAP"
android:layout_alignParentBottom="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/cancel_photo"
android:text="CANCEL"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"/>
</RelativeLayout>
机器视觉应用