opencv4android移植到系统app

 

最近在尝试使用opencv4android实现投影仪的自动对焦功能,在AndroidStudio后需要将功能移到系统工程编译成系统app,仅以此文记录下移植过程中遇到的问题。

首先去opencv官网下载一份android的sdk, 然后在AndroidStudio中将opencv_android的sdk以module的方式导入工程,编译生成classes.jar,该文件包含了Opencv的api接口;具体方式可参考如下链接

    https://blog.csdn.net/PZ0605/article/details/72778547?locationNum=12&fps=1

生成jar文件的路径会在对应应用路径下面的,根据opencv版本不同,略有不同

    openCVLibrary340/build/intermediates/intermediate-jars/debug

获取jar文件后需要在Android.mk中导入该jar文件,以如下方式即可导入

LOCAL_STATIC_JAVA_LIBRARIES := \
    opencv \
    android-support-v4
include $(BUILD_PACKAGE)


include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
opencv:lib/classes.jar
include $(BUILD_MULTI_PREBUILT)

这样,只要导入对应的包,就可以编译通过了。

 

下面讲下遇到的坑,大神请无视:

1.运行的时候提示unsatified link之类的错误,其实就是链接so失败了,后来阅读了下sdk代码后,在onResume中加入如下代码即可了

@Override
    protected void onResume() {
        super.onResume();
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_4_0, this, baseLoaderCallback);
    }

2.由于我实现的是自动对焦,所有起初我使用的是Opencv的JavaCameraView来显示摄像头采集到的图像,但是每次运行的时候都报找不到资源的问题,然后我就舍弃了opencv的这种方式,采用了Android的Camera类来实现这一功能

3.在使用Camera类保存图像的时候,发现每次调用完camera.takePicture后数据采集就停止了,所以不得不在保存图像后再次调用了camera.startPreview();

4.后续在做的时候,发现可以在onPreviewFrame中直接保存图片,由于该函数的数据为YUV数据,所以转成jpg需要用到YuvImage类,通过其中的yuvImage.compressToJpeg可以将YUV数据成功保存成jpg图片

贴下实现的代码:

其中Rect中的width和height,表示显示的区域,可用于裁剪

Camera.Size size = camera.getParameters().getPreviewSize();
int w = size.width;
int h = size.height;
saveMyBitmap(FileName, bytes, w, h);
public static void saveMyBitmap(String filePath,byte[] data,int width,int high){  
        File f = new File(filePath);  
        try {  
            f.createNewFile();  
        } catch (IOException e) {  
        }  
        FileOutputStream fOut = null;  
        try {  
            fOut = new FileOutputStream(f);  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        }  
        YuvImage yuvImage = new YuvImage(data,ImageFormat.NV21,width,high, null); 
        try {  
            yuvImage.compressToJpeg(new Rect(0,0,width,high),50,fOut);  
        }catch (Exception e){  
              
        }  
        try {  
            fOut.flush();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        try {  
            fOut.close();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }

5.在做的时候,起初使用的SurfaceView,必须在SurfaceView中显示拍摄到的图像才能调用onPreviewFrame,感觉十分蛋疼,然后机缘巧合下找到了这个SurfaceTexture的实现方式:

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        getPermission();
        surfaceviewer = (SurfaceView)findViewById(R.id.surfaceviewer);
        imageView = (ImageView)findViewById(R.id.imv);
        imageView.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(),R.drawable.fouse));

        surfaceholder = surfaceviewer.getHolder();
        surfaceholder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceholder.addCallback(AutoFouse.this);  
        
        surfaceTexture = new SurfaceTexture(10);  
@Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        // TODO Auto-generated method stub
        // 获取camera对象
        camera = Camera.open();
        try {
            // 设置预览监听
            //camera.setPreviewDisplay(surfaceHolder);
            camera.setPreviewTexture(surfaceTexture);  

 

posted @ 2018-04-02 16:58  零语  阅读(563)  评论(0编辑  收藏  举报