基于opencv的相机之物体跟踪/抖动检测/图库更新/模仿HDR/模仿ChromaFlash(三)

简介

  很显然,就是继续在之前的基础上添加着新功能。

物体跟踪

原理介绍

  主要使用的opencv集成的函数:calcOpticalFlowPyrLK。
具体可以参考这篇文档:opencv实现跟踪鼠标选取的目标:http://blog.csdn.net/u011630458/article/details/45950319

具体代码

  1、在setting中,加入了物体跟踪的选项。同时加入对应操作函数。
firstListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
   ..............
   }else if(arg2 == 2){
    initmyobjectTrackingPopupWindowView();
       }
       .............. 
    }
 }
 private void initmyobjectTrackingPopupWindowView() {
      myobjectTrackingListView.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
        if(arg2==0){
        myVariable.myobjectTracking = 1;
        myVariable.s.height= myVariable.screenHeight;
        myVariable.s.width= myVariable.screenWidth * 16 / 9;
        resolutionChange();
        Toast toast=Toast.makeText(getApplicationContext(), "", Toast.LENGTH_SHORT);
        ImageView iv = new ImageView(getApplicationContext());
        iv.setImageDrawable(getResources().getDrawable(R.drawable.toast_show_object_addr));
        toast.setView(iv); 
        toast.show();
         }else if(arg2 == 1){
        myVariable.myobjectTracking = 0;
        myVariable.myobjectTracking_x = 0;
        myVariable.myobjectTracking_y = 0;
         }
                 ........
    });
       }
 }
物体跟踪操作也是一个opupWindow,布局和setting一样。进入该功能之后,可以选择是或者否来使能和关闭该功能,通过myobjectTracking来
表示功能是否使能,myobjectTracking_x,和myobjectTracking_y 来表示被跟踪对象的中心点坐标。需要注意下,为了保证点击touch操作和预览
图像坐标对应起来,所以在打开物体跟踪之后,会强行重新设置一遍camera的分辨率。
  接着给预览界面注册了Touch操作,当被按下之后,通过timerAdd来判断是否是被长按了,如果是被长按,则表示当前被长按的中心左边就是需要被
跟踪的位置,更新坐标位置到myobjectTracking_x、myobjectTracking_y 。
public boolean onTouch(View arg0, MotionEvent arg1) {
    // TODO Auto-generated method stub
    if(arg1.getAction() == MotionEvent.ACTION_DOWN) {
        myVariable.timerEnable = 1;
        myVariable.timerAdd = 0;            
    }
    if(arg1.getAction() == MotionEvent.ACTION_UP){
        myVariable.timerEnable = 0;
        if(myVariable.timerAdd > 5){
            myVariable.myobjectTracking_x = (int)(arg1.getRawX() + (myVariable.screenWidth / 20));
            myVariable.myobjectTracking_y = (int)(arg1.getRawY());  
            myVariable.myobjectTrackingFlag = 1;
        }else{
            myVariable.mOpenCvCameraView.focusOnTouch(arg1);
        }
    }
    return true;
}
最后在预览画面更新函数中进行真正的图像跟踪处理:
@Override
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    // TODO Auto-generated method stub
            if((myVariable.myobjectTracking == 1)  && ((myVariable.myobjectTracking_x > 0) || myVariable.myobjectTracking_y > 0)){
        myobject.libmyobjectTracking(myVariable.mRgba.getNativeObjAddr(), 
                 myVariable.myobjectTracking_x, myVariable.myobjectTracking_y, myVariable.myobjectTrackingFlag);
        myVariable.myobjectTrackingFlag = 0;
    }
     }
最后的函数libmyobjectTracking,就是在之前提到的那篇文章中代码移植过来,通过ndk调用即可。

效果演示

  效果截图如下:
                 
                    (图一)                              (图二)

抖动检测

原理介绍

  主要用的是opencv集成的phaseCorrelate函数,用来检查移动的方向和速度。
具体可以看文档:opencv实现移动速度和方向探测 http://blog.csdn.net/u011630458/article/details/46323319

具体代码

  和之前的物体跟踪类似,首先也是在setting中加入功能选择,抖动检测;接着是可以选择是否打开该功能。
private void initTremblePopupWindowView() {
        myTrembleListView.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
        if(arg2==0){
        myVariable.myTremble = 1;
        myVariable.myTremble_flag = 1;
        }else if(arg2 == 1){
        myVariable.myTremble = 0;
        }
 
    }
    });
    }
通过myTremble和myTremble_flag来表示抖动检测功能开启了。接着也是在预览更新函数中进行具体的抖动检测操作。
@Override
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    // TODO Auto-generated method stub
            .............
            if(myVariable.myTremble == 1){
        myobject.libmyTremble(myVariable.mRgba.getNativeObjAddr(), myVariable.myTremble_flag);
        myVariable.myTremble_flag = 0;
    }
            ............
    }
   这里的libmyTremble也是将之前文档中的代码,通过ndk移植过来的。需要注意下,实际测试中,该计算很花时间,在实际运行中,如果分辨率稍大,就会效果很差。

效果演示

  效果截图如下:
                      
                    (图三)                                   (图四)

图库更新

具体代码

  在拍完图片之后,发现打开系统自带的图库中,并没有被新出来。所以对拍照之后,让系统进行了从新扫描目录。
首先看下ndk下,具体的拍照图片保存。
JNIEXPORT void Java_com_example_camera_1opencv_1android_PreviceGray_takePicture(JNIEnv* env, jclass obj, jlong imageGray){
    static int i = 0;
    string file_mo = "_opencv_for_android.jpg";
    string android_file = "mnt/sdcard/mycamera/";
    string filename;
 
    i++;
    char buf[10];
    sprintf(buf, "%d", i);
    string b = buf;
 
    filename = android_file + b + file_mo;
 
    Mat mat = Mat(*((Mat*)imageGray));
    Mat mat_1(mat), mat_2;
    transpose(mat ,mat_1);
    flip(mat_1, mat_2, 1);
 
    imwrite(filename,mat_2);
}
 这里可以看到保存出来的图片,在/sdcard/mycamera目录下,并且图片名字都是_opencv_for_android.jpg为结尾。
接着在保存完图片之后,让重新扫描目录:
private void fileScan(String file, Context context){
    MediaScannerConnection.scanFile(context,
            new String[] {file}, null,
            new MediaScannerConnection.OnScanCompletedListener() {
 
                public void onScanCompleted(String path, Uri uri) {
                    Log.i("TAG", "Finished scanning " + path);
                }
            });
}    
public void folderScan(String path, Context context){
    File file = new File(path);
     
    if(file.exists() && file.isDirectory()){
        File[] array = file.listFiles();
         
        for(int i=0;i<array.length;i++){
            File f = array[i];
             
            if(f.isFile()){//FILE TYPE
                String name = f.getName();                    
                if(name.endsWith("opencv_for_android.jpg")){
                    fileScan(f.getAbsolutePath(),context);
                }
            }
        }
    }
}
效果演示
  效果截图如下:
         
                    (图一)

模仿HDR

原理讲解

  就是分别连续拍摄过曝和欠曝两张图片,然后进行合成。
具体可以参考文档:opencv实现图片HDR功能 http://10.120.10.100:9002/Opencv_wt_image_android_38

具体代码

  1、在setting中,加上HDR选项,选择是否开启HDR功能。
private void initFirstPopupWindowView(View v) {
     firstListView.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
            ...............
        else if(arg2 == 4){
        initHDRPopupWindowView();
        }
            ...........
    });
     }
}
private void initHDRPopupWindowView() {
     myHDRListView.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
        if(arg2==0){
        myVariable.myHDR = 1;
        myVariable.myTremble = 0;
        myVariable.myobjectTracking = 0;
        myVariable.myChromaFlash = 0;
        }else if(arg2 == 1){
        myVariable.myHDR = 0;
        }
    }
     });
}
可以看到myHDR来表示HDR功能打开或者关闭,同时如果HDR功能被打开,则其他的如物体跟踪等功能就被强行关闭掉了。
  2、修改了拍照按钮操作流程。
@Override
public void onClick(View v) {
       .............
       else if(v.getId() == 4){
       if(myVariable.myHDR == 1){
        myVariable.pictureFlag = 2;
        myVariable.myHDR_num = 17;
       }else{
        myVariable.pictureFlag = 1;
    }
}
可以看到,HDR模式下,按下拍照之后,会连续拍摄两张照片,同时两张照片的间隔时间为myHDR_num。
  3、接着在预览更新函数中,进行HDR的具体操作。
@Override
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    if(myVariable.pictureFlag > 0){
        ...........
    else if(myVariable.myHDR == 1){
       myVariable.test.mainHDR(myVariable, MainActivity.this);
    }
        ...........
    }
}
public void mainHDR(MyVariable myVariable, Context context){
    if(myVariable.myHDR_num == 17){
    if(myVariable.pictureFlag == 2){
        myVariable.mOpenCvCameraView.setExposure(6);
    }else if(myVariable.pictureFlag == 1){
        myVariable.mOpenCvCameraView.setExposure(-6);
    }
    }else if(myVariable.myHDR_num == 0){
    PreviceGray.takeHDRPicture(myVariable.mRgba.getNativeObjAddr(), myVariable.pictureFlag);
    myVariable.myHDR_num = 18;
    myVariable.pictureFlag = myVariable.pictureFlag -1;
    if(myVariable.pictureFlag == 0){
        myVariable.mOpenCvCameraView.setExposure(0);
        myVariable.test.folderScan(myVariable.pic_sdcard, context);
    }
    }
    if(myVariable.myHDR_num > -1){
    myVariable.myHDR_num -= 1;
    }
}
这里可以看到首先设置camera曝光为过曝,拍摄一张图片,接着设置为欠曝,继续拍摄一张图片,最后在takeHDRPicture函数中进行合成。
takeHDRPicture就是将前面那篇文档中的代码,ndk下移植过来的。

模仿ChromaFlash

  和HDR类似,区别上也就是HDR是使用的过曝和欠曝图片进行合成,而这个功能用来合成的图片为:打开闪光灯和关闭闪光灯拍摄的图片。
public void mainChromaFlash(MyVariable myVariable, Context context){
    if(myVariable.myChromaFlash_num == 17){
        if(myVariable.pictureFlag == 2){
             myVariable.mOpenCvCameraView.setFlashMode(context, 4);
             myVariable.myFlashLight = 1;
        }else if(myVariable.pictureFlag == 1){
            myVariable.mOpenCvCameraView.setFlashMode(context, 1);
            myVariable.myFlashLight = 0;
        }
    }else if(myVariable.myChromaFlash_num == 0){
        PreviceGray.takeChromaFlashPicture(myVariable.mRgba.getNativeObjAddr(), myVariable.pictureFlag);
        myVariable.myChromaFlash_num = 28;
        myVariable.pictureFlag = myVariable.pictureFlag -1;
        if(myVariable.pictureFlag == 0){
            myVariable.test.folderScan(myVariable.pic_sdcard, context);
        }
    }
    if(myVariable.myChromaFlash_num > -1){
        myVariable.myChromaFlash_num -= 1;
    }
}
和HDR的操作基本类似,区别上也就是将设置camera曝光改为了设置camera的flash打开或者关闭。
具体演示下载:http://download.csdn.net/detail/u011630458/9261617
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值