[Android编程心得] Camera(OpenCV)自动对焦和触摸对焦的实现
生活随笔
收集整理的這篇文章主要介紹了
[Android编程心得] Camera(OpenCV)自动对焦和触摸对焦的实现
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
http://blog.csdn.net/candycat1992/article/details/21617741
實(shí)現(xiàn)
以O(shè)penCV的JavaCameraView為例,首先需要定制自己的Camera,主要代碼如下: [java]?view plaincopy print?- import?java.util.ArrayList;??
- import?java.util.List;??
- ??
- import?org.opencv.android.JavaCameraView;??
- ??
- import?android.R.integer;??
- import?android.content.Context;??
- import?android.graphics.Rect;??
- import?android.graphics.RectF;??
- import?android.hardware.Camera;??
- import?android.hardware.Camera.AutoFocusCallback;??
- import?android.util.AttributeSet;??
- import?android.view.MotionEvent;??
- import?android.widget.Toast;??
- ??
- public?class?MTCameraView?extends?JavaCameraView?implements?AutoFocusCallback?{??
- ??
- ????public?MTCameraView(Context?context,?int?attrs)?{??
- ????????super(context,?attrs);??
- ????????//?TODO?Auto-generated?constructor?stub??
- ????}??
- ??
- ????public?List<Camera.Size>?getResolutionList()?{????????
- ????????return??mCamera.getParameters().getSupportedPreviewSizes();????????
- ????}??
- ??????
- ????public?Camera.Size?getResolution()?{??
- ????????Camera.Parameters?params?=?mCamera.getParameters();???
- ????????Camera.Size?s?=?params.getPreviewSize();??
- ????????return?s;??
- ????}??
- ??????
- ????public?void?setResolution(Camera.Size?resolution)?{??
- ????????disconnectCamera();??
- ????????connectCamera((int)resolution.width,?(int)resolution.height);?????????
- ????}??
- ??????
- ????public?void?focusOnTouch(MotionEvent?event)?{??
- ????????Rect?focusRect?=?calculateTapArea(event.getRawX(),?event.getRawY(),?1f);??
- ????????Rect?meteringRect?=?calculateTapArea(event.getRawX(),?event.getRawY(),?1.5f);??
- ??
- ????????Camera.Parameters?parameters?=?mCamera.getParameters();??
- ????????parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);??
- ??????????
- ????????if?(parameters.getMaxNumFocusAreas()?>?0)?{??
- ????????????List<Camera.Area>?focusAreas?=?new?ArrayList<Camera.Area>();??
- ????????????focusAreas.add(new?Camera.Area(focusRect,?1000));??
- ??????????
- ????????????parameters.setFocusAreas(focusAreas);??
- ????????}??
- ??
- ????????if?(parameters.getMaxNumMeteringAreas()?>?0)?{??
- ????????????List<Camera.Area>?meteringAreas?=?new?ArrayList<Camera.Area>();??
- ????????????meteringAreas.add(new?Camera.Area(meteringRect,?1000));??
- ??????????????
- ????????????parameters.setMeteringAreas(meteringAreas);??
- ????????}??
- ??
- ????????mCamera.setParameters(parameters);??
- ????????mCamera.autoFocus(this);??
- ????}??
- ??????
- ????/**?
- ?????*?Convert?touch?position?x:y?to?{@link?Camera.Area}?position?-1000:-1000?to?1000:1000.?
- ?????*/??
- ????private?Rect?calculateTapArea(float?x,?float?y,?float?coefficient)?{??
- ????????float?focusAreaSize?=?300;??
- ????????int?areaSize?=?Float.valueOf(focusAreaSize?*?coefficient).intValue();??
- ??
- ????????int?centerX?=?(int)?(x?/?getResolution().width?*?2000?-?1000);??
- ????????int?centerY?=?(int)?(y?/?getResolution().height?*?2000?-?1000);??
- ??
- ????????int?left?=?clamp(centerX?-?areaSize?/?2,?-1000,?1000);??
- ????????int?right?=?clamp(left?+?areaSize,?-1000,?1000);??
- ????????int?top?=?clamp(centerY?-?areaSize?/?2,?-1000,?1000);??
- ????????int?bottom?=?clamp(top?+?areaSize,?-1000,?1000);??
- ??
- ????????return?new?Rect(left,?top,?right,?bottom);??
- ????????}??
- ??
- ????private?int?clamp(int?x,?int?min,?int?max)?{??
- ????????if?(x?>?max)?{??
- ????????????return?max;??
- ????????}??
- ????????if?(x?<?min)?{??
- ????????????return?min;??
- ????????}??
- ????????return?x;??
- ????}??
- ??????
- ????public?void?setFocusMode?(Context?item,?int?type){??
- ????????Camera.Parameters?params?=?mCamera.getParameters();???
- ????????List<String>?FocusModes?=?params.getSupportedFocusModes();??
- ??
- ????????switch?(type){??
- ????????case?0:??
- ????????????if?(FocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))??
- ????????????????params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);??
- ????????????else???
- ????????????????Toast.makeText(item,?"Auto?Mode?not?supported",?Toast.LENGTH_SHORT).show();??
- ????????????break;??
- ????????case?1:???????????
- ????????????if?(FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))??
- ????????????????params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);??
- ????????????else??
- ????????????????Toast.makeText(item,?"Continuous?Mode?not?supported",?Toast.LENGTH_SHORT).show();??
- ????????????break;??
- ????????case?2:???????????
- ????????????if?(FocusModes.contains(Camera.Parameters.FOCUS_MODE_EDOF))??
- ????????????????params.setFocusMode(Camera.Parameters.FOCUS_MODE_EDOF);??
- ????????????else??
- ????????????????Toast.makeText(item,?"EDOF?Mode?not?supported",?Toast.LENGTH_SHORT).show();??
- ????????????break;??
- ????????case?3:??
- ????????????if?(FocusModes.contains(Camera.Parameters.FOCUS_MODE_FIXED))??
- ????????????????params.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);??
- ????????????else??
- ????????????????Toast.makeText(item,?"Fixed?Mode?not?supported",?Toast.LENGTH_SHORT).show();??
- ????????????break;??
- ????????case?4:??
- ????????????if?(FocusModes.contains(Camera.Parameters.FOCUS_MODE_INFINITY))??
- ????????????????params.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);??
- ????????????else??
- ????????????????Toast.makeText(item,?"Infinity?Mode?not?supported",?Toast.LENGTH_SHORT).show();??
- ????????????break;??
- ????????case?5:??
- ????????????if?(FocusModes.contains(Camera.Parameters.FOCUS_MODE_MACRO))??
- ????????????????params.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);??
- ????????????else??
- ????????????????Toast.makeText(item,?"Macro?Mode?not?supported",?Toast.LENGTH_SHORT).show();??
- ????????????break;????????
- ????????}??
- ??
- ????????mCamera.setParameters(params);??
- ????}??
- ??????
- ????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);??
- ????}??
- ??
- ????@Override??
- ????public?void?onAutoFocus(boolean?arg0,?Camera?arg1)?{??
- ???????????
- ????}??
- }??
在MainActivity中需要初始化MTCamera,并且實(shí)現(xiàn)OnTouchListener接口,以便在觸摸屏幕時(shí)可以調(diào)用onTouch函數(shù)。其中主要代碼如下: [java]?view plaincopy print?
- private?MTCameraView?mOpenCvCameraView;??
- ??
- public?void?init()?{??
- ????mOpenCvCameraView?=?new?MTCameraView(this,?-1);??
- ????mOpenCvCameraView.setCvCameraViewListener(this);??
- ????mOpenCvCameraView.setFocusable(true);??
- ????mOpenCvCameraView.setOnTouchListener(MainActivity.this);??
- ????mOpenCvCameraView.enableView();??
- ??????
- ????FrameLayout?frame?=?new?FrameLayout(this);??
- ????frame.addView(mOpenCvCameraView);??
- ??????
- ????setContentView(frame);??
- ?????}??
- ??
- @Override??
- public?boolean?onTouch(View?arg0,?MotionEvent?arg1)?{??
- ????//?TODO?Auto-generated?method?stub??
- ????mOpenCvCameraView.focusOnTouch(arg1);??
- ????return?true;??
- }??
init()函數(shù)是自定義的初始化函數(shù),可以在onCreate時(shí)使用。由于這里需要使用OpenCV庫,所以本項(xiàng)目是在加載完OpenCV庫并判斷成功后才調(diào)用init()函數(shù)的。
解釋
在發(fā)生觸摸事件時(shí),MainActivity由于實(shí)現(xiàn)了OnTouchListener接口,因此會(huì)調(diào)用重寫的onTouch函數(shù),并把它的第二個(gè)參數(shù)MotionEvent傳遞給MTCamera,以便定位觸摸位置。 MTCamera的focusOnTouch函數(shù)繼續(xù)工作。它首先根據(jù)觸摸位置計(jì)算對(duì)焦和測(cè)光(metering)區(qū)域的大小(通過calculateTapArea函數(shù)),然后創(chuàng)建新的Camera.Parameters,并設(shè)置攝像機(jī)的對(duì)焦模式為Auto。 然后,它分別判斷該設(shè)備的相機(jī)是否支持設(shè)置對(duì)焦區(qū)域和測(cè)光區(qū)域,如果支持就分別為parameters設(shè)置之前計(jì)算好的聚焦和測(cè)光區(qū)域。 最后,讓Camera自動(dòng)對(duì)焦。- calculateTapArea函數(shù)
這個(gè)函數(shù)主要實(shí)現(xiàn)從屏幕坐標(biāo)系到對(duì)焦坐標(biāo)系的轉(zhuǎn)換。由MotionEvent.getRowX()得到的是以屏幕坐標(biāo)系(即屏幕左上角為原點(diǎn),右下角為你的當(dāng)前屏幕分辨率,單位是一個(gè)像素)為準(zhǔn)的坐標(biāo),而setFocusAreas接受的List<Area>中的每一個(gè)Area的范圍是(-1000,-1000)到(1000, 1000),也就是說屏幕中心為原點(diǎn),左上角為(-1000,-1000),右下角為(1000,1000)。注意,如果超出這個(gè)范圍的話,會(huì)報(bào)setParemeters failed的錯(cuò)誤哦!除此之外,我們還提前定義了一個(gè)對(duì)焦框(測(cè)光框)的大小,并且接受一個(gè)參數(shù)(第三個(gè)參數(shù)coefficient)作為百分比進(jìn)行調(diào)節(jié)。
- private?List<Camera.Size>?mResolutionList;??
- ??
- private?MenuItem[]?mResolutionMenuItems;??
- private?MenuItem[]?mFocusListItems;??
- private?MenuItem[]?mFlashListItems;??
- ??
- private?SubMenu?mResolutionMenu;??
- private?SubMenu?mFocusMenu;??
- private?SubMenu?mFlashMenu;??
- ??
- @Override??
- public?boolean?onCreateOptionsMenu(Menu?menu)?{??
- ????Log.i(TAG,?"called?onCreateOptionsMenu");??
- ??????
- ????List<String>?mFocusList?=?new?LinkedList<String>();??
- ?int?idx?=0;??
- ??
- ?mFocusMenu?=?menu.addSubMenu("Focus");??
- ??
- ?mFocusList.add("Auto");??
- ?mFocusList.add("Continuous?Video");??
- ?mFocusList.add("EDOF");??
- ?mFocusList.add("Fixed");??
- ?mFocusList.add("Infinity");??
- ?mFocusList.add("Makro");??
- ?mFocusList.add("Continuous?Picture");??
- ??
- ?mFocusListItems?=?new?MenuItem[mFocusList.size()];??
- ??
- ?ListIterator<String>?FocusItr?=?mFocusList.listIterator();??
- ?while(FocusItr.hasNext()){??
- ?????//?add?the?element?to?the?mDetectorMenu?submenu??
- ?????String?element?=?FocusItr.next();??
- ?????mFocusListItems[idx]?=?mFocusMenu.add(2,idx,Menu.NONE,element);??
- ?????idx++;??
- ?}??
- ??
- ?List<String>?mFlashList?=?new?LinkedList<String>();??
- ?idx?=?0;??
- ??
- ?mFlashMenu?=?menu.addSubMenu("Flash");??
- ??
- ?mFlashList.add("Auto");??
- ?mFlashList.add("Off");??
- ?mFlashList.add("On");??
- ?mFlashList.add("Red-Eye");??
- ?mFlashList.add("Torch");??
- ??
- ?mFlashListItems?=?new?MenuItem[mFlashList.size()];??
- ??
- ?ListIterator<String>?FlashItr?=?mFlashList.listIterator();??
- ?while(FlashItr.hasNext()){??
- ?????//?add?the?element?to?the?mDetectorMenu?submenu??
- ?????String?element?=?FlashItr.next();??
- ?????mFlashListItems[idx]?=?mFlashMenu.add(3,idx,Menu.NONE,element);??
- ?????idx++;??
- ?}??
- ??
- ?mResolutionMenu?=?menu.addSubMenu("Resolution");??
- ?mResolutionList?=?mOpenCvCameraView.getResolutionList();??
- ?mResolutionMenuItems?=?new?MenuItem[mResolutionList.size()];??
- ??
- ?ListIterator<Camera.Size>?resolutionItr?=?mResolutionList.listIterator();??
- ?idx?=?0;??
- ?while(resolutionItr.hasNext())?{??
- ?????Camera.Size?element?=?resolutionItr.next();??
- ?????mResolutionMenuItems[idx]?=?mResolutionMenu.add(1,?idx,?Menu.NONE,??
- ?????????????Integer.valueOf((int)?element.width).toString()?+?"x"?+?Integer.valueOf((int)?element.height).toString());??
- ?????idx++;??
- ??}??
- ??
- ?return?true;??
- }??
- ??
- public?boolean?onOptionsItemSelected(MenuItem?item)?{??
- ????Log.i(TAG,?"called?onOptionsItemSelected;?selected?item:?"?+?item);??
- ??
- ????if?(item.getGroupId()?==?1)??
- ?{??
- ?????int?id?=?item.getItemId();??
- ?????Camera.Size?resolution?=?mResolutionList.get(id);??
- ?????mOpenCvCameraView.setResolution(resolution);??
- ?????resolution?=?mOpenCvCameraView.getResolution();??
- ?????String?caption?=?Integer.valueOf((int)?resolution.width).toString()?+?"x"?+?Integer.valueOf((int)?resolution.height).toString();??
- ?????Toast.makeText(this,?caption,?Toast.LENGTH_SHORT).show();??
- ?}???
- ?else?if?(item.getGroupId()==2){??
- ??
- ????int?focusType?=?item.getItemId();??
- ??
- ????mOpenCvCameraView.setFocusMode(this,?focusType);??
- ?}??
- ?else?if?(item.getGroupId()==3){??
- ??
- ????int?flashType?=?item.getItemId();??
- ??
- ????mOpenCvCameraView.setFlashMode(this,?flashType);??
- ?}??
- ??
- ????return?true;??
- }??
這樣運(yùn)行后,點(diǎn)擊菜單就可以看見有三個(gè)菜籃列表:Focus(對(duì)焦模式),Flash(視頻模式),Resolution(支持的分辨率)。對(duì)焦模式和視頻模式中提供了幾種常見的模式供選擇,代碼會(huì)判斷當(dāng)前設(shè)備是否支持該模式。而分辨率菜單欄會(huì)顯示出當(dāng)前設(shè)備支持的所有分辨率種類。
參考
- StackOverFlow上關(guān)于觸摸對(duì)焦的討論
- Android多媒體和相機(jī)講解十
- 解讀Android 4.0 Camera原生應(yīng)用程序的設(shè)計(jì)思路
- OpenCV上的提問:ANDROID: Use autofocus with CameraBridgeViewBase?
轉(zhuǎn)載于:https://www.cnblogs.com/jukan/p/6857881.html
總結(jié)
以上是生活随笔為你收集整理的[Android编程心得] Camera(OpenCV)自动对焦和触摸对焦的实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个qq男生两字网名
- 下一篇: 数据库删除,存储