基于opencv的相机之最初布局(一)

简介

  学了opencv之后,一直在考虑结合自己方面,用它做点什么实际的东西。最后决定在Android opencv基础上,使用ndk,做一个相机、图片处理相关的
应用,应用很简陋,还在不断完善中。

效果演示

效果截图

                  
                      (图一)                                    (图二)


                  
                      (图三)                                    (图四)

操作讲解

  1、打开应用之后,进入图一界面,然后对应操作按钮分别有四个:(1)、camera切换 
                                                               (2)、闪光灯开关
                                                               (3)、setting选项按钮 
                                                               (4)、拍照按钮
    2、按下这些按钮时候,对应按钮图片会亮度变暗来作为提示。
    3、按下setting按钮之后,会弹出到图二界面上的选项框。
    4、继续点击选项:预览模式,可以进入到图三中,这里有两个选项:普通预览模式和灰阶预览模式。选择了灰阶模式之后,camera的预览界面将如图四
所示,预览界面图像会被灰阶化。
    5、点击拍照按钮,会拍摄照片,照片保存到/sdcard/mycamera目录下。

代码讲解

在开始讲解之前,请先看如下文档:
     1、opencv在android上预览的最小代码模块(2)
     2、opencv各种小功能记录总结 这一篇中的:不安装manager使用opencv库
     3、同时这里还借鉴了如下Blog:http://blog.csdn.net/candycat1992/article/details/21617741/

初始化布局

  1、做了一些界面初始化操作、获得屏幕尺寸等初始化操作。
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        
        WindowManager wm = this.getWindowManager();
        myVariable.screenWidth= wm.getDefaultDisplay().getWidth();
        myVariable.screenHeight = wm.getDefaultDisplay().getHeight();
        myVariable.mOpenCvCameraView = new WTCamera(this, -1);
        myVariable.mOpenCvCameraView.setCvCameraViewListener(this);
        myVariable.mOpenCvCameraView.setFocusable(true);   
        mainInit();
    }
    2、在mainInit中,画出了界面布局已经控件的相关设置。
private void mainInit(){	    
            LinearLayout frame = new LinearLayout(this);
            frame.setOrientation(LinearLayout.HORIZONTAL);
	    myVariable.mainToplinearLayout = new LinearLayout(this);
	    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(myVariable.screenWidth / 14, LayoutParams.MATCH_PARENT, 1);
	    myVariable.mainToplinearLayout.setLayoutParams(lp);
	    myVariable.mainToplinearLayout.setBackgroundColor(Color.BLACK);
	    myVariable.mainToplinearLayout.setOrientation(LinearLayout.VERTICAL);
	    
	    myVariable.mainBottomlinearLayout = new LinearLayout(this);
	    lp = new LinearLayout.LayoutParams(myVariable.screenWidth / 14, LayoutParams.MATCH_PARENT, 1);
	    myVariable.mainBottomlinearLayout.setLayoutParams(lp);
	    myVariable.mainBottomlinearLayout.setBackgroundColor(Color.BLACK);
	    myVariable.mainBottomlinearLayout.setOrientation(LinearLayout.VERTICAL);
	     	    
	    lp = new LinearLayout.LayoutParams(myVariable.screenWidth / 14 * 12, LayoutParams.MATCH_PARENT, 1);
	    myVariable.mOpenCvCameraView.setLayoutParams(lp);
	    
	    myVariable.btnSetting = new ImageButton(this);
	    myVariable.btnSetting .setId(1);
	    myVariable.btnSetting.setImageResource(R.drawable.image_setting);
	    myVariable.btnSetting.setRotation(-90);
	    lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, 1);
	    myVariable.btnSetting.setLayoutParams(lp);
	    myVariable.btnSetting.setBackgroundColor(Color.BLACK);
	    
	    myVariable.btnFlashLight = new ImageButton(this);
	    myVariable.btnFlashLight .setId(2);
	    myVariable.btnFlashLight.setImageResource(R.drawable.image_flash);
	    myVariable.btnFlashLight.setRotation(-90);
	    lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, 1);
	    myVariable.btnFlashLight.setLayoutParams(lp);
	    myVariable.btnFlashLight.setBackgroundColor(Color.BLACK);
	    
	    myVariable.btnCameraChange = new ImageButton(this);
	    myVariable.btnCameraChange .setId(3);
	    myVariable.btnCameraChange.setImageResource(R.drawable.image_camera_change);
	    myVariable.btnCameraChange.setRotation(-90);
	    lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, 1);
	    myVariable.btnCameraChange.setLayoutParams(lp);
	    myVariable.btnCameraChange.setBackgroundColor(Color.BLACK);

	    myVariable.btnPicture = new ImageButton(this);
	    myVariable.btnPicture .setId(4);
	    myVariable.btnPicture.setImageResource(R.drawable.image_picture);
	    myVariable.btnPicture.setRotation(-90);
	    lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, 1);
	    myVariable.btnPicture.setLayoutParams(lp);
	    myVariable.btnPicture.setBackgroundColor(Color.BLACK);
	     
	    myVariable.mainToplinearLayout.addView(myVariable.btnSetting);	    
	    myVariable.mainToplinearLayout.addView(myVariable.btnFlashLight);
	    myVariable.mainToplinearLayout.addView(myVariable.btnCameraChange);
	    myVariable.mainBottomlinearLayout.addView(myVariable.btnPicture);
	    
	    myVariable.btnCameraChange.setOnClickListener(btnFirstMenu); 
	    myVariable.btnCameraChange.setOnTouchListener(btnFirstMenu);
	    myVariable.btnSetting.setOnClickListener(btnFirstMenu); 
	    myVariable.btnSetting.setOnTouchListener(btnFirstMenu);
	    myVariable.btnFlashLight.setOnClickListener(btnFirstMenu);
	    myVariable.btnFlashLight.setOnTouchListener(btnFirstMenu);
	    myVariable.btnPicture.setOnClickListener(btnFirstMenu);
	    myVariable.btnPicture.setOnTouchListener(btnFirstMenu);
	    
	    frame.addView(myVariable.mainToplinearLayout);
	    frame.addView(myVariable.mOpenCvCameraView);
	    frame.addView(myVariable.mainBottomlinearLayout);
	    setContentView(frame); 	   	
	}
    这里分别设置了上下的控件布局size、控件对应的ID号、它们绑定的Click、Touch对应操作函数、以及预览图像显示模块myVariable.mOpenCvCameraView size。
  3、设置预览分辨率。
       @Override
	public void onCameraViewStarted(int width, int height) {
		// TODO Auto-generated method stub
		myVariable.mRgba = new Mat(height, width, CvType.CV_8UC4);
		Camera.Size s = myVariable.mOpenCvCameraView.getResolution();
		s.height=1080;
		s.width=1920;
		myVariable.mOpenCvCameraView.setResolution(s);
	}
com.example.camera_opencv_android.WTCamera
    public void setResolution(Camera.Size resolution) {
        disconnectCamera();
        connectCamera((int)resolution.width, (int)resolution.height);       
    }
org.opencv.android.JavaCameraView
@Override
 protectedboolean connectCamera(intwidth, intheight) {
     .........
     if(!initializeCamera(width, height))
         returnfalse;
     .........
 }
4、按键触发
classButtonListener implementsOnClickListener, OnTouchListener{
    @Override
    publicboolean onTouch(View arg0, MotionEvent arg1) {
        // TODO Auto-generated method stub
         if(arg0.getId() == 1){ 
             if(arg1.getAction() == MotionEvent.ACTION_DOWN){ 
                 myVariable.btnSetting.setImageResource(R.drawable.image_setting_2);
             }elseif(arg1.getAction() == MotionEvent.ACTION_UP){
                 myVariable.btnSetting.setImageResource(R.drawable.image_setting);
             }
         }elseif(arg0.getId() == 3){ 
             if(arg1.getAction() == MotionEvent.ACTION_DOWN){ 
                 myVariable.btnCameraChange.setImageResource(R.drawable.image_camera_change_2);
             }elseif(arg1.getAction() == MotionEvent.ACTION_UP){
                 myVariable.btnCameraChange.setImageResource(R.drawable.image_camera_change);
             }
         }elseif(arg0.getId() == 4){ 
             if(arg1.getAction() == MotionEvent.ACTION_DOWN){ 
                 myVariable.btnPicture.setImageResource(R.drawable.image_picture_2);
             }elseif(arg1.getAction() == MotionEvent.ACTION_UP){
                 myVariable.btnPicture.setImageResource(R.drawable.image_picture);
             }
         }elseif(arg0.getId() == 2){ 
             if(arg1.getAction() == MotionEvent.ACTION_DOWN){ 
                 myVariable.btnFlashLight.setImageResource(R.drawable.image_flash_2);
             }elseif(arg1.getAction() == MotionEvent.ACTION_UP){
                 myVariable.btnFlashLight.setImageResource(R.drawable.image_flash);
             }
         }
        returnfalse;
    }
 
    @Override
    publicvoid onClick(View v) {
        // TODO Auto-generated method stub
         if(v.getId() == 1){
             initFirstPopupWindowView(v); 
         }elseif(v.getId() == 3){              
              
         }elseif(v.getId() == 4){
             myVariable.pictureFlag = 1;
             File destDir = newFile("mnt/sdcard/mycamera/");
              if(!destDir.exists()) {
               destDir.mkdirs();
              }
             Toast toast=Toast.makeText(getApplicationContext(), "", Toast.LENGTH_SHORT);
             ImageView iv = newImageView(getApplicationContext());
             iv.setImageDrawable(getResources().getDrawable(R.drawable.toast_show_pic_addr));
             toast.setView(iv);
             toast.show();
         }elseif(v.getId() == 2){
 
         }
    }          
}    
在Touch操作中,根据不同的按键ID号,如果对应控件操作为ACTION_DOWN,表示控件被按下,则设置对应控件图片为比较偏暗图片来做提示。
当检测到操作为ACTION_UP,则恢复为原来的控件显示图片。
    在onClick操作中,(1)、按键为setting,进入到 initFirstPopupWindowView(v)中。
                     (2)、按键为闪光灯或者camera切换则不做处理。
                     (3)、按键为拍照,如果还没有mycamera目录,则先新建,同时设置拍照的pictureFlag,表示拍照张数为1张。
                          同时用Toast提示照片存放位置。
  5、拍照和灰阶预览处理。
@Override
    publicMat onCameraFrame(CvCameraViewFrame inputFrame) {
        // TODO Auto-generated method stub
        myVariable.mRgba = inputFrame.rgba();
        if(myVariable.previewFlag==0){
        }elseif(myVariable.previewFlag == 1){
            PreviceGray.grayProc(myVariable.mRgba.getNativeObjAddr());
        }
        if(myVariable.pictureFlag > 0){
            PreviceGray.takePicture(myVariable.mRgba.getNativeObjAddr());
            myVariable.pictureFlag = myVariable.pictureFlag -1;
        }  
        returnmyVariable.mRgba;
    }
    这里是预览的回调,每次更新预览照片,都会通过这里,于是在这里进行检查:                                                                1、myVariable.previewFlag如果为1,则PreviceGray.grayProc进行预览灰阶化处理,为0则不做处理,表示为正常预览。                    2、myVariable.pictureFlag > 0,则表示需要PreviceGray.takePicture进行拍照,同时根据pictureFlag 来决定需要拍摄的张数。
  6、Setting界面
privatevoid initFirstPopupWindowView(View v) {         
        View firstCustomView = getLayoutInflater().inflate(R.layout.picturesetting,  
                null,false); 
        myVariable.firstPopupwindow = newPopupWindow(firstCustomView, myVariable.screenWidth * 2/ 5, myVariable.screenHeight * 2/ 3); 
        ListView firstListView = (ListView) firstCustomView.findViewById(R.id.lvGroup);
        List<Map<String, Object>> firstListItems = newArrayList<Map<String, Object>>();
        for(inti = 0; i < myVariable.firstMenu.length; i++){
            Map<String, Object> firstListItem = newHashMap<String, Object>();
            firstListItem.put("cameraSetting", myVariable.firstMenu[i]);
            firstListItems.add(firstListItem);
        }
        SimpleAdapter simpleAdapter = newSimpleAdapter(this
                , firstListItems 
                , R.layout.listviewsetting
                ,newString[]{ "cameraSetting"}
                ,newint[]{R.id.icategory_name});
        firstListView.setAdapter(simpleAdapter); 
        firstListView.setRotation(-90);
        myVariable.firstPopupwindow.setFocusable(true);
        myVariable.firstPopupwindow.showAsDropDown(v, myVariable.screenWidth / 3, -(myVariable.screenHeight * 2/ 5));
        firstCustomView.setOnTouchListener(newOnTouchListener() {   
            @Override 
            publicboolean onTouch(View v, MotionEvent event) {  
                if(myVariable.firstPopupwindow != null&& myVariable.firstPopupwindow.isShowing()) {  
                    myVariable.firstPopupwindow.dismiss(); 
                    myVariable.firstPopupwindow = null; 
                }  
                returnfalse; 
            } 
        });
        firstListView.setOnItemClickListener(newOnItemClickListener() {
            @Override
            publicvoid onItemClick(AdapterView<?> arg0, View arg1, intarg2,
                    longarg3) {
                if(arg2==0){
                    initPreviewPopupWindowView();
                }
            }
        });
    }     
    这里也就是对应到点击Seting按键之后,弹出来的PopupWindow选择窗口,如果点中的是预览界面该窗口之外的其他位置,则销毁掉该窗口。
     如果点中的是该PopupWindow中对应选择项,则进去该选项操作中,目前选择项只有一个:预览模式,对应操作函数:initPreviewPopupWindowView();
  7、预览模式
private void initPreviewPopupWindowView() {
		// TODO Auto-generated method stub
    	View previewCustomView = getLayoutInflater().inflate(R.layout.picturesetting,  
                null, false);  
        myVariable.previewPopupwindow = new PopupWindow(previewCustomView, myVariable.screenWidth * 2 / 5, myVariable.screenHeight * 2 / 3);  
        ListView previewListView = (ListView) previewCustomView.findViewById(R.id.lvGroup);
        List<Map<String, Object>> previewListItems = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < myVariable.priviewMenu.length; i++){
			Map<String, Object> previewListItem = new HashMap<String, Object>();
			previewListItem.put("cameraSetting", myVariable.priviewMenu[i]);
			previewListItems.add(previewListItem);
		}
		SimpleAdapter simpleAdapter = new SimpleAdapter(this
				, previewListItems 
				, R.layout.listviewsetting
				, new String[]{ "cameraSetting"}
				, new int[]{R.id.icategory_name});
		previewListView.setAdapter(simpleAdapter);  
		previewListView.setRotation(-90);
        myVariable.previewPopupwindow.setFocusable(true);
        myVariable.previewPopupwindow.showAsDropDown(myVariable.btnSetting, myVariable.screenWidth / 3, -(myVariable.screenHeight * 2 / 5));
        previewCustomView.setOnTouchListener(new OnTouchListener() {   
            @Override  
            public boolean onTouch(View v, MotionEvent event) {  
                if (myVariable.previewPopupwindow != null && myVariable.previewPopupwindow.isShowing()) {  
                	myVariable.previewPopupwindow.dismiss();  
                	myVariable.previewPopupwindow = null;  
                }   
                return false;  
            }  
        });
        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;
				}
				if (myVariable.previewPopupwindow != null && myVariable.previewPopupwindow.isShowing()) {  
	                myVariable.previewPopupwindow.dismiss();  
	                myVariable.previewPopupwindow = null;  
	            }   
			}
		});
	} 
     和setting界面基本一样,在setting界面同样的位置上,再弹出一个PopupWindow,这样可以遮掩住上一个窗口,同时本窗口被销毁之后,能从新
回到setting窗口界面。
    同样是看该PopupWindow中的选择项,如果选择为普通模式,则myVariable.previewFlag = 0;如果是灰阶模式,则myVariable.previewFlag = 1;
根据之前讲解,我们已经知道如果previewFlag 为1,则在预览更新函数中会通过PreviceGray.grayProc来讲预览图像灰阶化。
    最后在该窗口中选择好了之后,该窗口会自动销毁,回退到setting窗口界面。
   代码下载: http://download.csdn.net/detail/u011630458/9241627
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值