今天遇到一个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
才能作为有效的参数,至于为什么这么转来转去,谁知道呢!
今日记录于此,留与后人吐槽!