android opencv抠图

opencv抠图很简单,只需要调用grabCut函数就可以实现,不过在android端对图片尺寸有要求,太大了会卡死

补充说明一下这种抠图方法,这是一种在一个矩形范围内自动扣的方法,不是交互式抠图,交互式抠图也是用grabCut函数,不过还要进行其他操作

原图

抠图

图片缩小后看起来还好

蒙版

贴代码

 

Mat img = new Mat();
//缩小图片尺寸
Bitmap bm = Bitmap.createScaledBitmap(bitmap,bitmap.getWidth()/10,bitmap.getHeight()/10,true);
//bitmap->mat
Utils.bitmapToMat(bm, img);
//转成CV_8UC3格式
Imgproc.cvtColor(img, img, Imgproc.COLOR_RGBA2RGB);
//设置抠图范围的左上角和右下角
Point tl=new Point(64, 10);
Point br=new Point(230, 300);
Rect rect = new Rect(tl, br);

//生成遮板
Mat firstMask = new Mat();
Mat bgModel = new Mat();
Mat fgModel = new Mat();
Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(Imgproc.GC_PR_FGD));
Imgproc.grabCut(img, firstMask, rect, bgModel, fgModel,5, Imgproc.GC_INIT_WITH_RECT);
Core.compare(firstMask, source, firstMask, Core.CMP_EQ);

//抠图
Mat foreground = new Mat(img.size(), CvType.CV_8UC3, new Scalar(255, 255, 255));
img.copyTo(foreground, firstMask);

//mat->bitmap
Bitmap b = Bitmap.createBitmap(bitmap.getWidth()/10,bitmap.getHeight()/10, Bitmap.Config.ARGB_8888);
Utils.matToBitmap(foreground,b);

imageView.setImageBitmap(b);

这是java层实现的代码,jni实现也差不多

 

java代码

 

Mat img = new Mat();
Bitmap bm = Bitmap.createScaledBitmap(bitmap,bitmap.getWidth()/10,bitmap.getHeight()/10,true);
Utils.bitmapToMat(bm, img);
Imgproc.cvtColor(img, img, Imgproc.COLOR_RGBA2RGB);
Mat dst = new Mat(grabCutFromJNI(img.nativeObj,64,10,230,300));
Bitmap b = Bitmap.createBitmap(bitmap.getWidth()/10,bitmap.getHeight()/10, Bitmap.Config.ARGB_8888);
Utils.matToBitmap(dst,b);
imageView.setImageBitmap(b);

java调用c++函数

 

 

 

public native long grabCutFromJNI(long m,int l,int t,int r,int b);

 

 

 

c++代码

 

extern "C"
JNIEXPORT Mat* JNICALL
Java_com_example_hyq_opencv_MainActivity_grabCutFromJNI(JNIEnv *env, jobject instance, jlong m,
                                                        jint l, jint t, jint r, jint b) {

    // TODO
    Mat *img = (Mat *) m ;

    Rect rect(l,t,r - l,b - t);

    Mat firstMask;
    Mat bgModel;
    Mat fgModel;

    grabCut(*img,
            firstMask,
            rect,
            bgModel,fgModel,
            5,
            GC_INIT_WITH_RECT);
    compare(firstMask,GC_PR_FGD,firstMask,CMP_EQ);

    Mat *foreground = new Mat(img->size(),CV_8UC3,Scalar(255,255,255));

    img->copyTo(*foreground,firstMask);

    return foreground;

}

 

 

 

如果想实现原图抠图,可以先缩小生成遮板,再放大蒙版进行抠图,当然还要进行优化,不然很难看

也可以试试线程抠图,可能是因为主线程阻塞导致闪退

2017/12/03更新

发现这篇博文看的人比较多,最近又写了交互式抠图所以就把那篇博文的链接加上来

android opencv交互式抠图

2020/4/16更新

想把demo上传到github,可是发现原来的demo不停报错,也不知道为啥,以前测试都没问题啊,就又改改,问题根源在java和c++的内存管理,他们是相互独立的,比如一个Mat同时存在java和c++的时候,当java把资源释放了,而c++不知道java把那个Mat释放了,c++调用的时候就崩溃了,当然反过来的情况也是一样的,所以就把资源统一由java或c++管理,最好不要混合使用

修改上传到GitHub了,RectActivity是简单的抠图,GCActivity是交互抠图,MainActivity和GrabCut这两个文件是我测试用的请无视

GrabCut

 

 

 

 

 

 

 

 

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值