Android NDK开发:利用OpenCV实现简笔画效果
2019-08-09 本文已影响17人
itfitness
目录
![](https://img.haomeiwen.com/i8850933/90bc0f4a58085cf2.png)
效果演示
![](https://img.haomeiwen.com/i8850933/d4bbcbf1a67372e4.gif)
实现原理
首先利用高斯滤波对图像进行降噪处理,然后将图像转换为灰度图像方便边缘的提取,接下来对灰度图像进行边缘的提取并将提取出的边缘作为前景色为指定颜色的图像的蒙版(这个图像可以是纯色也可以是有纹路的图像),最后将蒙版区域添加到背景为白色的图像上。
相关API
●GaussianBlur(高斯滤波)
●cvtColor(颜色空间转换)
●Canny(边缘提取)
●copyTo(拷贝图像)
核心代码
OpenCV库的引入可以看:OpenCV On Android最佳环境配置指南(Android Studio篇)
为了方便大家理解,这次的操作应用了C++与OpenCV提供的JNI函数库分别做了实现。
●Native层、
public native void stickFigure(Object bitmap);
extern "C"
JNIEXPORT void JNICALL
Java_com_itfitness_opencvrehearse_demos_stickfigure_StickFigureActivity_stickFigure__Ljava_lang_Object_2(
JNIEnv *env, jobject instance, jobject bitmap) {
AndroidBitmapInfo info;
void *pixels;
CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
info.format == ANDROID_BITMAP_FORMAT_RGB_565);
CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
CV_Assert(pixels);
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
Mat temp(info.height, info.width, CV_8UC4, pixels);
GaussianBlur(temp,temp,Size(3,3),0,0);//高斯去噪
Mat gray;
cvtColor(temp,gray,CV_RGBA2GRAY);//转换为灰度图
Mat mask;
Canny(gray,mask,20,200);//边缘提取
Mat backGround = Mat(temp.size(),temp.type(),Scalar(255,255,255));//背景为白色
Mat foreGround = Mat(temp.size(),temp.type(),Scalar(255,0,0));//前景色
foreGround.copyTo(backGround,mask);
backGround.copyTo(temp);//将最终图像赋给bitmap
//释放资源
gray.release();
mask.release();
backGround.release();
foreGround.release();
}
AndroidBitmap_unlockPixels(env, bitmap);
}
●Java层
private Bitmap stickFigure(){
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_relief);
Mat src = new Mat();
Utils.bitmapToMat(bitmap,src);//将Bitmap对象转换为Mat对象
Imgproc.GaussianBlur(src,src,new Size(3,3),0,0);
Imgproc.cvtColor(src,src,Imgproc.COLOR_RGBA2GRAY);//将图像转换为灰度图像
Mat mask = new Mat();//边缘蒙版
Imgproc.Canny(src,mask,20,200);//边缘提取
Mat dst = new Mat(src.size(), CvType.CV_8UC3,new Scalar(255,255,255));//背景色为白色CV_8UC3表示为3通道即R、G、B
Mat fground = new Mat(src.size(), CvType.CV_8UC3,mSelectscalar);//前景色
fground.copyTo(dst,mask);//将蒙版区域拷贝到背景为白色的图像上
Utils.matToBitmap(dst,bitmap);//将Mat对象转换为Bitmap对象
return bitmap;
}