Я новичок в 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 algorithmLOGI("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, используемый для определения контура, но я не понимаю, насколько программно он обнаруживает края, пожалуйста, дайте мне знать, что не так в коде.
заранее спасибо
Я подозреваю, что здесь есть несколько проблем.
Для начала, в своем коде 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);
}
Держите меня в курсе о ваших успехах!
Других решений пока нет …