opencv ios透明图片加载不透明
Posted
技术标签:
【中文标题】opencv ios透明图片加载不透明【英文标题】:opencv ios transparent image loaded without transparency 【发布时间】:2013-06-06 15:04:35 【问题描述】:我正在开发一个使用一些 opencv 功能(删除背景、边缘检测等)的 ios 应用程序
除其他外,我加载透明图像 (png)。由于某种原因,当我加载图像时,opencv 决定忽略一些透明区域,同时尊重其他区域。我可以通过将我的半透明 UIImage 转换为 IplImage 然后返回 UIImage(不对 iplimage 进行任何操作)并将这两个图像保存到本地文件来看到这一点。
这是我用于将 UIImage 转换为 IplImage 并向后转换的代码:
- (IplImage *)CreateIplImageFromUIImageWithTransparency:(UIImage *)image
// Getting CGImage from UIImage
CGImageRef imageRef = image.CGImage;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Creating temporal IplImage for drawing
IplImage *iplimage = cvCreateImage(
cvSize(image.size.width,image.size.height), IPL_DEPTH_8U, 4
);
// Creating CGContext for temporal IplImage
CGContextRef contextRef = CGBitmapContextCreate(
iplimage->imageData, iplimage->width, iplimage->height,
iplimage->depth, iplimage->widthStep,
colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault
);
// Drawing CGImage to CGContext
CGContextDrawImage(
contextRef,
CGRectMake(0, 0, image.size.width, image.size.height),
imageRef
);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);
// Creating result IplImage
IplImage *ret = cvCreateImage(cvGetSize(iplimage), IPL_DEPTH_8U, 4);
cvCvtColor(iplimage, ret, CV_RGBA2BGRA);
cvReleaseImage(&iplimage);
return ret;
- (UIImage *)UIImageFromIplImage:(IplImage *)image
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSData *data = [NSData dataWithBytes:image->imageData length:image->imageSize];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
CGImageRef imageRef = CGImageCreate(image->width, image->height,
image->depth, image->depth * image->nChannels, image->widthStep,
colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast ,
provider, NULL, false, kCGRenderingIntentDefault);
UIImage *ret = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return ret;
什么可能导致这种行为?
谢谢
【问题讨论】:
【参考方案1】:此代码对我有用。我从here修改了代码
从 UIImage 读取
-(cv::Mat)CVMat
CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage);
CGFloat cols = self.size.width;
CGFloat rows = self.size.height;
cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to backing data
cols, // Width of bitmap
rows, // Height of bitmap
8, // Bits per component
cvMat.step[0], // Bytes per row
colorSpace, // Colorspace
//kCGImageAlphaNoneSkipLast |
kCGImageAlphaPremultipliedLast |
kCGBitmapByteOrderDefault); // Bitmap info flags
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), self.CGImage);
CGContextRelease(contextRef);
return cvMat;
转换回 UIImage:
+ (UIImage *)imageWithCVMat:(const cv::Mat&)cvMat
return [[UIImage alloc] initWithCVMat:cvMat];
- (id)initWithCVMat:(const 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);
CGImageRef imageRef = CGImageCreate(cvMat.cols, // Width
cvMat.rows, // Height
8, // Bits per component
8 * cvMat.elemSize(), // Bits per pixel
cvMat.step[0], // Bytes per row
colorSpace, // Colorspace
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault, // Bitmap info flags
provider, // CGDataProviderRef
NULL, // Decode
false, // Should interpolate
kCGRenderingIntentDefault); // Intent
self = [self initWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return self;
【讨论】:
【参考方案2】:我认为这就是问题所在:
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
你不应该在这里使用 RGBA 吗?
【讨论】:
好吧,没有 CGColorSpaceCreateDeviceRGBA 支持 :( 只有 CGColorSpaceCreateDeviceRGB 抱歉,应该先检查一下。我检查了我以前的项目,发现我一直在其中使用 kCGImageAlphaNone。 CGBitmapContextCreate 和 kCGImageAlphaPremultipliedLast 应该创建正确的上下文。只是几个问题,因为我也想找到解决方案: 1. 如果某些透明区域被忽略,是否会因为通道的顺序出现错误而发生? 2. CGImageCreate()中为什么要使用kCGImageAlphaLast? 其实我不是 100% 确定,虽然我知道如果我使用 kCGImageAlphaPremultipliedLast 而不是 kCGImageAlphaLast 我得到以下错误:IplImage *ret = cvLoadImage("file.png", CV_LOAD_IMAGE_UNCHANGED);
查看文档:http://opencv.willowgarage.com/documentation/c/reading_and_writing_images_and_video.html
CV_LOAD_IMAGE_UNCHANGED 加载的图像将按原样加载,而默认参数将您的 img 转换为 RGB
【讨论】:
我不能,这不是保存在本地目录中的文件。相反,它保存在程序的内存中。将图像保存到文件并再次加载将非常低效(我确实需要在此方法中达到一定程度的效率)。 哼...不好意思,我没注意,也许你应该看看:***.com/questions/6861891/… 是的,如果您在我的 CreateIplImageFromUIImageWithTransparency 中注意到,我会按照该问题中的建议调用 kCGImageAlphaPremultipliedLast以上是关于opencv ios透明图片加载不透明的主要内容,如果未能解决你的问题,请参考以下文章
怎么把加载bmp图片的picture control 变成透明