項目介紹——拍照筆記

拍照筆記

背景

  • 這是我大二修讀的智能移動平臺應用開發的課程項目,老師要求我們自選題目。我和另一個小組成員發現在平時上課的時候,經常會使用手機對ppt進行拍照來記錄一些重要的信息。但是如果你坐在教室兩側的位置,那麼照片中的ppt就會是斜着的並且ppt也不會佔滿整張照片。所以我們就決定做一個拍照筆記應用,這個應用能夠對照片中的矩形進行識別、截取、矯正以覆蓋原來的照片,並且能夠對照片做筆記。
  • 不同於普通的筆記應用,我們開發的這個筆記應用可以在照片的任意位置做筆記(也就是選中照片上的一個點之後,長按就能在標記處做筆記,爲了不影響照片的顯示筆記的標記點是可以顯示和隱藏的),其他的筆記應用一般是在筆記中插入照片而不是在照片上做筆記。

職責

  1. 照片的拍攝、截取與保存
  2. 筆記及筆記本的編輯與保存
  3. 筆記標記所處照片位置的更新與保存
class Mark {
	private int x;
	private int y;
	private String description;
}

class Note {
	private Image image;
	private List<Mark> marks;

	// 依賴於接口而不是具體實現
	// 這樣我們在實例化Note的時候就可以傳入一個具體實現List接口的類的實例,比如ArrayList或者LinkedList
	public Note(List<Mark> marks){
		this.marks = marks;
	}
}

遇到的問題(Bug)

  1. 當照片的標記過多時,拖動照片會出現閃爍甚至程序崩潰的情況。原因:這是由於將標記點位置的更新放在了子線程中(標記點較多時,更新所有標記點位置的操作比較費時,所以需要放在子線程中),然後直接在子線程中跟新了UI。解決方法:使用Handler,在Handler的post()方法中更新UI
  2. 爲什麼Android不能在非UI線程中更新UI?首先UI線程並不是線程安全的(更新UI的方法沒有加鎖,任何子線程均可以調用),所以在子線程中修改UI的話數據容易出錯;其次,如果支持子線程修改UI,由此帶來的線程同步和線程安全的代價很高。所以Android直接規定不能在子線程中修改UI,簡化了設計。

難點

  1. 照片的截取(截取照片的指定區域並矯正爲矩形):最開始,我直接調用Android系統自帶的裁剪功能來實現,但是發現只能裁剪矩形區域,不能是任意四邊形。所以嘗試自己實現圖片裁剪及矯正功能,讓用戶自己選定照片的裁剪區域,然後對這個區域進行透視變換將圖片矯正。雖然實現了裁剪和矯正的功能,但是每次都需要選定裁剪區域,操作麻煩,而且處理速度較慢。最後我們使用了一個開源的圖片裁剪庫——SmartCropper,該庫基於opencv識別圖片中的四邊形區域,支持手動調節選區,然後根據所選區域裁剪出選區內的圖片,並透視變換矯正成正面圖片。
// 設置要裁剪的圖片
public viod setImageToCrop(Bitmap bmp){
	setImageBitmap(bmp);
	// 如果開啓了自動掃描,那麼會調用native方法自動識別四邊形區域
	setCropPoints(mAutoScanEnable ? SmartCropper.scan(bmp) : null);
}

// 裁剪圖片
public Bitmap crop(Point[] points){
	if(!checkPoints(points)) return null;
	Bitmap bmp = getBitmap();
	// 調用native方法裁剪圖片並透視變換矯正成正面圖片
	return bmp == null ? null : SmartCropper.crop(bmp, points);
}
  1. opencv是什麼?opencv是一個跨平臺計算機視覺庫,可以運行在Linux、Windows、Android、Mac操作系統上。
  2. 參考 OpenCV Java 實現票據、紙張的四邊形邊緣檢測與提取、擺正
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章