Opencv图像变灰处理(纯C++,不依赖Opencv Manager)

         本文是参考博客名为“千里之外”的朋友的文章,感谢!原链接为:http://blog.csdn.net/pwh0996/article/details/8957764/   但是没有完全一样,做了一些修改,已实践可用。

        之前做的opencv图像处理,总是会依赖Opencv Manager,所以需要再安装一个Opencv Manager的apk,这样就比较不方便,很多人也不愿意。 所以今天用到的是纯C++,抛弃了Opencv Manager。

       首先上资源代码(注意:因为OpenCVSDK占内存超出我上传文件的限制额,所以我把它去除了,用的时候还需要下载opencv的sdk,放入jni目录中。怎么命名下面对jni目录介绍时会提到这点)点击下载

       下面是项目的步骤:

        1、首先在项目中创建一个jni目录。目录的文件列表如下图:

      下面将对这些文件一一介绍。

       1)ImageProc.cpp文件。C++文件,里面有图片处理的方法。

 

#include <ImageProc.h>
#include <opencv2/core/core.hpp>
#include <string>
#include <vector>

using namespace cv;
using namespace std;

void proc(Mat &src);

JNIEXPORT jintArray JNICALL Java_com_example_grayonlyc_ImageProc_grayProc
  (JNIEnv* env, jclass obj, jintArray buf, jint w, jint h, jfloatArray width, jfloatArray maskX, jfloatArray maskY){
    jint *cbuf;
    cbuf = env->GetIntArrayElements(buf, JNI_FALSE);
    if(cbuf == NULL){
        return 0;
    }

/  测试object数组      ///
    jfloat *mx, *my;
    //jint length;
    mx = env->GetFloatArrayElements(maskX,JNI_FALSE);
    my = env->GetFloatArrayElements(maskY,JNI_FALSE);
    //length = env->GetArrayLength(maskX);

    Point2f mask[16];
    for(int i=0;i<16;i++){
    	mask[i].x = mx[i];
    	mask[i].y = my[i];
    }
    mask[0] = Point2f(0,1);
    mx[0] = mask[0].x;
    my[0] = mask[0].y;
    mx[1] = mask[1].x;
    my[1] = mask[1].y;
//

 /  测试float数组      ///
    jfloat* arr;
    jint length;
    arr = env->GetFloatArrayElements(width,JNI_FALSE);
    length = env->GetArrayLength(width);

    float finWidth[15];
    for(int i=0;i<15;i++){
    	finWidth[i] = arr[i];
    }
    finWidth[0] = 0.1f;
    arr[0] = finWidth[0];
    //SetIntArrayRegion(width, 0, length, arr);
//

    Mat imgData(h, w, CV_8UC4, (unsigned char*)cbuf);

    proc(imgData);//C++处理

    int size=w * h;
    jintArray result = env->NewIntArray(size);
    env->SetIntArrayRegion(result, 0, size, cbuf);
    env->ReleaseIntArrayElements(buf, cbuf, 0);
    return result;
}

void proc(Mat &src){
	uchar* ptr = src.ptr(0);
	for(int i = 0; i < src.cols * src.rows; i ++){
    //计算公式:Y(亮度) = 0.299*R + 0.587*G + 0.114*B
	        //对于一个int四字节,其彩色值存储方式为:BGRA
	    int grayScale = (int)(ptr[4*i+2]*0.299 + ptr[4*i+1]*0.587 + ptr[4*i+0]*0.114);
	    ptr[4*i+1] = grayScale;
	    ptr[4*i+2] = grayScale;
	    ptr[4*i+0] = grayScale;
	 }
}

         供Java调用的方法的命名规则为:Java_包名_类名_方法名。

 

        2)ImageProc.h头文件。声明定义C文件中用到的方法。声明规则也是:Java_包名_类名_方法名。

 

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

#ifndef _Included_com_example_grayonlyc_ImageProc
#define _Included_com_example_grayonlyc_ImageProc
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_grayonlyc_ImageProc
 * Method:    grayProc
 * Signature: ([III[F[F[F)[I
 */
JNIEXPORT jintArray JNICALL Java_com_example_grayonlyc_ImageProc_grayProc
  (JNIEnv *, jclass, jintArray, jint, jint, jfloatArray, jfloatArray, jfloatArray);

#ifdef __cplusplus
}
#endif
#endif

         .h头文件可以自己手动创建,然后声明方法,也可以通过命令自动生成。介绍一下自动生成:

 

          在Eclipse中写好java文件保存后,会自动生成class文件,在bin目录的classes目录下,有自己项目的包名,在相应java的包下就有相应class文件。在doc中进入到classes目录下,输入javah com.example.grayonlyc.ImageProc即可以生成.h头文件。这里的包名是我自己的,需要改成你自己的。

          生成的头文件,可以自己修改成自己想要的名称,比如我这用的名称为ImageProc.h。

         3)Android.mk文件。这个文件是向ndk系统描述代码的信息和需要生成文件的信息。

 

LOCAL_PATH := $(call my-dir)  
include $(CLEAR_VARS)  
include $(LOCAL_PATH)/OpenCVsdk/native/jni/OpenCV.mk  
LOCAL_SRC_FILES  := ImageProc.cpp  
LOCAL_MODULE     := image_proc  
include $(BUILD_SHARED_LIBRARY)

         4)Application.mk文件。这个文件是用来描述你的程序需要哪些模块。

 

 

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

         5)OpencvSDK  这个是opencv的官方sdk。我把名称改成了OpenCVSDK。它的目录列表如下:

          项目中因为OpencvSDK占内存超出我上传文件的限制额,所以我把它去除了,用的时候还需要下载opencv的sdk,然后把名称改成OpenCVSDK放入jni目录中就可以使用了,引用已经在Android.mk文件中写好了。

 

        6)以上5步都完成后,需要将C文件编译成so库供java使用。首先电脑里要下载好ndk,然后配置好环境变量(没有的话百度一下,很简单,解压后配置一下环境变量就OK)。然后在doc系统中进入jni中的C文件所在目录,输入命令:ndk-build 或者 ndk-build.cmd   然后就等待编译成功,就可以发现lib下相应的文件夹内就有libimage_proc.so库了。

          2、java文件。共有两个java文件。MainActivity.java和ImageProc.java文件。

          1)MainActivity.java

 

package com.example.grayonlyc;

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

public class MainActivity extends Activity implements OnClickListener{
	private Button btnProc;  
    private ImageView imageView;  
    private TextView textView;  
    private Bitmap bmp;  
    private float[] width = new float[15];//手指宽度
    //private Point[] mask = new Point[16];
    private float[] maskX = new float[16];//X坐标
    private float[] maskY = new float[16];//Y坐标

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
        System.loadLibrary("image_proc"); 
        
        btnProc = (Button) findViewById(R.id.btn_gray_process);  
        imageView = (ImageView) findViewById(R.id.image_view);  
        //textView = (TextView) findViewById(R.id.text_view);  
        //将lena图像加载程序中并进行显示  
        bmp = BitmapFactory.decodeResource(getResources(), R.drawable.lena);  
        imageView.setImageBitmap(bmp);  
        btnProc.setOnClickListener(this);
        
        for(int i=0;i<15;i++){       	
        	width[i] = 0.0f;
        	maskX[i] = 0;
        	maskY[i] = 0;		
        }
        maskX[15] = maskY[15] = 0;
        width[1] = 1.0f;
        maskX[1] = maskY[1] = 1;
        
        //textView.setText("width原值01:"+width[0]+";"+width[1]);
        //textView.setText("mask原值:("+ maskX[0] + "," + maskY[0] +") ; ("+ maskX[1] + "," + maskY[1] +")");
	}

	@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
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		long current = System.currentTimeMillis();   
        int w = bmp.getWidth();  
        int h = bmp.getHeight();  
        int[] pixels = new int[w*h]; 
              
        
        bmp.getPixels(pixels, 0, w, 0, 0, w, h);  
        int[] resultInt = ImageProc.grayProc(pixels, w, h, width, maskX, maskY);  
        Bitmap resultImg = Bitmap.createBitmap(w, h, Config.ARGB_8888);  
        resultImg.setPixels(resultInt, 0, w, 0, 0, w, h);  
        
        long performance = System.currentTimeMillis() - current;
        this.setTitle("NDK耗时"+ String.valueOf(performance) + " 毫秒");
        imageView.setImageBitmap(resultImg);    
        //textView.setText("mask改变值:("+ maskX[0] + "," + maskY[0] +") ; ("+ maskX[1] + "," + maskY[1] +")");
	}
}

          2)ImageProc.java  改文件中是声明了一个本地方法,调用C文件中相应的方法。命名规则:方法前要有native关键字,表示调用JNI中相应方法名的方法。

 

 

package com.example.grayonlyc;  

public class ImageProc {  
    public static native int[] grayProc(int[] pixels, int w, int h, float width[], float maskX[], float maskY[]);  
}

          3、布局文件,activity_main.xml  

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:orientation="vertical"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" >  
      
    <Button   
        android:id="@+id/btn_gray_process"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="@string/str_proc"/>  
      
    <ImageView  
        android:id="@+id/image_view"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:contentDescription="@string/str_proc"/>  
         
</LinearLayout> 

           以上是这个工程所有的介绍,虽然是参考别人的,但是也是用心去了解和修改的,希望有所帮助。  

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值