简介
简而言之,就是在之前的最初基本布局,继续完善了camera前后摄切换、闪光灯开关,以及添加了边缘预览模式,以及预览分辨率设置功能。
边缘模式
原理讲解
简单的说,就是利用ndk,使用opencv集成的Canny功能,对预览图像做边缘检测,然后将这个检测结果当做预览图像显示出来。
代码讲解
1、首先是从setting界面的FirstPopupWindowView窗口,选择进入的预览模式中加上一个选项:边缘模式。
com.example.camera_opencv_android.MyVariable
public String[] firstMenu = { "预览模式", "分辨率"};
public String[] priviewMenu = {"普通模式", "灰阶模式", "边缘模式"};
2、接着在预览模式选择函数:initPreviewPopupWindowView中,加上边缘模式选项对应的操作
com.example.camera_opencv_android.MainActivity
previewListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
if(arg2==0){
myVariable.previewFlag = 0;
}else if(arg2 == 1){
myVariable.previewFlag = 1;
}else if(arg2 == 2){
myVariable.previewFlag = 2;
}
if (myVariable.previewPopupwindow != null && myVariable.previewPopupwindow.isShowing()) {
myVariable.previewPopupwindow.dismiss();
myVariable.previewPopupwindow = null;
}
}
});
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
// TODO Auto-generated method stub
myVariable.mRgba = inputFrame.rgba();
if(myVariable.previewFlag==0){
}else if(myVariable.previewFlag == 1){
PreviceGray.grayProc(myVariable.mRgba.getNativeObjAddr());
}else if(myVariable.previewFlag == 2){
PreviceGray.canny(myVariable.mRgba.getNativeObjAddr());
}
.............
}
通过对previewFlag的设置,来选择预览模式:
(1)、previewFlag为0表示正常预览;
(2)、previewFlag为1表示灰阶预览;
(3)、previewFlag为1表示边缘预览;
对应的ndk里面图像处理函数,在PreviceGray.cpp中。
效果演示
效果截图如下:
(图一) (图二)
闪光灯开关
1、在上一篇初始化界面控件函数mainInit中,设置了闪光灯开关的控件ID为2,所以对应的函数操作如下:
@Override public void onClick(View v) { ............ }else if(v.getId() == 2){ if(myVariable.myFlashLight == 0){ myVariable.mOpenCvCameraView.setFlashMode(MainActivity.this, 4); myVariable.myFlashLight = 1; }else{ myVariable.mOpenCvCameraView.setFlashMode(MainActivity.this, 1); myVariable.myFlashLight = 0; } }
当被点击的控件ID为2的时候,检查当前闪光灯状态,如果是enable则关闭闪光灯;如果是关闭,则开启闪光灯。
对闪光灯真正的操作函数为:setFlashMode。
com.example.camera_opencv_android.WTCamera
public void setFlashMode (Context item, int type){
Camera.Parameters params = mCamera.getParameters();
List<String> FlashModes = params.getSupportedFlashModes();
switch (type){
case 0:
if (FlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO))
params.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
else
Toast.makeText(item, "Auto Mode not supported", Toast.LENGTH_SHORT).show();
break;
case 1:
if (FlashModes.contains(Camera.Parameters.FLASH_MODE_OFF))
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
else
Toast.makeText(item, "Off Mode not supported", Toast.LENGTH_SHORT).show();
break;
case 2:
if (FlashModes.contains(Camera.Parameters.FLASH_MODE_ON))
params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
else
Toast.makeText(item, "On Mode not supported", Toast.LENGTH_SHORT).show();
break;
case 3:
if (FlashModes.contains(Camera.Parameters.FLASH_MODE_RED_EYE))
params.setFlashMode(Camera.Parameters.FLASH_MODE_RED_EYE);
else
Toast.makeText(item, "Red Eye Mode not supported", Toast.LENGTH_SHORT).show();
break;
case 4:
if (FlashModes.contains(Camera.Parameters.FLASH_MODE_TORCH))
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
else
Toast.makeText(item, "Torch Mode not supported", Toast.LENGTH_SHORT).show();
break;
}
mCamera.setParameters(params);
}
分辨率设置
具体代码
1、这里是在setting选项中,除了之前选项:预览模式之外,新加入选项:分辨率,对应操作函数如下:
private void initFirstPopupWindowView(View v) { firstListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) { if(arg2==0){ initPreviewPopupWindowView(); }else if(arg2 == 1){ initResolutionPopupWindowView(); } } }); private void resolutionChange(){ if(myVariable.myCameraID == 0){ myVariable.myDisplayOrientation = -1; }else{ myVariable.myDisplayOrientation = 2; } myVariable.mOpenCvCameraView.setResolution(myVariable.s, myVariable.myCameraID); } private void initResolutionPopupWindowView() { resolutionListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) { if(arg2==0){ myVariable.s.height=1080; myVariable.s.width=1920; resolutionChange(); }else if(arg2 == 1){ myVariable.s.height=960; myVariable.s.width=1280; resolutionChange(); }else if(arg2 == 2){ myVariable.s.height=720; myVariable.s.width=1280; resolutionChange(); }else if(arg2 == 3){ myVariable.s.height=480; myVariable.s.width=864; resolutionChange(); }else if(arg2 == 4){ myVariable.s.height=480; myVariable.s.width=720; resolutionChange(); }else if(arg2 == 5){ myVariable.s.height=360; myVariable.s.width=480; resolutionChange(); } ............ } });
在分辨率选择窗口中,根据不同选择,来设置不同的分辨率到结构myVariable.s中。接着在resolutionChange中,利用setResolution进行具体的解析力
设置。
com.example.camera_opencv_android.WTCamera
public void setResolution(Camera.Size resolution, int cameraID) {
disconnectCamera();
myConnectCamera((int)resolution.width, (int)resolution.height, cameraID);
}
这里需要稍微改动下Opencv库中的代码:
org.opencv.android.JavaCameraView
protected boolean initializeCamera(int width, int height, int cameraID) {
..........
try {
mCamera = Camera.open(cameraID);
}
}
@Override
protected boolean connectCamera(int width, int height) {
.............
if (!initializeCamera(width, height, 0))
return false;
.............
}
@Override
protected boolean myConnectCamera(int width, int height, int cameraID) {
/* 1. We need to instantiate camera
* 2. We need to start thread which will be getting frames
*/
/* First step - initialize camera connection */
Log.d(TAG, "Connecting to camera");
if (!initializeCamera(width, height, cameraID))
return false;
mCameraFrameReady = false;
/* now we can start update thread */
Log.d(TAG, "Starting processing thread");
mStopThread = false;
mThread = new Thread(new CameraWorker());
mThread.start();
return true;
}
在connectCamera调用的函数initializeCamera中,加上了初始化cameraId的参数,另外新写了一个函数myConnectCamera,该函数在
connectCamera基础上,加上了前后摄camera的选择操作。主要是为了方便之后的camera前后摄切换功能。
效果演示
效果截图如下:
(图三) (图四)
前后摄切换
和闪光灯开关类似,camera切换控件ID为3。对应操作代码如下:
public void onClick(View v) { // TODO Auto-generated method stub if(v.getId() == 1){ initFirstPopupWindowView(v); }else if(v.getId() == 3){ if(myVariable.myCameraID == 0){ myVariable.s.height=960; myVariable.s.width=1280; myVariable.myDisplayOrientation = 2; myVariable.mOpenCvCameraView.changeCamera(myVariable.s, 1); myVariable.myCameraID = 1; }else{ myVariable.s.height=1080; myVariable.s.width=1920; myVariable.myDisplayOrientation = -1; myVariable.mOpenCvCameraView.changeCamera(myVariable.s, 0); myVariable.myCameraID = 0; } }
com.example.camera_opencv_android.WTCamera
public void changeCamera(Camera.Size resolution, int cameraID){ disconnectCamera(); myConnectCamera((int)resolution.width, (int)resolution.height, cameraID); }
从代码中可以看到,点击camera切换控件之后,首先检查当前使用的camera设备:myCameraID,为0表示为后摄,为1表示为前摄。然后修改myCameraID值,表示进行了切换,接着从新设置了camera的分辨率。最后通过函数changeCamera来调用myConnectCamera,最终进行了分辨率和camera的切换。
函数myConnectCamera,已经在之前分辨率设置功能中,做了讲解。
具体演示下载:http://download.csdn.net/detail/u011630458/9261617