Android和OpenCV开发编程(1)图像灰度化和Canny检测
来源:互联网 发布:mac ox版本升级mac os 编辑:程序博客网 时间:2024/06/03 08:38
开发的基础是首先配置好各种开发环境,过程很复杂,这里先不具体介绍了,整个过程中遇到了很多问题,主要步骤参考这几篇博客
http://blog.csdn.net/pwh0996/article/details/8957764
下面直接介绍同时实现两个功能的app,这里采用的是利用C++来实现,至于直接利用JAVA来实现灰度化的过程,可以参考这里http://blog.csdn.net/yanzi1225627/article/details/16917961
使用java API开发android:
创建工程
(1) 打开eclipse,创建android应用工程Img;
(2) 将测试图像lena.jpg添加到资源目录res/drawable-hdpi中;
(3) 在Package Explorer中选择项目Img,单击右键在弹出菜单中选择Properties,然后在弹出的Properties窗口中左侧选择Android,然后点击右下方的Add按钮,选择OpenCV Library 2.4.9并点击OK,操作完成后,会将OpenCV类库添加到Img的Android Dependencies中.
工程代码:
(1) 布局文件:activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/btnNDK" android:text="Canny检测" /> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/btnGray" android:text="灰度化" /> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/btnRestore" android:text="还原" /> <ImageView android:id="@+id/ImageView01" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
2、MainActivity.java文件
package com.iipc.img;import org.opencv.android.BaseLoaderCallback;import org.opencv.android.LoaderCallbackInterface;import org.opencv.android.OpenCVLoader;import android.app.Activity; import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.widget.Button; import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.ImageView;public class MainActivity extends Activity implements OnClickListener {/** Called when the activity is first created. */ImageView imgView; Bitmap resultImg; Bitmap img;Button btnNDK, btnRestore,btnGray; private static final String TAG="MainActivity"; //OpenCV类库加载并初始化成功后的回调函数,在此我们不进行任何操作 private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS:{ Log.i(TAG,"成功加载"); System.loadLibrary("Image_proc"); } break; default:{ super.onManagerConnected(status); Log.i(TAG,"加载失败"); } break; } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);this.setTitle("应用NDK转换灰度图"); btnRestore = (Button) findViewById(R.id.btnRestore); btnNDK = (Button) findViewById(R.id.btnNDK); btnGray = (Button) findViewById(R.id.btnGray); imgView = (ImageView) findViewById(R.id.ImageView01); img = ((BitmapDrawable) getResources().getDrawable( R.drawable.lena)).getBitmap();imgView.setImageBitmap(img); btnRestore.setOnClickListener(this); btnNDK.setOnClickListener(this);btnGray.setOnClickListener(this);} public void procSrc2Gray(){ int w = img.getWidth(); int h = img.getHeight(); int[] pixels = new int[w*h]; img.getPixels(pixels, 0, w, 0, 0, w, h); int[] resultInt = LibImgFun.grayProc(pixels, w, h); resultImg = Bitmap.createBitmap(w, h, Config.ARGB_8888); resultImg.setPixels(resultInt, 0, w, 0, 0, w, h); } @Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (v == btnNDK) { //long current = System.currentTimeMillis();Bitmap img1 = ((BitmapDrawable) getResources().getDrawable( R.drawable.lena)).getBitmap(); int w = img1.getWidth(), h = img1.getHeight(); int[] pix = new int[w * h]; img1.getPixels(pix, 0, w, 0, 0, w, h); int[] resultInt = LibImgFun.imgFun(pix, w, h);Bitmap resultImg = Bitmap.createBitmap(w, h, Config.ARGB_8888);resultImg.setPixels(resultInt, 0, w, 0, 0, w, h); //long performance = System.currentTimeMillis() - current; imgView.setImageBitmap(resultImg); //MainActivity.this.setTitle("w:" + String.valueOf(img1.getWidth()) + ",h:" + String.valueOf(img1.getHeight()) + "NDK耗时" + String.valueOf(performance) + " 毫秒");MainActivity.this.setTitle("OpenCV的Canny检测图");}else if (v == btnGray) { procSrc2Gray();imgView.setImageBitmap(resultImg); MainActivity.this.setTitle("OpenCV灰度化");}else if (v == btnRestore) {Bitmap img2 = ((BitmapDrawable) getResources().getDrawable( R.drawable.lena)).getBitmap(); imgView.setImageBitmap(img2);MainActivity.this.setTitle("原始图像");}} @Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存在于OpenCV安装包的apk目录中 OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this, mLoaderCallback); } }
3、LibImgFun.java文件
package com.iipc.img;public class LibImgFun {public static native int[] imgFun(int[] buf, int w, int h);public static native int[] grayProc(int[] buf, int w, int h);}
4、Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) include ../OpenCV-SDK/native/jni/OpenCV.mk LOCAL_SRC_FILES := LibImgFun.cpp LOCAL_MODULE := Image_proc include $(BUILD_SHARED_LIBRARY)
5、 Application.mk(配置文件)
APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions APP_ABI := armeabi-v7a APP_PLATFORM := android-86、LibImgFun.cpp文件
#include <LibImgFun.h>#include <opencv2/opencv.hpp>#include<highgui.h>#include <string>#include <vector>#include<stdio.h>#include<stdlib.h>#include<iostream>using namespace cv;using namespace std;//改写的canny检测代码,返回值为存储canny检测图像数据的int数组jintArray,传递的参数存储原始图像数据的int数组,以及w和hJNIEXPORT jintArray JNICALL Java_com_iipc_img_LibImgFun_imgFun(JNIEnv* env, jclass obj, jintArray buf, jint w, jint h){jint *cbuf; cbuf = env->GetIntArrayElements(buf, false);//JNI传递int数组的方法if (cbuf == NULL){return 0;}Mat myimg(h, w, CV_8UC4, (unsigned char*) cbuf);//java中读入的图像都是4通道的,所以这里myimg声明定义为CV_8UC4,以一个数组中的数据来建立MatMat grayimg;cvtColor(myimg,grayimg,CV_BGRA2GRAY);//将4通道的彩色图转为灰度图Mat pCannyImage;Canny(grayimg,pCannyImage,50,150,3);//canny检测uchar* ptr = myimg.ptr(0);//因为灰度图最终以4通道bmp形式显示,所以将得到的灰度图grayimg的数据赋值到4通道的imageData中, for(int i = 0; i < w*h; i ++){ //得到的canny图像原本是单通道,但java中显示bmp时只能4通道或三通道,为了使显示的图像时灰度的,把canny图像的数据值赋给一个4通道的myimg //对于一个int四字节,其彩色值存储方式为:BGRA ptr[4*i+1] = pCannyImage.data[i]; ptr[4*i+2] = pCannyImage.data[i]; ptr[4*i+0] = pCannyImage.data[i]; }//以下部分是将得到canny图像存在数组中,以数组的形式返回int size = w * h;jintArray result = env->NewIntArray(size);env->SetIntArrayRegion(result, 0, size, cbuf);env->ReleaseIntArrayElements(buf, cbuf, 0);return result;}JNIEXPORT jintArray JNICALL Java_com_iipc_img_LibImgFun_grayProc(JNIEnv* env, jclass obj, jintArray buf, jint w, jint h){ jint *cbuf; cbuf = env->GetIntArrayElements(buf, false); if(cbuf == NULL){ return 0; } Mat imgData(h, w, CV_8UC4, (unsigned char*)cbuf);Mat grayimg;cvtColor(imgData,grayimg,CV_BGRA2GRAY);//将4通道的彩色图转为灰度图 uchar* ptr = imgData.ptr(0);//因为灰度图最终以4通道bmp形式显示,所以将得到的灰度图grayimg的数据赋值到4通道的imageData中, for(int i = 0; i < w*h; i ++){ //计算公式:Y(亮度) = 0.299*R + 0.587*G + 0.114*B//去掉了原始程序中转换的公式 //对于一个int四字节,其彩色值存储方式为:BGRA ptr[4*i+1] = grayimg.data[i]; ptr[4*i+2] = grayimg.data[i]; ptr[4*i+0] = grayimg.data[i]; }//以下部分是将得到canny图像存在数组中,以数组的形式返回int size = w * h;jintArray result = env->NewIntArray(size);env->SetIntArrayRegion(result, 0, size, cbuf);env->ReleaseIntArrayElements(buf, cbuf, 0);return result;}
7、LibImgFun.h文件
#include <jni.h>extern "C" {JNIEXPORT jintArray JNICALL Java_com_iipc_img_LibImgFun_imgFun (JNIEnv *, jclass, jintArray, jint, jint);JNIEXPORT jintArray JNICALL Java_com_iipc_img_LibImgFun_grayProc (JNIEnv *, jclass, jintArray, jint, jint);}
8、结果
1、原图
2、灰度化
3、Canny检测
0 0
- Android和OpenCV开发编程(1)图像灰度化和Canny检测
- OpenCV-Python—图像梯度和Canny边缘检测
- OpenCV图像边缘检测(Canny算法)
- 灰度图像--图像分割 Canny边缘检测
- OpenCV读入视频,灰度化,并Canny边缘检测
- 基于java(加eclipse)的OpenCV学习之二____图像加载、灰度图、开运算、画线、Canny检测
- 【OpenCV学习笔记 004】 图像的缩放、Canny边缘检测和图像的二值化
- opencv边缘检测Sobel和Canny
- OpenCV Canny边缘检测输出写入一个单通道(灰度级)图像
- 【OpenCV】图像的变换(三)-Canny边缘检测
- OpenCV 图像增强—直方图均衡化和灰度拉伸
- 灰度图像的区域分割插值算法和针对彩色图像的基于Canny边缘检测的色彩融合算法
- 一些基本的opencv图像预处理函数直接用法(灰度化,otsu二值化,腐蚀膨胀,canny)
- 图像基本处理系列:灰度处理(1):灰度图像和灰度直方图
- opencv简单的彩色图像灰度化和二值化(学习笔记)
- opencv学习(一)实现将彩色图像转换成灰度图像和二值图像
- OpenCV图像灰度化
- OpenCV图像灰度化
- linux drm 架构
- Spring2.5学习2.2_编码剖析Spring依赖注入原理
- JS获取当前对象大小以及屏幕分辨率等
- iOS编程——类的继承
- Ping Pong 操作
- Android和OpenCV开发编程(1)图像灰度化和Canny检测
- Android总结之:Activity生命周期详解
- c++基础学习(03PM)
- HDFS HA切换后missing block问题分析
- Learning to Rank 简介
- Java如何等待子线程执行结束
- 如何在eclipse + python的环境中怎么使用ODBC
- android从相册中获取图片
- Activity切换结合动画效果出现白屏的问题