例:
IplImage *img = cvCreateImage(cvSize(imageWidth, imageHeight),IPL_DEPTH_8U,3);
cv::Mat imgMat(imagewidth, imageHeight, CV_8UC3);
for (int j=0; j<imageHeight; j++){
for (int i=0; i<imageWidth; i++){
imgMat.data[j*imgMat.widthStep+i*imgMat.nChannels] = img->imageData[j*img->widthStep+i*nChannels]; // B
imgMat.data[j*imgMat.widthStep+i*imgMat.nChannels+1] = img->imageData[j*img->widthStep+i*nChannels+1]; // G
imgMat.data[j*imgMat.widthStep+i*imgMat.nChannels+2] = img->imageData[j*img->widthStep+i*nChannels+2]; // R
}
}
正常來說應該是這樣子把IplImage的資料複製到cvMat底下,但我經過了以上的code後,在把cvMat透過以下的方式轉到UIImage,卻發現顏色跑掉。
+(UIImage *)UIImageFromCVMat:(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);
bool alpha = cvMat.channels() == 4;
CGBitmapInfo bitMapInfo = (alpha ? kCGImageAlphaLast : kCGImageAlphaNone) | kCGBitmapByteOrderDefault;
// Creating CGImage from cv::Mat
CGImageRef imageRef = CGImageCreate(cvMat.cols, //width
cvMat.rows, //height
8, //bits per component
8 * cvMat.elemSize(), //bits per pixel
cvMat.step[0], //bytesPerRow
colorSpace, //colorspace
bitMapInfo, // bitmap info
provider, //CGDataProviderRef
NULL, //decode
false, //should interpolate
kCGRenderingIntentDefault //intent
);
// Getting UIImage from CGImage
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return finalImage;
}
所以我試著把BGR的位置對調,如下:
IplImage *img = cvCreateImage(cvSize(imageWidth, imageHeight),IPL_DEPTH_8U,3);
cv::Mat imgMat(imagewidth, imageHeight, CV_8UC3);
for (int j=0; j<imageHeight; j++){
for (int i=0; i<imageWidth; i++){
imgMat.data[j*imgMat.widthStep+i*imgMat.nChannels+2] = img->imageData[j*img->widthStep+i*nChannels]; // B
imgMat.data[j*imgMat.widthStep+i*imgMat.nChannels+1] = img->imageData[j*img->widthStep+i*nChannels+1]; // G
imgMat.data[j*imgMat.widthStep+i*imgMat.nChannels] = img->imageData[j*img->widthStep+i*nChannels+2]; // R
}
}
是的! 可能是CvMat 轉UIImage時,把他看成RGB的排列方式轉了吧!?(不確定)
但使用上列方式,顏色就正常了。
最後在丟一些convert的code:
UIImage to CvMat:
+ (cv::Mat)cvMatFromUIImage:(UIImage *)image
{
CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
CGFloat cols = image.size.width;
CGFloat rows = image.size.height;
cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to data
cols, // Width of bitmap
rows, // Height of bitmap
8, // Bits per component
cvMat.step[0], // Bytes per row
colorSpace, // Colorspace
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault); // Bitmap info flags
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
CGContextRelease(contextRef);
// CGColorSpaceRelease(colorSpace);
return cvMat;
}
+ (cv::Mat)cvMatGrayFromUIImage:(UIImage *)image
{
cv::Mat cvMat = [UIImageCVMatConverter cvMatFromUIImage:image];
cv::Mat grayMat;
if (cvMat.channels() == 1) {
grayMat = cvMat;
} else{
grayMat = cv :: Mat(cvMat.rows,cvMat.cols, CV_8UC1);
cv::cvtColor(cvMat, grayMat, CV_BGR2GRAY);
}
return grayMat;
}
UIImage to IplImage:
// NOTE you SHOULD cvReleaseImage() for the return value when end of the code.
- (IplImage *)CreateIplImageFromUIImage:(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, 3);
cvCvtColor(iplimage, ret, CV_RGBA2BGR);
cvReleaseImage(&iplimage);
return ret;
}
IplImage to UIImage:
// NOTE You should convert color mode as RGB before passing to this function
- (UIImage *)UIImageFromIplImage:(IplImage *)image {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Allocating the buffer for CGImage
NSData *data =
[NSData dataWithBytes:image->imageData length:image->imageSize];
CGDataProviderRef provider =
CGDataProviderCreateWithCFData((CFDataRef)data);
// Creating CGImage from chunk of IplImage
CGImageRef imageRef = CGImageCreate(
image->width, image->height,
image->depth, image->depth * image->nChannels, image->widthStep,
colorSpace, kCGImageAlphaNone|kCGBitmapByteOrderDefault,
provider, NULL, false, kCGRenderingIntentDefault
);
// Getting UIImage from CGImage
UIImage *ret = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return ret;
}
ref:
https://sites.google.com/site/iprinceps/Home/iphone-1/converting-images-between-uiimage-and-iplimage
http://code.opencv.org/svn/gsoc2012/ios/trunk/ImageFilter/ImageFilter/UIImageCVMatConverter.mm
沒有留言:
張貼留言