在android中用opencv实现拍照,存储照片的程序源代码


我用的是opencvforandroid2.4.6,调用opencv自己封装的类来实现拍照功能

程序具体流程如下所述:

先启动CameraActivity,,屏幕显示摄像头以及两个菜单,一个菜单可以转换摄像头,一个菜单拍照,,

当按下拍照菜单后会设置mIsPhotoPending 为true,此后程序自动调用onCameraFrame方法,因为mIsPhotoPending 为true所以可以在onCameraFrame方法中进行照片的保存等工作,由于保存照片很繁琐所以独立用了一个方法

takePhoto(),,在该方法中程序会跳转到LabActivity,该activity中有三个菜单,删除,编辑,分享,,可对拍摄好的照片进行这些操作。

下面是具体代码,,可以在手机(android4.2以上的系统上)实现


 
  
CameraActivity.java
package com.nummist.secondsight;


import java.io.File;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.NativeCameraView;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;

import com.nummist.secondsight.filters.Filter;
import com.nummist.secondsight.filters.NoneFilter;
import com.nummist.secondsight.filters.convolution.StrokeEdgesFilter;
import com.nummist.secondsight.filters.curve.CrossProcessCurveFilter;
import com.nummist.secondsight.filters.curve.PortraCurveFilter;
import com.nummist.secondsight.filters.curve.ProviaCurveFilter;
import com.nummist.secondsight.filters.curve.VelviaCurveFilter;
import com.nummist.secondsight.filters.mixer.RecolorCMVFilter;
import com.nummist.secondsight.filters.mixer.RecolorRCFilter;
import com.nummist.secondsight.filters.mixer.RecolorRGVFilter;


import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.Images;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

public class CameraActivity extends FragmentActivity
implements CvCameraViewListener2 {
// A tag for log output.
	//一个标记为日志输出
private static final String TAG = "MainActivity";
// A key for storing the index of the active camera.
//一个关键的,用于存储有效的照相机的索引。
private static final String STATE_CAMERA_INDEX = "cameraIndex";
// The index of the active camera.
//活动摄像头的索引
private int mCameraIndex;
// Whether the active camera is front-facing.
//活动相机是前置
// If so, the camera view should be mirrored.
//如果是这样,相机视图要显示
private boolean mIsCameraFrontFacing;
// The number of cameras on the device.
//这个数表示设备上相机的数量
private int mNumCameras;
// The camera view.
private CameraBridgeViewBase mCameraView;
// Whether the next camera frame should be saved as a photo.
//无论下一相机框架是哪一个都应该保存照片
private boolean mIsPhotoPending;
// A matrix that is used when saving photos.
//一个矩阵是用于保存照片的
private Mat mBgr;
//Whether an asynchronous menu action is in progress.
//If so, menu interaction should be disabled.
//如果一个菜单在进行,菜单交互应该被禁止
private boolean mIsMenuLocked;

//The OpenCV loader callback.
//Opencv 程序回调
private BaseLoaderCallback mLoaderCallback =
new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(final int status) {
   switch (status) {
     case LoaderCallbackInterface.SUCCESS:
     Log.d(TAG, "OpenCV loaded successfully");
     mCameraView.enableView();
     mBgr = new Mat();
   
     break;
     default:
     super.onManagerConnected(status);
     break;
  }
}
};
@SuppressLint("NewApi")
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Window window = getWindow();
window.addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (savedInstanceState != null) {
mCameraIndex = savedInstanceState.getInt(
STATE_CAMERA_INDEX, 0);

} else {
mCameraIndex = 0;
mCurveFilterIndex = 0;
mMixerFilterIndex = 0;
mConvolutionFilterIndex = 0;
}
if (Build.VERSION.SDK_INT >=
Build.VERSION_CODES.GINGERBREAD) {
CameraInfo cameraInfo = new CameraInfo();
Camera.getCameraInfo(mCameraIndex, cameraInfo);
mIsCameraFrontFacing =
(cameraInfo.facing ==
CameraInfo.CAMERA_FACING_FRONT);
mNumCameras = Camera.getNumberOfCameras();
} else { // pre-Gingerbread
// Assume there is only 1 camera and it is rear-facing.
mIsCameraFrontFacing = false;
mNumCameras = 1;
}
mCameraView = new NativeCameraView(this, mCameraIndex);
mCameraView.setCvCameraViewListener(this);
setContentView(mCameraView);
}
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the current camera index.
savedInstanceState.putInt(STATE_CAMERA_INDEX, mCameraIndex);
savedInstanceState.putInt(STATE_CURVE_FILTER_INDEX,
mCurveFilterIndex);
savedInstanceState.putInt(STATE_MIXER_FILTER_INDEX,
mMixerFilterIndex);
savedInstanceState.putInt(STATE_CONVOLUTION_FILTER_INDEX,
mConvolutionFilterIndex);
super.onSaveInstanceState(savedInstanceState);
}
@Override
public void onPause() {
if (mCameraView != null) {
mCameraView.disableView();
}
super.onPause();
}
@Override
public void onResume() {
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3,
this, mLoaderCallback);
mIsMenuLocked = false;
}
@Override
public void onDestroy() {
super.onDestroy();
if (mCameraView != null) {
mCameraView.disableView();
}
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.activity_camera, menu);
if (mNumCameras < 2) {
// Remove the option to switch cameras, since there is
// only 1.
menu.removeItem(R.id.menu_next_camera);
}
return true;
}

@SuppressLint("NewApi")
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
if (mIsMenuLocked) {
return true;
}
switch (item.getItemId()) {
case R.id.menu_next_curve_filter:
	mCurveFilterIndex++;
	if (mCurveFilterIndex == mCurveFilters.length) {
	mCurveFilterIndex = 0;
	}
	return true;
	case R.id.menu_next_mixer_filter:
	mMixerFilterIndex++;
	if (mMixerFilterIndex == mMixerFilters.length) {
	mMixerFilterIndex = 0;
	}
	return true;
	case R.id.menu_next_convolution_filter:
	mConvolutionFilterIndex++;
	if (mConvolutionFilterIndex ==
	mConvolutionFilters.length) {
	mConvolutionFilterIndex = 0;
	}
	return true;
case R.id.menu_next_camera:
mIsMenuLocked = true;
// With another camera index, recreate the activity.
//另一个相机索引,重新创建活动
mCameraIndex++;
if (mCameraIndex == mNumCameras) {
mCameraIndex = 0;
}
recreate();
return true;
case R.id.menu_take_photo:
mIsMenuLocked = true;
// Next frame, take the photo.
//
mIsPhotoPending = true;
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void takePhoto(final Mat rgba) {
	// Determine the path and metadata for the photo.
	//确定路径和照片元数据
	final long currentTimeMillis = System.currentTimeMillis();
	final String appName = getString(R.string.app_name);
	final String galleryPath =
	Environment.getExternalStoragePublicDirectory(
	Environment.DIRECTORY_PICTURES).toString();
	final String albumPath = galleryPath + "/" + appName;
	final String photoPath = albumPath + "/" +
	currentTimeMillis + ".png";
	final ContentValues values = new ContentValues();
	values.put(MediaStore.MediaColumns.DATA, photoPath);
	values.put(Images.Media.MIME_TYPE,
	LabActivity.PHOTO_MIME_TYPE);
	values.put(Images.Media.TITLE, appName);
	values.put(Images.Media.DESCRIPTION, appName);
	values.put(Images.Media.DATE_TAKEN, currentTimeMillis);
	// Ensure that the album directory exists.
	//确保相片目录存在
	File album = new File(albumPath);
	if (!album.isDirectory() && !album.mkdirs()) {
	Log.e(TAG, "Failed to create album directory at " +
	albumPath);
	onTakePhotoFailed();
	return;
	}
	// Try to create the photo.
	//尝试创建照片
	Imgproc.cvtColor(rgba, mBgr, Imgproc.COLOR_RGBA2BGR, 3);
	if (!Highgui.imwrite(photoPath, mBgr)) {
	Log.e(TAG, "Failed to save photo to " + photoPath);//图片没有保存到
	onTakePhotoFailed();
	}
	Log.d(TAG, "Photo saved successfully to " + photoPath);//图片保存成功
	// Try to insert the photo into the MediaStore.
	//尝试插入图片到MediaStore
	Uri uri;
	try {
		uri = getContentResolver().insert(
		Images.Media.EXTERNAL_CONTENT_URI, values);
		} catch (final Exception e) {
		Log.e(TAG, "Failed to insert photo into MediaStore");//无法插入图像到MediaStore
		e.printStackTrace();
		// Since the insertion failed, delete the photo.
		//由于插入失败,删除图片
		File photo = new File(photoPath);
		if (!photo.delete()) {
		Log.e(TAG, "Failed to delete non-inserted photo");
		}
		onTakePhotoFailed();
		return;
		}
		// Open the photo in LabActivity.
	//打开照片在LabActivity
		final Intent intent = new Intent(this, LabActivity.class);
		intent.putExtra(LabActivity.EXTRA_PHOTO_URI, uri);
		intent.putExtra(LabActivity.EXTRA_PHOTO_DATA_PATH,
		photoPath);
		startActivity(intent);
		}
		private void onTakePhotoFailed() {
		mIsMenuLocked = false;
		// Show an error message.
		// 显示一个错误消息
		final String errorMessage =
		getString(R.string.photo_error_message);
		runOnUiThread(new Runnable() {
		@Override
		public void run() {
		Toast.makeText(CameraActivity.this, errorMessage,
		Toast.LENGTH_SHORT).show();
		}
		});
		
		}
		
@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) {
	final Mat rgba = inputFrame.rgba();
	if (mIsPhotoPending) {
	mIsPhotoPending = false;
	takePhoto(rgba);
	}
	if (mIsCameraFrontFacing) {
	// Mirror (horizontally flip) the preview.
	Core.flip(rgba, rgba, 1);
	}
	return rgba;
}
}

LabActivity.java

package com.nummist.secondsight;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.Images;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;

public class LabActivity extends Activity {
public static final String PHOTO_MIME_TYPE = "image/png";
public static final String EXTRA_PHOTO_URI =
"com.nummist.secondsight.LabActivity.extra.PHOTO_URI";
public static final String EXTRA_PHOTO_DATA_PATH =
"com.nummist.secondsight.LabActivity.extra.PHOTO_DATA_PATH";
private Uri mUri;
private String mDataPath;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
mUri = intent.getParcelableExtra(EXTRA_PHOTO_URI);
mDataPath = intent.getStringExtra(EXTRA_PHOTO_DATA_PATH);
final ImageView imageView = new ImageView(this);
imageView.setImageURI(mUri);
setContentView(imageView);
}

@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.activity_lab, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_delete:
deletePhoto();
return true;
case R.id.menu_edit:
editPhoto();
return true;
case R.id.menu_share:
sharePhoto();
return true;
default:
return super.onOptionsItemSelected(item);
}
}

private void deletePhoto() {
final AlertDialog.Builder alert = new AlertDialog.Builder(
LabActivity.this);
alert.setTitle(R.string.photo_delete_prompt_title);
alert.setMessage(R.string.photo_delete_prompt_message);
alert.setCancelable(false);//按返回键不能退出
alert.setPositiveButton(R.string.delete,
new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog,
final int which) {
getContentResolver().delete(
Images.Media.EXTERNAL_CONTENT_URI,
MediaStore.MediaColumns.DATA + "=?",
new String[] { mDataPath });
finish();
}
});
alert.setNegativeButton(android.R.string.cancel, null);
alert.show();
}
private void editPhoto() {
final Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setDataAndType(mUri, PHOTO_MIME_TYPE);
startActivity(Intent.createChooser(intent,
getString(R.string.photo_edit_chooser_title)));
}
private void sharePhoto() {
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType(PHOTO_MIME_TYPE);
intent.putExtra(Intent.EXTRA_STREAM, mUri);
intent.putExtra(Intent.EXTRA_SUBJECT,
getString(R.string.photo_send_extra_subject));
intent.putExtra(Intent.EXTRA_TEXT,
getString(R.string.photo_send_extra_text));
startActivity(Intent.createChooser(intent,
getString(R.string.photo_send_chooser_title)));
}
}

layout\\gg.xml


    


 
  
menu\\activity_camera.xml

 
   




menu\\activi_lab.xml

 
  
menu\\activi_lab.xml





配置文件的代码




    





    
        
            
                


                
            
        
        

    



 
  
 
  

你可能感兴趣的:(opencv,for,android)