《Master Opencv...读书笔记》卡通化效果移植到android系统

简介: 昨天CSDN博客抽风了。这是第7次编辑这个文件了,之前老是提交失败!     声明 1.电脑比较坑爹,前置摄像头坏掉了。 2.卡通化效果运行比较慢,老外的书上说是,人每触摸一下屏幕,才生成一张卡通化效果的图片 因此,为了简便期间,我就只对一副图像进行卡通化效果。

昨天CSDN博客抽风了。这是第7次编辑这个文件了,之前老是提交失败!

 

 

声明

1.电脑比较坑爹,前置摄像头坏掉了。

2.卡通化效果运行比较慢,老外的书上说是,人每触摸一下屏幕,才生成一张卡通化效果的图片

因此,为了简便期间,我就只对一副图像进行卡通化效果。

原理什么的见前面的文章,本文的目的,是熟悉ndkjni

 

环境需求:

eclipse juno

ndk(r9)

android sdk 4.4 api 19

opencv 2.4.7 android版本

cygwin

准备工作:

1.E:\OpenCV-2.4.7.1-android-sdk\sdk中的java项目导入工作空间,日后凡事java端调用opencv的函数都要用到这个类库

2.安装opencv manager.apk,目前在android上所有的opencv程序都必须依附于android manger。在DOS窗口口中执行:

adb install <OpenCV4Android SDKpath>/apk/OpenCV_2.4.7_Manager_2.14_armv7a-neon.apk

开始项目:

1.新建android application工程,取名Cartoonfiy,右击项目属性,勾选opencv类库


2.将林志玲MM的照片复制到drwabale随便哪个目录下,然后编写布局文件activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
     <Button   
        android:id="@+id/btn_gray_process"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="卡通化"
        android:onClick="click"
        />  
      
    <ImageView  
        android:id="@+id/image_view"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:contentDescription="@string/str_proc"/>  

</LinearLayout>

效果比较丑,不管了:)

4.新建ImageProc类,编写本地化方法,作为调用c语言代码的入口:

package com.example.cartoonfiy;

public class ImageProc {
	public static native void CartoonProc(int[] pixels,int[] result, int w, int h);
}


5.dos窗口中,使用javah工具,自动生成c语言的头文件,具体方法就是在DOS窗口中跑到Cartoonfiy项目的bin\classes目录下:

javah com.example.cartoonfiy.ImageProc

之后,在classes目录下将会有com_example_cartoonfiy_ImageProc.h文件,具体内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_cartoonfiy_ImageProc */

#ifndef _Included_com_example_cartoonfiy_ImageProc
#define _Included_com_example_cartoonfiy_ImageProc
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_cartoonfiy_ImageProc
 * Method:    CartoonProc
 * Signature: ([III)[I
 */
JNIEXPORT void JNICALL Java_com_example_cartoonfiy_ImageProc_CartoonProc
  (JNIEnv *, jclass, jintArray,jintArray, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

6.我们新建一个jni文件夹(名字就这个,不能随便改,否则ndk-build命令据说找不到的),把刚才的那个com_example_cartoonfiy_ImageProc.h文件拷贝过来。然后分别编写Android.mk

LOCAL_PATH := $(call my-dir)  
include $(CLEAR_VARS)  
include E:/OpenCV-2.4.7.1-android-sdk/sdk/native/jni/OpenCV.mk  
LOCAL_SRC_FILES  := ImageProc.cpp  
LOCAL_SRC_FILES  += Cartoon.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_MODULE     := image_proc  
include $(BUILD_SHARED_LIBRARY)  

和Application.mk:

APP_STL := gnustl_static  
APP_CPPFLAGS := -frtti -fexceptions  
APP_ABI := armeabi-v7a  
APP_PLATFORM := android-8 

7.回到MainActivity中,编写java端主要的代码:

package com.example.cartoonfiy;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.Config;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends Activity {
	private ImageView imageView;  
	private Bitmap bmp;  
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		imageView = (ImageView) findViewById(R.id.image_view);  
	     //将lena图像加载程序中并进行显示  
	     bmp = BitmapFactory.decodeResource(getResources(), R.drawable.lady);  
	     imageView.setImageBitmap(bmp);  
	}	
	
	//OpenCV类库加载并初始化成功后的回调函数,在此我们不进行任何操作  
    private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {  
       @Override  
       public void onManagerConnected(int status) {  
           switch (status) {  
               case LoaderCallbackInterface.SUCCESS:{  
                   System.loadLibrary("image_proc");  
               } break;  
               default:{  
                   super.onManagerConnected(status);  
               } break;  
           }  
       }  
   };  
   
   public void click(View view){
	   int w = bmp.getWidth();
	   int h = bmp.getHeight();
	   int[] pixels = new int[w * h];
	   int[] resultInt = new int[w*h];
	   bmp.getPixels(pixels, 0, w, 0, 0, w, h);
	   ImageProc.CartoonProc(pixels,resultInt, w, h);
	   Bitmap resultImg = Bitmap.createBitmap(w, h, Config.ARGB_8888);
	   resultImg.setPixels(resultInt, 0, w, 0, 0, w, h);
	   imageView.setImageBitmap(resultImg);
	   
   }
   
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		  //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是  
        //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存在于OpenCV安装包的apk目录中  
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);  
	}
	
	
}


好了,现在开始主要的C语言部分。由于是针对一副图像处理,我把上次的代码修改封装成一个函数,对应头文件和源文件内容分别是(这两个文件也放在jni目录下):

Cartoon.h:

#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <iostream>
using namespace cv;
using namespace std;

Mat image_proc(Mat src);

Cartoon.cpp:

#include "Cartoon.h"

//对一张图像进行卡通化效果处理
Mat image_proc(Mat src)
{
	Mat smallImg,tmp,bigImg,gray,edges,masks,dst;

	int repetitions = 7; // Repetitions for strong cartoon effect.
	const int MEDIAN_BLUR_FILTER_SIZE = 7;
	const int LAPLACIAN_FILTER_SIZE = 5;
	const int EDGES_THRESHOLD = 80;
	
	Size size = src.size();
	Size smallSize;
	smallSize.width = size.width/2;
	smallSize.height = size.height/2;
	smallImg = Mat(smallSize, CV_8UC3);
	tmp = Mat(smallSize, CV_8UC3);
	dst= Mat(size,CV_8UC3);

	if (src.empty()) {
		cerr << "ERROR: Couldn't grab a video frame." <<endl;
		exit(1);
	}

	cvtColor(src,gray,CV_BGR2GRAY);

	medianBlur(gray,gray,MEDIAN_BLUR_FILTER_SIZE);

	Laplacian(gray, edges, CV_8U, LAPLACIAN_FILTER_SIZE);

	threshold(edges, masks, EDGES_THRESHOLD, 255, THRESH_BINARY_INV);

	resize(src, smallImg, smallSize, 0,0, INTER_LINEAR);

	for (int i=0; i<repetitions; i++) {
		int ksize = 9; // Filter size. Has a large effect on speed.
		double sigmaColor = 9; // Filter color strength.
		double sigmaSpace = 7; // Spatial strength. Affects speed.
		bilateralFilter(smallImg, tmp, ksize, sigmaColor, sigmaSpace);
		bilateralFilter(tmp, smallImg, ksize, sigmaColor, sigmaSpace);
	}

	resize(smallImg, bigImg, size, 0,0, INTER_LINEAR);

	dst.setTo(0);
	
	//! copies those matrix elements to "m" that are marked with non-zero mask elements.
	bigImg.copyTo(dst,masks);

	return dst;

}

然后,编写我们的ImageProc.cpp

#include<com_example_cartoonfiy_ImageProc.h>
#include<Cartoon.h>

JNIEXPORT void JNICALL Java_com_example_cartoonfiy_ImageProc_CartoonProc
  (JNIEnv *env, jclass obj, jintArray buf,jintArray res, jint w, jint h){
	jint *cbuf,*bgra;
	cbuf = env->GetIntArrayElements(buf, false);
	bgra = env->GetIntArrayElements(res, 0);

	Mat src,dst,mbgra,imgData;

	Size size;
	size.width = w;
	size.height = h;

	src = Mat(size, CV_8UC3);
	dst = Mat(size, CV_8UC3);
	imgData = Mat(size, CV_8UC4, (unsigned char*)cbuf);
	mbgra = Mat(size, CV_8UC4, (unsigned char *)bgra);
	cvtColor(imgData,src,CV_BGRA2BGR);

	dst = image_proc(src);
	cvtColor(dst, mbgra, CV_BGR2BGRA);
	env->ReleaseIntArrayElements(buf, cbuf, 0);
	env->ReleaseIntArrayElements(res, bgra, 0);
}

最后用cygwin进行交叉编译:

打开cygwin,输入

cd /cygdrive/e/worksapce/Cartoonfiy

ndk-build

记得按F5,并clean一下工程,这是在libs目录下有个libimage_proc.so文件,

如果cygwin没有报错的话,然后运行我们的android applicatoin

 

运行效果:

   


注意:

1.老外书中说的android处理图片的color format,什么用照相机拍出来的是:YUV420s,用Bitmap读取的本地图片是:BGRA。当你的图像处理函数只能应付BGR时,你必须用cvtColor进行格式转换。老外又说什么转换格式会影响速度等等,这些先不管了。

2.关于cjava端数据传输,可以参考三个姓王的兄弟写的《android高级开发实战-UI、NDK、安全》。我这边在端直接把mat.data转换成int输出返回了。以后再学吧

 


 

目录
相关文章
|
2月前
|
人工智能 搜索推荐 物联网
Android系统版本演进与未来展望####
本文深入探讨了Android操作系统从诞生至今的发展历程,详细阐述了其关键版本迭代带来的创新特性、用户体验提升及对全球移动生态系统的影响。通过对Android历史版本的回顾与分析,本文旨在揭示其成功背后的驱动力,并展望未来Android可能的发展趋势与面临的挑战,为读者呈现一个既全面又具深度的技术视角。 ####
|
2月前
|
IDE Java 开发工具
移动应用与系统:探索Android开发之旅
在这篇文章中,我们将深入探讨Android开发的各个方面,从基础知识到高级技术。我们将通过代码示例和案例分析,帮助读者更好地理解和掌握Android开发。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧。让我们一起开启Android开发的旅程吧!
|
1月前
|
监控 Java Android开发
深入探索Android系统的内存管理机制
本文旨在全面解析Android系统的内存管理机制,包括其工作原理、常见问题及其解决方案。通过对Android内存模型的深入分析,本文将帮助开发者更好地理解内存分配、回收以及优化策略,从而提高应用性能和用户体验。
|
1月前
|
存储 安全 Android开发
探索Android系统的最新安全特性
在数字时代,智能手机已成为我们生活中不可或缺的一部分。随着技术的不断进步,手机操作系统的安全性也越来越受到重视。本文将深入探讨Android系统最新的安全特性,包括其设计理念、实施方式以及对用户的影响。通过分析这些安全措施如何保护用户免受恶意软件和网络攻击的威胁,我们希望为读者提供对Android安全性的全面了解。
|
2月前
|
监控 Java Android开发
深入探讨Android系统的内存管理机制
本文将深入分析Android系统的内存管理机制,包括其内存分配、回收策略以及常见的内存泄漏问题。通过对这些方面的详细讨论,读者可以更好地理解Android系统如何高效地管理内存资源,从而提高应用程序的性能和稳定性。
98 16
|
2月前
|
安全 Android开发 iOS开发
深入探讨Android与iOS系统的差异及未来发展趋势
本文旨在深入分析Android和iOS两大移动操作系统的核心技术差异、用户体验以及各自的市场表现,进一步探讨它们在未来技术革新中可能的发展方向。通过对比两者的开放性、安全性、生态系统等方面,本文揭示了两大系统在移动设备市场中的竞争态势和潜在变革。
|
2月前
|
算法 JavaScript Android开发
|
4天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
1月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
65 19
|
1月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
70 14

热门文章

最新文章