2009年9月19日土曜日

QC: OpneCVでステレオ画像処理

追記(2009/9/21): &を直接書いて表示されてない問題があった.&として表示を修正.



Quartz Composerでやってみた.
結果


やったこと: OpenCV 1.1preについて
以前の記事に書いた通り
こちらからEnglish Versionの'OpenCV-Private-Framework-1.2.dmg'をdownload.
・インストールとしてOpenCV.frameworkフォルダを/Library/FrameworksフォルダへCopy.


やったこと:プロジェクトの用意
・XcodeにてApplication Plug-inのQuartz Composer Plug-inプロジェクトを選択

・プロジェクトに既存のフレームワークとして‘/Library/Frameworks/OpenCV.framework’を追加
・プロジェクトの情報(インスペクタ)でアーキテクチャを‘32-bit Universal’, 有効なアーキテクチャを‘i386’にする.
・参考:以前の記事


やったこと:コード
FindStereoCorrespondenceBMPlugIn.h
#import <Quartz/Quartz.h>
#import <OpenCV/cv.h>

@interface FindStereoCorrespondenceBMPlugIn : QCPlugIn
{
}

@property(assign) id<QCPlugInInputImageSource> inputLeftSourceImage;
@property(assign) id<QCPlugInInputImageSource> inputRightSourceImage;
@property(assign) id<QCPlugInOutputImageProvider> outputResultImage;

@end
@interface FindStereoCorrespondenceBMPlugIn (Func)
- (IplImage *)grayImageWihtSourceImage:(id)image;
- (IplImage *)iplImageWihtImage:(id<QCPlugInInputImageSource>)image;
@end


FindStereoCorrespondenceBMPlugIn.m
#import <OpenGL/CGLMacro.h>

#import "FindStereoCorrespondenceBMPlugIn.h"
#import "OutputImageProvider.h"

#define kQCPlugIn_Name @"FindStereoCorrespondenceBM"
#define kQCPlugIn_Description @"FindStereoCorrespondenceBM description"

@implementation FindStereoCorrespondenceBMPlugIn
@dynamic inputRightSourceImage;
@dynamic inputLeftSourceImage;
@dynamic outputResultImage;

…略…

- (BOOL) execute:(id<QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary*)arguments
{
id<QCPlugInInputImageSource> imageLeft, imageRight;
self.outputResultImage = nil;

if(imageLeft= self.inputLeftSourceImage) {
if(![imageLeft lockBufferRepresentationWithPixelFormat:QCPlugInPixelFormatBGRA8
colorSpace:[imageLeft imageColorSpace]
forBounds:[imageLeft imageBounds]]) {
return NO;
}
if(imageRight= self.inputRightSourceImage) {
if(![imageRight lockBufferRepresentationWithPixelFormat:QCPlugInPixelFormatBGRA8
colorSpace:[imageRight imageColorSpace]
forBounds:[imageRight imageBounds]]) {
return NO;
}



IplImage *image_left= [self grayImageWihtSourceImage:imageLeft];
IplImage *image_right= [self grayImageWihtSourceImage:imageRight];
CvSize size = cvGetSize(image_left);
CvMat *disparity= cvCreateMat(size.height, size.width, CV_16S);
CvStereoBMState *state= cvCreateStereoBMState(CV_STEREO_BM_BASIC, 16);
cvFindStereoCorrespondenceBM(image_left, image_right, disparity, state);
CvMat *disparity_8U= cvCreateMat(size.height, size.width, CV_8U);
cvConvertScale(disparity, disparity_8U, 1, 0);

IplImage *disparity_visual= cvCreateImage(size, IPL_DEPTH_8U, 4);
int i, j;
int w= size.width;
int h= size.height;
for(i= 0;i<h;i++) {
for(j= 0;j<w;j++) {
unsigned char c= disparity_8U->data.ptr[i*w+j];
disparity_visual->imageData[(i*w+j)*4 + 0]= c;
disparity_visual->imageData[(i*w+j)*4 + 1]= c;
disparity_visual->imageData[(i*w+j)*4 + 2]= c;
disparity_visual->imageData[(i*w+j)*4 + 3]= 255;
}
}

cvReleaseMat(&disparity_8U);
cvReleaseStereoBMState(&state);
cvReleaseMat(&disparity);
cvReleaseImage(&image_right);
cvReleaseImage(&image_left);

OutputImageProvider *provider = [[OutputImageProvider alloc] initWithIplImage:disparity_visual
pixelFormat:QCPlugInPixelFormatBGRA8
colorSpaceRef:[imageLeft imageColorSpace]];
if(provider == nil)
return NO;
self.outputResultImage = provider;
[provider release];


[imageRight unlockBufferRepresentation];
}

[imageLeft unlockBufferRepresentation];
}
return YES;
}

…略…

@end
@implementation FindStereoCorrespondenceBMPlugIn (Func)
- (IplImage *)grayImageWihtSourceImage:(id)image
{
IplImage *src_img= [self iplImageWihtImage:image];
IplImage *src_gray = cvCreateImage (cvGetSize(src_img), IPL_DEPTH_8U, 1);
cvCvtColor (src_img, src_gray, CV_BGRA2GRAY);
return src_gray;
}
- (IplImage *)iplImageWihtImage:(id)image
{
char *q= (char *)[image bufferBaseAddress];
IplImage *iplImage = calloc(1, sizeof(IplImage));

iplImage->nSize= sizeof(IplImage);
iplImage->ID= 0;
iplImage->nChannels= 4;
iplImage->depth= IPL_DEPTH_8U;
iplImage->dataOrder= 0;
iplImage->origin= 0;
iplImage->width= [image bufferPixelsWide];
iplImage->height= [image bufferPixelsHigh];
iplImage->roi= NULL;
iplImage->maskROI= NULL;
iplImage->imageData= q;
iplImage->widthStep= [image bufferBytesPerRow];
iplImage->imageDataOrigin= q;

return iplImage;
}

@end


OutputImageProvider.h
#import <Cocoa/Cocoa.h>
#import <OpenCV/cv.h>

@interface OutputImageProvider : NSObject <QCPlugInOutputImageProvider>
{
IplImage *_iplImage;
void *_baseAddress;
NSUInteger _rowBytes;
NSString *_format;
NSRect _bounds;
CGColorSpaceRef _cgColorSpaceRef;
}
- (id)initWithIplImage:(IplImage *)image
pixelFormat:(NSString *)format
colorSpaceRef:(CGColorSpaceRef)cgColorSpaceRef;
@end



OutputImageProvider.m
#import "OutputImageProvider.h"

@implementation OutputImageProvider
- (id)initWithIplImage:(IplImage *)image
pixelFormat:(NSString *)format
colorSpaceRef:(CGColorSpaceRef)cgColorSpaceRef
{
if(self = [super init]) {
_iplImage= image;
_baseAddress= _iplImage->imageData;
_rowBytes= _iplImage->widthStep;
_format= [format retain];
_bounds= NSMakeRect(0, 0, _iplImage->width, _iplImage->height);
_cgColorSpaceRef= cgColorSpaceRef;
}
return self;
}
- (void) dealloc
{
if (_iplImage) {
cvReleaseImage(&_iplImage);
}
[_format release];
[super dealloc];
}
- (NSRect) imageBounds
{
return _bounds;
}
- (CGColorSpaceRef) imageColorSpace
{
return _cgColorSpaceRef;
}
- (NSArray*) supportedBufferPixelFormats
{
return [NSArray arrayWithObjects: _format,
nil];
}
- (BOOL) renderToBuffer:(void*)baseAddress
withBytesPerRow:(NSUInteger)rowBytes
pixelFormat:(NSString*)format
forBounds:(NSRect)bounds
{
memcpy(baseAddress, _baseAddress, _rowBytes*_bounds.size.height);
return YES;
}
@end



実行について
OpenCVの入手に依存するがここにある方法だと32bitモードでないと動かない.Quartz Composerのインスペクタで32ビットモードで開くにチェックを入れておく(後日なにかの問題になるかもしれないから入れた事を忘れないようにw).

LeftとRightを反対にしてみるとまったく面影がないw.


参考
こちらの記事こちらの記事リファレンス
感謝!

0 件のコメント: