使用NDK显示轮廓的图像处理

时间:2012-10-29 13:28:44

标签: android c++ c android-ndk

我是android ndk的新手。我已经开始通过ruckus和IBM博客了解图像处理示例。我试图显示图像的轮廓。这是我正在使用的代码

package com.example;

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

public class OutlineClass extends Activity{
    private ImageView imageView;
      private Bitmap bitmap;
      private Button button;
      private Bitmap original;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.outline);

          original  = BitmapFactory.decodeResource(getResources(), R.drawable.wallace);
          bitmap    = BitmapFactory.decodeResource(getResources(), R.drawable.wallace);
          button    = (Button) findViewById(R.id.obutton);
          imageView = (ImageView) findViewById(R.id.oimageView2);
          button.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                  ShowOutline();

            }


        });

        }

        private void ShowOutline() {
            Bitmap oBitmap = original.copy(Bitmap.Config.ARGB_8888, true);
            Bitmap gBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

            showOutlineWithNative(oBitmap,gBitmap );
            imageView.setImageBitmap(gBitmap);

        }

        public native void showOutlineWithNative(Bitmap bmp1, Bitmap bmp2);
    }

这是我用于显示图像行的c代码

/*
To show outline
Pixel operation
*/
JNIEXPORT void JNICALL Java_com_example_OutlineClass_showOutlineWithNative(JNIEnv
* env, jobject  obj, jobject bitmapedges,jobject bitmapgray)
{
    AndroidBitmapInfo  infogray;
        void*              pixelsgray;
        AndroidBitmapInfo  infoedges;
        void*              pixelsedge;
        int                ret;
        int             y;
        int             x;
        int             sumX,sumY,sum;
        int             i,j;
        int                Gx[3][3];
        int                Gy[3][3];
        uint8_t            *graydata;
        uint8_t            *edgedata;


        LOGI("findEdges running");

        Gx[0][0] = -1;Gx[0][1] = 0;Gx[0][2] = 1;
        Gx[1][0] = -2;Gx[1][1] = 0;Gx[1][2] = 2;
        Gx[2][0] = -1;Gx[2][1] = 0;Gx[2][2] = 1;



        Gy[0][0] = 1;Gy[0][1] = 2;Gy[0][2] = 1;
        Gy[1][0] = 0;Gy[1][1] = 0;Gy[1][2] = 0;
        Gy[2][0] = -1;Gy[2][1] = -2;Gy[2][2] = -1;


        if ((ret = AndroidBitmap_getInfo(env, bitmapedges, &infogray)) < 0) {
            LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
            return;
        }


        if ((ret = AndroidBitmap_getInfo(env, bitmapgray, &infoedges)) < 0) {
            LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
            return;
        }




        if (infogray.format != ANDROID_BITMAP_FORMAT_A_8) {
            LOGE("Bitmap format is not A_8 !");
            return;
        }


        if (infoedges.format != ANDROID_BITMAP_FORMAT_A_8) {
            LOGE("Bitmap format is not A_8 !");
            return;
        }



        if ((ret = AndroidBitmap_lockPixels(env, bitmapedges, &pixelsgray)) < 0) {
            LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
        }

        if ((ret = AndroidBitmap_lockPixels(env, bitmapgray, &pixelsedge)) < 0) {
            LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
        }


        // modify pixels with image processing algorithm


        LOGI("time to modify pixels....");

        graydata = (uint8_t *) pixelsgray;
        edgedata = (uint8_t *) pixelsedge;

        for (y=0;y<=infogray.height - 1;y++) {
            for (x=0;x<infogray.width -1;x++) {
                sumX = 0;
                sumY = 0;
                // check boundaries
                if (y==0 || y == infogray.height-1) {
                    sum = 0;
                } else if (x == 0 || x == infogray.width -1) {
                    sum = 0;
                } else {
                    // calc X gradient
                    for (i=-1;i<=1;i++) {
                        for (j=-1;j<=1;j++) {
                            sumX += (int) ( (*(graydata + x + i + (y + j)
    * infogray.stride)) * Gx[i+1][j+1]);
                        }
                    }

                    // calc Y gradient
                    for (i=-1;i<=1;i++) {
                        for (j=-1;j<=1;j++) {
                            sumY += (int) ( (*(graydata + x + i + (y + j)
    * infogray.stride)) * Gy[i+1][j+1]);
                        }
                    }

                    sum = abs(sumX) + abs(sumY);

                }

                if (sum>255) sum = 255;
                if (sum<0) sum = 0;

                *(edgedata + x + y*infogray.width) = 255 - (uint8_t) sum;



            }
        }

        AndroidBitmap_unlockPixels(env, bitmapgray);
        AndroidBitmap_unlockPixels(env, bitmapedges);

}

我得到的结果是相同的图像,没有变化...... 我知道sebel算法用于检测轮廓,但我没有得到它是如何编程检测边缘请告诉我代码中的错误。

提前致谢

1 个答案:

答案 0 :(得分:1)

我怀疑这里有几个问题。

对于初学者,在NDK代码中,检查输入位图是否编码为Alpha_8图像(即灰度图像):

if (infogray.format != ANDROID_BITMAP_FORMAT_A_8) {
        LOGE("Bitmap format is not A_8 !");
        return;
}


if (infoedges.format != ANDROID_BITMAP_FORMAT_A_8) {
        LOGE("Bitmap format is not A_8 !");
        return;
}

创建位图时,将Bitmap.Config.ARGB_8888传递给copy函数。我怀疑这导致这些检查失败,因此函数在处理图像之前返回。您应该使用copy(Bitmap.Config.ALPHA_8, true)

创建位图

在我看来,您尝试在流程结束时显示错误的位图:您以错误的顺序将位图传递给showOutlineWithNative。您要显示的位图是原生函数的bitmapedges参数,此处您将要显示输入的灰度图像。

总而言之,在我看来ShowOutline的正确代码就是:

private void ShowOutline() {
        // grayscale version of the original bitmap:
        Bitmap gray = original.copy(Bitmap.Config.ALPHA_8, true);
        // receiver bitmap for the Sobel detector:
        Bitmap output = bitmap.copy(Bitmap.Config.ALPHA_8, true);

        showOutlineWithNative(output, gray);
        imageView.setImageBitmap(output);

}

让我发布您的进度!