今天遇到一個OpenCV的坑,其本身不是OpenCV造成的,而是是偉大的蘋果,以及其封閉的系統。這個坑使得存儲圖像文件的過程多費周章,曲折難解。
在OpenCV中,寫入圖像文件,只需要用imwrite
函數:
cv::imwrite(imageName, img);
在Android系統中,在獲取相冊存儲權限的條件下,以上方法即可很容易地將img對象中的圖像文件存儲到系統相冊中,無需做過多處理。
然而,在iOS系統中,只傳入imageName
和cv::Mat
的img
是無任何作用的,該方法執行成功,卻不見效果。而將cv::Mat
轉化成UIImage
類型,再存儲到沙盒中的方式也不失為比較好的方法,但缺點是它會導致一些意想不到的問題。
在我的實踐中,問題如下:
- 圖片所占存儲空間變小(原圖為3+MB,只做讀取并轉化成
UIImage
后僅500+K) - 顏色錯誤,原本紅色的實木家具變成了棕色,淺黃色的地板變成了藍色(不知其然,所用
cv::Mat
-->UIImage
方法為OpenCV官方文檔中方法)
經過一下午的問題排查,終尋求方法將原圖像文件無差別寫入iOS設備沙盒中,實現過程:
bool writeImage2Document(const char *imageName, cv::Mat img) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"/%s", imageName]];
const char* cPath = [filePath cStringUsingEncoding:NSMacOSRomanStringEncoding];
const cv::String newPaths = (const cv::String)cPath;
//Save as Bitmap to Documents-Directory
cv::imwrite(newPaths, img);
return true;
}
這里的路徑經過三次轉化,才得到imwrite
函數在iOS系統中有用的參數,實在令人汗顏,其中NSMacOSRomanStringEncoding
就是用MacOS的特殊編碼方式對路徑進行編碼,再強轉為cv::String
才能作為有效的參數,至于為什么這么轉來轉去,誰知道呢!
今日記錄于此,留與后人吐槽!