将 cvMat 转换为 UIImage 时出现内存问题
Memory problems while converting cvMat to UIImage
在这里发布这个问题之前,我已经阅读了所有材料和上面的类似帖子,但我无法了解主要的 "idea" 发生了什么以及如何解决它,在 10 个类似问题中,大家正在用 @autoreleasepool
解决这个问题,在这种情况下我无法实现我的目标。因此,在将 cvMat 转换为 UIImage 时,我会根据大小增加内存。
以下是我在将 mat 转换为 uiimage 之前正在执行的步骤:
cv::Mat undistorted = cv::Mat(cvSize(maxWidth,maxHeight), CV_8UC1);
cv::Mat original = [MatStructure convertUIImageToMat:adjustedImage];
cv::warpPerspective(original, undistorted, cv::getPerspectiveTransform(src, dst), cvSize(maxWidth, maxHeight));
original.release();
adjustedImage = [MatStructure convertMatToUIImage:undistorted];
undistorted.release();
在我将垫子转换为 uiimage 时出现问题,内存增加到 400 mb,并且在每个周期都增加。
+ (UIImage *) convertMatToUIImage: (cv::Mat) cvMat {
NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize() * cvMat.total()];
CGColorSpaceRef colorSpace;
if (cvMat.elemSize() == 1) {
colorSpace = CGColorSpaceCreateDeviceGray();
} else {
colorSpace = CGColorSpaceCreateDeviceRGB();
}
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef) data);
CGBitmapInfo bmInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
CGImageRef imageRef = CGImageCreate(cvMat.cols, // width
cvMat.rows, // height
8, // bits per component
8 * cvMat.elemSize(), // bits per pixel
cvMat.step.p[0], // bytesPerRow
colorSpace, // colorspace
bmInfo, // bitmap info
provider, // CGDataProviderRef
NULL, // decode
false, // should interpolate
kCGRenderingIntentDefault // intent
);
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
cvMat.release(); // this line is optional.
return image;
}
我见过许多类似的代码,但每个示例都与此示例相同。
我相信问题存在于 (__bridge CFDataRef)
并且 ARC
无法清理这些数据,如果我尝试 CFRelease((__bridge CFDataRef)data)
将会发生崩溃,因为程序将搜索分配的内存并且它已经被释放所以它会 运行 崩溃。
我正在使用 openCV3
并尝试了他们的方法 MatToUIImage
但问题仍然存在,在 leaks
分析器上根本没有泄漏,内存中最昂贵的任务是 convertMatToUIImage
.
我整天都在阅读有关它的内容,但实际上还找不到任何有用的解决方案。
目前我在 swift 3.0
上工作,它继承了 class XXX
,它使用 objC
class 裁剪某些东西,而不是 return 到 UIImage
以及。在 deinit
中,我将继承的 class 属性 分配为零,但问题仍然存在 exsists.Also 我认为 dataWithBytes
正在复制内存,就像我有 16MB
在创建 NSData
后开始时它将是 32MB
..
如果您能就此问题提出有用的线索,我将很乐意阅读所有线索。感谢帮助
在解决这个问题三天多之后,我不得不重写函数并且它 100% 有效,我已经在五种不同的设备上进行了测试。
CFRelease
、Free(
) 和 @autoreleasepool
对我一点帮助都没有,我实现了这个:
data = UIImageJPEGRepresentation([[UIImage alloc] initWithCGImage:imageRef], 0.2f); // because images are 30MB and up
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:@"MyFile.jpeg"];
[data writeToFile:appFile atomically:NO];
data = nil;
在这个解决方案之后一切正常。所以我抓取 UIImage
并转换为 NSData
,之后我们应该将它保存到本地目录,唯一剩下的就是从 directory
读取数据。希望这一主题有一天能对某人有所帮助。
在这里发布这个问题之前,我已经阅读了所有材料和上面的类似帖子,但我无法了解主要的 "idea" 发生了什么以及如何解决它,在 10 个类似问题中,大家正在用 @autoreleasepool
解决这个问题,在这种情况下我无法实现我的目标。因此,在将 cvMat 转换为 UIImage 时,我会根据大小增加内存。
以下是我在将 mat 转换为 uiimage 之前正在执行的步骤:
cv::Mat undistorted = cv::Mat(cvSize(maxWidth,maxHeight), CV_8UC1);
cv::Mat original = [MatStructure convertUIImageToMat:adjustedImage];
cv::warpPerspective(original, undistorted, cv::getPerspectiveTransform(src, dst), cvSize(maxWidth, maxHeight));
original.release();
adjustedImage = [MatStructure convertMatToUIImage:undistorted];
undistorted.release();
在我将垫子转换为 uiimage 时出现问题,内存增加到 400 mb,并且在每个周期都增加。
+ (UIImage *) convertMatToUIImage: (cv::Mat) cvMat {
NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize() * cvMat.total()];
CGColorSpaceRef colorSpace;
if (cvMat.elemSize() == 1) {
colorSpace = CGColorSpaceCreateDeviceGray();
} else {
colorSpace = CGColorSpaceCreateDeviceRGB();
}
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef) data);
CGBitmapInfo bmInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
CGImageRef imageRef = CGImageCreate(cvMat.cols, // width
cvMat.rows, // height
8, // bits per component
8 * cvMat.elemSize(), // bits per pixel
cvMat.step.p[0], // bytesPerRow
colorSpace, // colorspace
bmInfo, // bitmap info
provider, // CGDataProviderRef
NULL, // decode
false, // should interpolate
kCGRenderingIntentDefault // intent
);
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
cvMat.release(); // this line is optional.
return image;
}
我见过许多类似的代码,但每个示例都与此示例相同。
我相信问题存在于 (__bridge CFDataRef)
并且 ARC
无法清理这些数据,如果我尝试 CFRelease((__bridge CFDataRef)data)
将会发生崩溃,因为程序将搜索分配的内存并且它已经被释放所以它会 运行 崩溃。
我正在使用 openCV3
并尝试了他们的方法 MatToUIImage
但问题仍然存在,在 leaks
分析器上根本没有泄漏,内存中最昂贵的任务是 convertMatToUIImage
.
我整天都在阅读有关它的内容,但实际上还找不到任何有用的解决方案。
目前我在 swift 3.0
上工作,它继承了 class XXX
,它使用 objC
class 裁剪某些东西,而不是 return 到 UIImage
以及。在 deinit
中,我将继承的 class 属性 分配为零,但问题仍然存在 exsists.Also 我认为 dataWithBytes
正在复制内存,就像我有 16MB
在创建 NSData
后开始时它将是 32MB
..
如果您能就此问题提出有用的线索,我将很乐意阅读所有线索。感谢帮助
在解决这个问题三天多之后,我不得不重写函数并且它 100% 有效,我已经在五种不同的设备上进行了测试。
CFRelease
、Free(
) 和 @autoreleasepool
对我一点帮助都没有,我实现了这个:
data = UIImageJPEGRepresentation([[UIImage alloc] initWithCGImage:imageRef], 0.2f); // because images are 30MB and up
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:@"MyFile.jpeg"];
[data writeToFile:appFile atomically:NO];
data = nil;
在这个解决方案之后一切正常。所以我抓取 UIImage
并转换为 NSData
,之后我们应该将它保存到本地目录,唯一剩下的就是从 directory
读取数据。希望这一主题有一天能对某人有所帮助。