.03 2013
こんにちわ。Uedaです。
今回は初心に帰ってベクトルの内積と外積と正規化です。なんだかんだでよく使うと思うので、まとめておきます。
コード
Vector3d a = Vector3d::Random(3, 1);
Vector3d b = Vector3d::Random(3, 1);
NSLog(@"a: %f, %f, %f", a(0), a(1), a(2));
NSLog(@"b: %f, %f, %f", b(0), b(1), b(2));
double dot = a.dot(b);
NSLog(@"a・b = %f", dot);
Vector3d cross = a.cross(b);
NSLog(@"a×b = %f, %f, %f", cross(0), cross(1), cross(2));
結果
a: -0.999984, -0.736924, 0.511211
b: -0.082700, 0.065534, -0.562082
a・b = -0.252938
a×b = 0.380710, -0.604350, -0.126477
aの正規化: -0.744443, -0.548607, 0.380573
以上です。
.31 2013
こんにちわ。Uedaです。
OpenCVを使って、ORB特徴点で2枚の画像からどこが同じ特徴のところかを調べてみました。
UIImage *image1 = [UIImage imageNamed:@"IMG_0091.jpg"];
UIImage *image2 = [UIImage imageNamed:@"IMG_0092.jpg"];
Mat imageMat1 = [self cvMatFromUIImage:image1];
Mat imageMat2 = [self cvMatFromUIImage:image2];
Mat grayImage1, grayImage2;
cvtColor(imageMat1, grayImage1, CV_BGR2GRAY);
cvtColor(imageMat2, grayImage2, CV_BGR2GRAY);
OrbFeatureDetector detector(500);
OrbDescriptorExtractor extractor;
std::vector<:keypoint> keypoints1, keypoints2;
detector.detect(grayImage1, keypoints1);
detector.detect(grayImage2, keypoints2);
Mat descriptor1, descriptor2;
extractor.compute(grayImage1, keypoints1, descriptor1);
extractor.compute(grayImage2, keypoints2, descriptor2);
vector matches;
BFMatcher matcher(cv::NORM_HAMMING, true);
matcher.match(descriptor1, descriptor2, matches);
for (int i = 0; i < matches.size(); i++)
{
NSLog(@"%f", matches[i].distance);
if (matches[i].distance < 50.0)
{
KeyPoint p1 = keypoints1.at(matches[i].queryIdx);
cv::circle(imageMat1, cv::Point(p1.pt.x, p1.pt.y), 20, Scalar(255, 255, 0), -1);
KeyPoint p2 = keypoints2.at(matches[i].trainIdx);
cv::circle(imageMat2, cv::Point(p2.pt.x, p2.pt.y), 20, Scalar(255, 255, 0), -1);
}
}
[self.imageView1 setImage:[self UIImageFromCVMat:imageMat1]];
[self.imageView2 setImage:[self UIImageFromCVMat:imageMat2]];
結果
うーん...
以上です。
.30 2013
こんにちわ。Uedaです。
今回はEigenでオペレータ演算子を使った行列の計算の紹介です。
Matrix3d m1 = Matrix3d::Random(3, 3);
Matrix3d m2 = Matrix3d::Random(3, 3);
Matrix3d m3 = m1 + m2;
Matrix3d m4 = m1 * m2;
直感的に実装できるので便利です。
計算結果
2013-05-30 17:40:33.783 TestEigen[3396:c07]
-0.999984, -0.082700, -0.905911
-0.736924, 0.065534, 0.357729
0.511211, -0.562082, 0.358593
2013-05-30 17:40:33.785 TestEigen[3396:c07]
0.869386, 0.661931, 0.059400
-0.232996, -0.930856, 0.342299
0.038833, -0.893077, -0.984604
2013-05-30 17:40:33.786 TestEigen[3396:c07]
-0.130599, 0.579231, -0.846510
-0.969920, -0.865321, 0.700028
0.550043, -1.455158, -0.626011
2013-05-30 17:40:33.787 TestEigen[3396:c07]
-0.885282, 0.224109, 0.804256
-0.642049, -0.868276, -0.373563
0.589327, 0.541352, -0.515106
以上です。
.29 2013
こんにちわ。Uedaです。
前回, iphone側で動画像を取得して, それをOpenCVで扱える形に変換するところまで紹介しました。
今回はとりあえずORBを使って特徴点を表示してみました。
OrbFeatureDetector detector(500);
// OrbDescriptorExtractor *extractor;
std::vector<:keypoint> keypoints;
detector.detect(grayImage, keypoints);
for (int i = 0; i < keypoints.size(); i++)
{
KeyPoint p = keypoints.at(i);
cv::circle(imageMat, cv::Point(p.pt.x, p.pt.y), 1, Scalar(0, 255, 0), -1);
}
これでORB特徴点が表示されます。
今回は以上です。
.28 2013
こんにちわ。Uedaです。
今回はタイトル通り, ios上で動画像をOpenCVで解析するための準備をしてみました。
http://reiji1020.hatenablog.com/entry/2012/11/18/165804のサイト曰く, OpenCV2.4.2からFramework形式のものが既に準備されているので, 導入がすごく簡単になっています。
ライブラリにopencv2.frameworkを追加し, 以下のファイルUIViewControllerを実行すると, 動画像をOpenCVで画像処理・解析するためのMatの形式に変換することができます。
ヘッダファイル
@interface TestOpenCVViewController : UIViewController
{
IBOutlet UIImageView *cameraPreviewImageView;
AVCaptureSession* session;
}
@property(strong, nonatomic) AVCaptureSession *session;
@property(strong, nonatomic) UIImageView *cameraPreviewImageView;
@end
ソースファイル
using namespace cv;
@interface TestOpenCVViewController ()
@end
@implementation TestOpenCVViewController
@synthesize session;
@synthesize cameraPreviewImageView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"viewDidLoad");
// Do any additional setup after loading the view from its nib.
// ビデオキャプチャデバイスの取得
AVCaptureDevice* device;
device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// オートフォーカスモードを解消
if ([device isFocusPointOfInterestSupported] && [device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
NSError *error;
if ([device lockForConfiguration:&error]) {
[device setFocusMode:AVCaptureFocusModeAutoFocus];
[device unlockForConfiguration];
}
}
// デバイス入力の取得
AVCaptureDeviceInput* deviceInput;
deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:NULL];
// ビデオデータ出力の作成
NSMutableDictionary* settings;
AVCaptureVideoDataOutput* dataOutput;
settings = [NSMutableDictionary dictionary];
[settings setObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
dataOutput = [[AVCaptureVideoDataOutput alloc] init];
// [dataOutput autorelease];
dataOutput.videoSettings = settings;
[dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
// セッションの作成
self.session = [[AVCaptureSession alloc] init];
// 画質の制御
self.session.sessionPreset = AVCaptureSessionPreset640x480;
[self.session addInput:deviceInput];
[self.session addOutput:dataOutput];
// ステータスバーを隠す
[UIApplication sharedApplication].statusBarHidden = YES;
self.view.bounds = [UIScreen mainScreen].bounds;
// カメラの開始
[self.session startRunning];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/***** カメラの動作 *****/
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
// キャプチャしたフレームからCGImageを作成
UIImage *image = [self imageFromSampleBuffer:sampleBuffer];
cv::Mat imageMat = [self cvMatFromUIImage:image];
/* あとはimageMatをOpenCVで煮るなり焼くなり */
image = [self UIImageFromCVMat:imageMat];
cameraPreviewImageView.image = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationUp];
}
// サンプルバッファのデータからCGImageRefを生成する
- (UIImage *)imageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer
{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// ピクセルバッファのベースアドレスをロックする
CVPixelBufferLockBaseAddress(imageBuffer, 0);
// Get information of the image
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
// RGBの色空間
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef newContext = CGBitmapContextCreate(baseAddress,
width,
height,
8,
bytesPerRow,
colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGImageRef cgImage = CGBitmapContextCreateImage(newContext);
CGContextRelease(newContext);
CGColorSpaceRelease(colorSpace);
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
UIImage *image = [UIImage imageWithCGImage:cgImage scale:1.0 orientation:UIImageOrientationRight];
CGImageRelease(cgImage);
return image;
}
- (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;
}
- (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);
// 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
kCGImageAlphaNone|kCGBitmapByteOrderDefault,// 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;
}
あとはMat形式にした画像をOpenCVで用意されている様々な関数を使って煮るなり, 焼くなりすればOpenCVを堪能することができます。
今回は以上です。