拍照筆記
背景
- 這是我大二修讀的智能移動平臺應用開發的課程項目,老師要求我們自選題目。我和另一個小組成員發現在平時上課的時候,經常會使用手機對ppt進行拍照來記錄一些重要的信息。但是如果你坐在教室兩側的位置,那麼照片中的ppt就會是斜着的並且ppt也不會佔滿整張照片。所以我們就決定做一個拍照筆記應用,這個應用能夠對照片中的矩形進行識別、截取、矯正以覆蓋原來的照片,並且能夠對照片做筆記。
- 不同於普通的筆記應用,我們開發的這個筆記應用可以在照片的任意位置做筆記(也就是選中照片上的一個點之後,長按就能在標記處做筆記,爲了不影響照片的顯示筆記的標記點是可以顯示和隱藏的),其他的筆記應用一般是在筆記中插入照片而不是在照片上做筆記。
職責
- 照片的拍攝、截取與保存
- 筆記及筆記本的編輯與保存
- 筆記標記所處照片位置的更新與保存
class Mark {
private int x;
private int y;
private String description;
}
class Note {
private Image image;
private List<Mark> marks;
public Note(List<Mark> marks){
this.marks = marks;
}
}
遇到的問題(Bug)
- 當照片的標記過多時,拖動照片會出現閃爍甚至程序崩潰的情況。原因:這是由於將標記點位置的更新放在了子線程中(標記點較多時,更新所有標記點位置的操作比較費時,所以需要放在子線程中),然後直接在子線程中跟新了UI。解決方法:使用Handler,在Handler的post()方法中更新UI
- 爲什麼Android不能在非UI線程中更新UI?首先UI線程並不是線程安全的(更新UI的方法沒有加鎖,任何子線程均可以調用),所以在子線程中修改UI的話數據容易出錯;其次,如果支持子線程修改UI,由此帶來的線程同步和線程安全的代價很高。所以Android直接規定不能在子線程中修改UI,簡化了設計。
難點
- 照片的截取(截取照片的指定區域並矯正爲矩形):最開始,我直接調用Android系統自帶的裁剪功能來實現,但是發現只能裁剪矩形區域,不能是任意四邊形。所以嘗試自己實現圖片裁剪及矯正功能,讓用戶自己選定照片的裁剪區域,然後對這個區域進行透視變換將圖片矯正。雖然實現了裁剪和矯正的功能,但是每次都需要選定裁剪區域,操作麻煩,而且處理速度較慢。最後我們使用了一個開源的圖片裁剪庫——SmartCropper,該庫基於opencv識別圖片中的四邊形區域,支持手動調節選區,然後根據所選區域裁剪出選區內的圖片,並透視變換矯正成正面圖片。
public viod setImageToCrop(Bitmap bmp){
setImageBitmap(bmp);
setCropPoints(mAutoScanEnable ? SmartCropper.scan(bmp) : null);
}
public Bitmap crop(Point[] points){
if(!checkPoints(points)) return null;
Bitmap bmp = getBitmap();
return bmp == null ? null : SmartCropper.crop(bmp, points);
}
- opencv是什麼?opencv是一個跨平臺計算機視覺庫,可以運行在Linux、Windows、Android、Mac操作系統上。
- 參考 OpenCV Java 實現票據、紙張的四邊形邊緣檢測與提取、擺正