2013-03-23 116 views
1

我想在我的Android應用中使用Tom Gibaras實現(更改爲Android)實現Canny邊緣檢測算法。該應用程序使用相機捕捉圖片,相機工作正常,圖片被拍攝,問題在於我想將它傳遞給算法並顯示結果。而不是正在處理的圖像和邊緣檢測然後顯示,該應用程序返回到主屏幕下面的代碼是我目前的活動。我可以提供任何額外的代碼請求,你能幫助我嗎?Android的Canny邊緣檢測器

/** 
* ShootActivity demonstrates capturing camera images 
* - user presses button to capture an image using the device camera 
*/ 
public class ShootActivity extends Activity { 
public static final int ACTION_TAKE_PHOTO_B = 1; 

public String mCurrentPhotoPath; 
public static final String BITMAP_STORAGE_KEY = "viewbitmap"; 
public static final String IMAGEVIEW_VISIBILITY_STORAGE_KEY = "imageviewvisibility"; 
public ImageView mImageView; 
public Bitmap mImageBitmap; 
public static final String JPEG_FILE_PREFIX = "IMG_"; 
public static final String JPEG_FILE_SUFFIX = ".jpg"; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    mImageView = (ImageView) findViewById(R.id.imageView1); 
    mImageBitmap = null; 

    Button picBtn = (Button) findViewById(R.id.btnIntend); 
    setBtnListenerOrDisable( 
      picBtn, 
      mTakePicOnClickListener, 
      MediaStore.ACTION_IMAGE_CAPTURE 
    ); 

} 
/** 
* Click method to handle user pressing button to launch camera 
*/ 

Button.OnClickListener mTakePicOnClickListener = 
     new Button.OnClickListener() { 
     public void onClick(View v) { 
      dispatchTakePictureIntent(ACTION_TAKE_PHOTO_B); 
     } 
    }; 


public File createImageFile() throws IOException { 
    // Create an image file name 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
    String imageFileName = JPEG_FILE_PREFIX + timeStamp + "_"; 
    //File albumF = getAlbumDir(); 
    File imageF = File.createTempFile(imageFileName, JPEG_FILE_SUFFIX); 
    return imageF; 
} 

public File setUpPhotoFile() throws IOException { 

    File f = createImageFile(); 
    mCurrentPhotoPath = f.getAbsolutePath(); 

    return f; 
} 

public void setPic() { 

    /* There isn't enough memory to open up more than a couple camera photos */ 
    /* So pre-scale the target bitmap into which the file is decoded */ 

    /* Get the size of the ImageView */ 
    int targetW = mImageView.getWidth(); 
    int targetH = mImageView.getHeight(); 

    /* Get the size of the image */ 
    BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
    bmOptions.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); 
    int photoW = bmOptions.outWidth; 
    int photoH = bmOptions.outHeight; 

    /* Figure out which way needs to be reduced less */ 
    int scaleFactor = 2; 
    if ((targetW > 0) || (targetH > 0)) { 
     scaleFactor = Math.min(photoW/targetW, photoH/targetH); 
    } 

    /* Set bitmap options to scale the image decode target */ 
    bmOptions.inJustDecodeBounds = false; 
    bmOptions.inSampleSize = scaleFactor; 
    bmOptions.inPurgeable = true; 

    /* Decode the JPEG file into a Bitmap */ 
    mImageBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); 
    CannyEdgeDetection detector = new CannyEdgeDetection(); 
    detector.setLowThreshold(0.5f); 
    detector.setHighThreshold(1f); 
    detector.setSourceImage(mImageBitmap); 
    detector.process(); 
    Bitmap edges = detector.getEdgesImage(); 
    /* Associate the Bitmap to the ImageView */ 
    mImageView.setImageBitmap(edges); 
    mImageView.setVisibility(View.VISIBLE); 
} 

public void galleryAddPic() { 
     Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE"); 
     File f = new File(mCurrentPhotoPath); 
     Uri contentUri = Uri.fromFile(f); 
     mediaScanIntent.setData(contentUri); 
     this.sendBroadcast(mediaScanIntent); 
} 

public void dispatchTakePictureIntent(int actionCode) { 

    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 

     File f = null; 

     try { 
      f = setUpPhotoFile(); 
      mCurrentPhotoPath = f.getAbsolutePath(); 
      takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      f = null; 
      mCurrentPhotoPath = null; 
     } 


    startActivityForResult(takePictureIntent, 1102); 
} 
public void handleBigCameraPhoto() 
{ 
    if (mCurrentPhotoPath != null) 
    { 
     setPic(); 
     galleryAddPic(); 
     mCurrentPhotoPath = null; 
    } 
} 
/** 
* Handle user returning from capturing the image 
*/ 
@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{ 
    if(requestCode == 1102 && resultCode == Activity.RESULT_OK) 
    { 
     if(data != null) 
     { 
     handleBigCameraPhoto(); 
     } 
    } 

} 
@Override 
protected void onSaveInstanceState(Bundle outState) { 
    outState.putParcelable(BITMAP_STORAGE_KEY, mImageBitmap); 
    outState.putBoolean(IMAGEVIEW_VISIBILITY_STORAGE_KEY, (mImageBitmap != null)); 
    super.onSaveInstanceState(outState); 
} 

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState) { 
    super.onRestoreInstanceState(savedInstanceState); 
    mImageBitmap = savedInstanceState.getParcelable(BITMAP_STORAGE_KEY); 
    mImageView.setImageBitmap(mImageBitmap); 
    mImageView.setVisibility(savedInstanceState.getBoolean(IMAGEVIEW_VISIBILITY_STORAGE_KEY) ? ImageView.VISIBLE : ImageView.INVISIBLE); 
} 
public static boolean isIntentAvailable(Context context, String action) { 
    final PackageManager packageManager = context.getPackageManager(); 
    final Intent intent = new Intent(action); 
    List<ResolveInfo> list = 
     packageManager.queryIntentActivities(intent, 
       PackageManager.MATCH_DEFAULT_ONLY); 
    return list.size() > 0; 
} 


public void setBtnListenerOrDisable( 
     Button btn, 
     Button.OnClickListener onClickListener, 
     String intentName 
) { 
    if (isIntentAvailable(this, intentName)) { 
     btn.setOnClickListener(onClickListener);    
    } else { 
     btn.setText( 
      getText(R.string.cannot).toString() + " " + btn.getText()); 
     btn.setClickable(false); 
    } 
} 

}

03-27 02:47:37.310: E/AndroidRuntime(6513): FATAL EXCEPTION: main 
03-27 02:47:37.310: E/AndroidRuntime(6513): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1102, result=-1, data=null} to activity {com.example.f_y_p/com.example.f_y_p.ShootActivity}: java.lang.NullPointerException 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at android.app.ActivityThread.deliverResults(ActivityThread.java:3182) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at android.app.ActivityThread.handleSendResult(ActivityThread.java:3225) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at android.app.ActivityThread.access$1100(ActivityThread.java:140) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1275) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at android.os.Handler.dispatchMessage(Handler.java:99) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at android.os.Looper.loop(Looper.java:137) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at android.app.ActivityThread.main(ActivityThread.java:4898) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at java.lang.reflect.Method.invokeNative(Native Method) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at java.lang.reflect.Method.invoke(Method.java:511) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at dalvik.system.NativeStart.main(Native Method) 
03-27 02:47:37.310: E/AndroidRuntime(6513): Caused by: java.lang.NullPointerException 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at com.example.f_y_p.CannyEdgeDetection.setSourceImage(CannyEdgeDetection.java:75) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at com.example.f_y_p.ShootActivity.setPic(ShootActivity.java:114) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at com.example.f_y_p.ShootActivity.handleBigCameraPhoto(ShootActivity.java:153) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at com.example.f_y_p.ShootActivity.onActivityResult(ShootActivity.java:166) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  at android.app.Activity.dispatchActivityResult(Activity.java:5390)  
032702:47:37.310:E/AndroidRuntime(6513):atandroid.app.ActivityThread.deliverResults(ActivityThread.java:3178) 
03-27 02:47:37.310: E/AndroidRuntime(6513):  ... 11 more 

2月3日至二十七日:47:48.535:I /過程(6513):發送信號。 PID:6513 SIG:9

回答

2

崩潰

您的應用程序返回到主屏幕,因爲有一個崩潰。 該崩潰可能是由於NullPointerException

這可能是因爲這行:

Bitmap mBitmap = (Bitmap) data.getExtras().get("data"); 

logcat的

您可以準確地確定在崩潰是通過查看logcat的輸出發生。請發佈LogCat輸出或僅掃描它並確定應用程序崩潰的位置。

攝影地點

現在的壞消息。您無法通過您嘗試的方式通過ExtrasBundle從相機拍攝照片。此功能最多隻會返回一個不適合您的圖像處理算法的小縮略圖。您的圖片更可能位於由outputFileUri指定的位置。

如何捕獲和可選從圖庫中選擇

請看到這個帖子:Allow user to select camera or gallery for image。尋找標題爲「如何啓動單個意圖從圖庫或照相機中選擇圖像,或者任何註冊的應用程序來瀏覽文件系統」。您將不得不使用這種或類似的方法從相機中獲取圖像的路徑。

規模

此外,還有就是你要不得不面對另一個問題。很可能無法打開圖像的單個全尺寸Bitmap表示形式。它太大而不適合Android設備的可用堆內存。因此,您將不得不打開縮小版的圖像。幸運的是,使用BitmapFactory.decodeFile(String pathName, BitmapFactory.Options opts)並不是很困難。

實施例:

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inSampleSize = 4; // Arbitrary, your mileage may vary. 
return BitmapFactory.decodeFile(path, options); 

可以通過1,2,3縮放圖像,使用次數較小inSampleSize等。有計算inSampleSize如保持Bitmap特定字節大小低於甚至途徑。

+0

嗨大衛,謝謝你的建議,我已經板載採取它改變了我的代碼,但同樣的問題仍然發生,當我去保存通過相機,我得到上面的空指針異常拍攝的圖像中,resuly代碼-1且數據爲空。我編輯了代碼,並在logcat上面發佈,你能幫助我嗎? – Cheeseking11 2013-03-27 03:12:01

+0

嘿CK,有一個'NullPointerException'在ShootActivity.java的166線。那裏發生了什麼? – 2013-03-27 04:59:01